From 1ad44ed461aafb61ac046353c021e1926fd2398b Mon Sep 17 00:00:00 2001 From: Siyuan Date: Fri, 10 Oct 2025 14:42:23 +0000 Subject: [PATCH] allow to toggle dhcp client via touchscreen --- display.go | 7 + internal/native/eez/jetkvm.eez-project | 854 ++++++++++++++++++++++++- internal/native/eez/src/ui/actions.c | 20 + internal/native/eez/src/ui/actions.h | 1 + internal/native/eez/src/ui/screens.c | 237 +++++++ internal/native/eez/src/ui/screens.h | 14 + native.go | 2 + network.go | 11 + 8 files changed, 1144 insertions(+), 2 deletions(-) diff --git a/display.go b/display.go index cab87ff3..220c8055 100644 --- a/display.go +++ b/display.go @@ -43,6 +43,13 @@ func updateDisplay() { nativeInstance.UpdateLabelIfChanged("home_info_mac_addr", networkManager.MACString()) + switch config.NetworkConfig.DHCPClient.String { + case "jetdhcpc": + nativeInstance.UpdateLabelIfChanged("dhcp_client_change_label", "Change to udhcpc") + case "udhcpc": + nativeInstance.UpdateLabelIfChanged("dhcp_client_change_label", "Change to JetKVM") + } + if usbState == "configured" { nativeInstance.UpdateLabelIfChanged("usb_status_label", "Connected") _, _ = nativeInstance.UIObjAddState("usb_status_label", "LV_STATE_CHECKED") diff --git a/internal/native/eez/jetkvm.eez-project b/internal/native/eez/jetkvm.eez-project index 0ad49e76..5d09cb25 100644 --- a/internal/native/eez/jetkvm.eez-project +++ b/internal/native/eez/jetkvm.eez-project @@ -48,7 +48,7 @@ { "objID": "58af3ebb-96b3-494c-f4e3-9c23852e3e42", "fileName": "actions.c", - "template": "#include \"actions.h\"\n#include \"screens.h\"\n#include \n#include \n#include \"ui.h\"\n#include \"vars.h\"\n\nint handle_gesture_screen_switch(lv_event_t *e, lv_dir_t direction, int screenId) {\n lv_event_code_t event_code = lv_event_get_code(e);\n if (event_code != LV_EVENT_GESTURE) {\n return 0;\n }\n\n if (lv_indev_get_gesture_dir(lv_indev_get_act()) != direction) {\n return 0;\n }\n lv_indev_wait_release(lv_indev_get_act());\n loadScreen(screenId);\n return 1;\n}\n\nvoid handle_gesture_main_screen_switch(lv_event_t *e, lv_dir_t direction) {\n const char *main_screen = get_var_main_screen();\n if (strcmp(main_screen, \"home_screen\") == 0) { \n loadScreen(SCREEN_ID_HOME_SCREEN);\n } else if (strcmp(main_screen, \"no_network_screen\") == 0) {\n loadScreen(SCREEN_ID_NO_NETWORK_SCREEN);\n }\n}\n\nvoid action_switch_to_menu(lv_event_t *e) {\n loadScreen(SCREEN_ID_MENU_SCREEN);\n}\n\nvoid action_switch_to_advanced_menu(lv_event_t *e) {\n loadScreen(SCREEN_ID_MENU_ADVANCED_SCREEN);\n}\n\nvoid action_switch_to_status(lv_event_t *e) {\n loadScreen(SCREEN_ID_STATUS_SCREEN);\n}\n\nvoid action_switch_to_about(lv_event_t *e) {\n loadScreen(SCREEN_ID_ABOUT_SCREEN);\n}\n\nvoid action_switch_to_reset_config(lv_event_t *e) {\n loadScreen(SCREEN_ID_RESET_CONFIG_SCREEN);\n}\n\nvoid action_switch_to_reboot(lv_event_t *e) {\n loadScreen(SCREEN_ID_REBOOT_SCREEN);\n}\n\nvoid action_menu_screen_gesture(lv_event_t * e) {\n handle_gesture_main_screen_switch(e, LV_DIR_RIGHT);\n}\n\nvoid action_menu_advanced_screen_gesture(lv_event_t * e) {\n handle_gesture_screen_switch(e, LV_DIR_RIGHT, SCREEN_ID_MENU_SCREEN);\n}\n\nvoid action_reset_config_screen_gesture(lv_event_t * e) {\n handle_gesture_screen_switch(e, LV_DIR_RIGHT, SCREEN_ID_MENU_SCREEN);\n}\n\nvoid action_home_screen_gesture(lv_event_t * e) {\n handle_gesture_screen_switch(e, LV_DIR_LEFT, SCREEN_ID_MENU_SCREEN);\n}\n\nvoid action_about_screen_gesture(lv_event_t * e) {\n handle_gesture_screen_switch(e, LV_DIR_RIGHT, SCREEN_ID_MENU_SCREEN);\n}\n\n// user_data doesn't seem to be working, so we use a global variable here\nstatic uint32_t t_reset_config;\nstatic uint32_t t_reboot;\n\nstatic bool b_reboot = false;\nstatic bool b_reset_config = false;\n\nstatic bool b_reboot_lock = false;\nstatic bool b_reset_config_lock = false;\n\nconst int RESET_CONFIG_HOLD_TIME = 10;\nconst int REBOOT_HOLD_TIME = 5;\n\ntypedef struct {\n uint32_t *start_time;\n bool *completed;\n bool *lock;\n int hold_time_seconds;\n const char *rpc_method;\n lv_obj_t *button_obj;\n lv_obj_t *spinner_obj;\n lv_obj_t *label_obj;\n const char *default_text;\n} hold_action_config_t;\n\nstatic void handle_hold_action(lv_event_t *e, hold_action_config_t *config) {\n lv_event_code_t event_code = lv_event_get_code(e);\n \n if (event_code == LV_EVENT_PRESSED) {\n *(config->start_time) = lv_tick_get();\n }\n else if (event_code == LV_EVENT_PRESSING) {\n int remaining_time = config->hold_time_seconds * 1000 - lv_tick_elaps(*(config->start_time));\n if (remaining_time <= 0) {\n if (*(config->lock)) {\n return;\n }\n if (config->button_obj && config->spinner_obj) {\n lv_obj_add_flag(config->button_obj, LV_OBJ_FLAG_HIDDEN);\n lv_obj_clear_flag(config->spinner_obj, LV_OBJ_FLAG_HIDDEN);\n }\n ui_call_rpc_handler(config->rpc_method, NULL);\n *(config->lock) = true;\n *(config->completed) = true;\n } else {\n *(config->completed) = false;\n char buf[100];\n int remaining_time_seconds = remaining_time / 1000;\n if (remaining_time_seconds <= 1) {\n remaining_time_seconds = 1;\n }\n sprintf(buf, \"Press and hold for\\n%d seconds\", remaining_time_seconds);\n lv_label_set_text(config->label_obj, buf);\n }\n } else if (event_code == LV_EVENT_RELEASED) {\n if (*(config->lock)) {\n *(config->lock) = false;\n }\n\n if (!*(config->completed)) {\n lv_label_set_text(config->label_obj, config->default_text);\n }\n }\n}\n\nvoid action_reset_config(lv_event_t * e) {\n hold_action_config_t config = {\n .start_time = &t_reset_config,\n .completed = &b_reset_config,\n .lock = &b_reset_config_lock,\n .hold_time_seconds = RESET_CONFIG_HOLD_TIME,\n .rpc_method = \"resetConfig\",\n .button_obj = objects.reset_config_button,\n .spinner_obj = objects.reset_config_spinner,\n .label_obj = objects.reset_config_label,\n .default_text = \"Press and hold for\\n10 seconds\"\n };\n \n handle_hold_action(e, &config);\n}\n\nvoid action_reboot(lv_event_t * e) {\n hold_action_config_t config = {\n .start_time = &t_reboot,\n .completed = &b_reboot,\n .lock = &b_reboot_lock,\n .hold_time_seconds = REBOOT_HOLD_TIME,\n .rpc_method = \"reboot\",\n .button_obj = NULL, // No button/spinner for reboot\n .spinner_obj = NULL,\n .label_obj = objects.reboot_label,\n .default_text = \"Press and hold for\\n5 seconds\"\n };\n \n handle_hold_action(e, &config);\n}" + "template": "#include \"actions.h\"\n#include \"screens.h\"\n#include \n#include \n#include \"ui.h\"\n#include \"vars.h\"\n\nint handle_gesture_screen_switch(lv_event_t *e, lv_dir_t direction, int screenId) {\n lv_event_code_t event_code = lv_event_get_code(e);\n if (event_code != LV_EVENT_GESTURE) {\n return 0;\n }\n\n if (lv_indev_get_gesture_dir(lv_indev_get_act()) != direction) {\n return 0;\n }\n lv_indev_wait_release(lv_indev_get_act());\n loadScreen(screenId);\n return 1;\n}\n\nvoid handle_gesture_main_screen_switch(lv_event_t *e, lv_dir_t direction) {\n const char *main_screen = get_var_main_screen();\n if (strcmp(main_screen, \"home_screen\") == 0) { \n loadScreen(SCREEN_ID_HOME_SCREEN);\n } else if (strcmp(main_screen, \"no_network_screen\") == 0) {\n loadScreen(SCREEN_ID_NO_NETWORK_SCREEN);\n }\n}\n\nvoid action_switch_to_menu(lv_event_t *e) {\n loadScreen(SCREEN_ID_MENU_SCREEN);\n}\n\nvoid action_switch_to_advanced_menu(lv_event_t *e) {\n loadScreen(SCREEN_ID_MENU_ADVANCED_SCREEN);\n}\n\nvoid action_switch_to_status(lv_event_t *e) {\n loadScreen(SCREEN_ID_STATUS_SCREEN);\n}\n\nvoid action_switch_to_about(lv_event_t *e) {\n loadScreen(SCREEN_ID_ABOUT_SCREEN);\n}\n\nvoid action_switch_to_reset_config(lv_event_t *e) {\n loadScreen(SCREEN_ID_RESET_CONFIG_SCREEN);\n}\n\nvoid action_switch_to_reboot(lv_event_t *e) {\n loadScreen(SCREEN_ID_REBOOT_SCREEN);\n}\n\nvoid action_menu_screen_gesture(lv_event_t * e) {\n handle_gesture_main_screen_switch(e, LV_DIR_RIGHT);\n}\n\nvoid action_menu_advanced_screen_gesture(lv_event_t * e) {\n handle_gesture_screen_switch(e, LV_DIR_RIGHT, SCREEN_ID_MENU_SCREEN);\n}\n\nvoid action_reset_config_screen_gesture(lv_event_t * e) {\n handle_gesture_screen_switch(e, LV_DIR_RIGHT, SCREEN_ID_MENU_SCREEN);\n}\n\nvoid action_home_screen_gesture(lv_event_t * e) {\n handle_gesture_screen_switch(e, LV_DIR_LEFT, SCREEN_ID_MENU_SCREEN);\n}\n\nvoid action_about_screen_gesture(lv_event_t * e) {\n handle_gesture_screen_switch(e, LV_DIR_RIGHT, SCREEN_ID_MENU_SCREEN);\n}\n\n// user_data doesn't seem to be working, so we use a global variable here\nstatic uint32_t t_reset_config;\nstatic uint32_t t_reboot;\nstatic uint32_t t_dhcpc;\n\nstatic bool b_reboot = false;\nstatic bool b_reset_config = false;\nstatic bool b_dhcpc = false;\n\nstatic bool b_reboot_lock = false;\nstatic bool b_reset_config_lock = false;\nstatic bool b_dhcpc_lock = false;\n\nconst int RESET_CONFIG_HOLD_TIME = 10;\nconst int REBOOT_HOLD_TIME = 5;\nconst int DHCPC_HOLD_TIME = 5;\n\ntypedef struct {\n uint32_t *start_time;\n bool *completed;\n bool *lock;\n int hold_time_seconds;\n const char *rpc_method;\n lv_obj_t *button_obj;\n lv_obj_t *spinner_obj;\n lv_obj_t *label_obj;\n const char *default_text;\n} hold_action_config_t;\n\nstatic void handle_hold_action(lv_event_t *e, hold_action_config_t *config) {\n lv_event_code_t event_code = lv_event_get_code(e);\n \n if (event_code == LV_EVENT_PRESSED) {\n *(config->start_time) = lv_tick_get();\n }\n else if (event_code == LV_EVENT_PRESSING) {\n int remaining_time = config->hold_time_seconds * 1000 - lv_tick_elaps(*(config->start_time));\n if (remaining_time <= 0) {\n if (*(config->lock)) {\n return;\n }\n if (config->button_obj && config->spinner_obj) {\n lv_obj_add_flag(config->button_obj, LV_OBJ_FLAG_HIDDEN);\n lv_obj_clear_flag(config->spinner_obj, LV_OBJ_FLAG_HIDDEN);\n }\n ui_call_rpc_handler(config->rpc_method, NULL);\n *(config->lock) = true;\n *(config->completed) = true;\n } else {\n *(config->completed) = false;\n char buf[100];\n int remaining_time_seconds = remaining_time / 1000;\n if (remaining_time_seconds <= 1) {\n remaining_time_seconds = 1;\n }\n sprintf(buf, \"Press and hold for\\n%d seconds\", remaining_time_seconds);\n lv_label_set_text(config->label_obj, buf);\n }\n } else if (event_code == LV_EVENT_RELEASED) {\n if (*(config->lock)) {\n *(config->lock) = false;\n }\n\n if (!*(config->completed)) {\n lv_label_set_text(config->label_obj, config->default_text);\n }\n }\n}\n\nvoid action_reset_config(lv_event_t * e) {\n hold_action_config_t config = {\n .start_time = &t_reset_config,\n .completed = &b_reset_config,\n .lock = &b_reset_config_lock,\n .hold_time_seconds = RESET_CONFIG_HOLD_TIME,\n .rpc_method = \"resetConfig\",\n .button_obj = objects.reset_config_button,\n .spinner_obj = objects.reset_config_spinner,\n .label_obj = objects.reset_config_label,\n .default_text = \"Press and hold for\\n10 seconds\"\n };\n \n handle_hold_action(e, &config);\n}\n\nvoid action_dhcpc(lv_event_t * e) {\n hold_action_config_t config = {\n .start_time = &t_dhcpc,\n .completed = &b_dhcpc,\n .lock = &b_dhcpc_lock,\n .hold_time_seconds = DHCPC_HOLD_TIME,\n .rpc_method = \"toggleDHCPClient\",\n .button_obj = NULL, // No button/spinner for reboot\n .spinner_obj = NULL,\n .label_obj = objects.dhcpc_label,\n .default_text = \"Press and hold for\\n5 seconds\"\n };\n \n handle_hold_action(e, &config);\n}\n\nvoid action_reboot(lv_event_t * e) {\n hold_action_config_t config = {\n .start_time = &t_reboot,\n .completed = &b_reboot,\n .lock = &b_reboot_lock,\n .hold_time_seconds = REBOOT_HOLD_TIME,\n .rpc_method = \"reboot\",\n .button_obj = NULL, // No button/spinner for reboot\n .spinner_obj = NULL,\n .label_obj = objects.reboot_label,\n .default_text = \"Press and hold for\\n5 seconds\"\n };\n \n handle_hold_action(e, &config);\n}" }, { "objID": "1dbd1b7e-7270-47f0-ee02-e80bdae287cf", @@ -273,6 +273,14 @@ "localVariables": [], "userProperties": [], "name": "SwitchToReboot" + }, + { + "objID": "3efa8142-0c2d-4b63-e75e-8ff57d132f5e", + "components": [], + "connectionLines": [], + "localVariables": [], + "userProperties": [], + "name": "DHCPC" } ], "userPages": [ @@ -3038,7 +3046,7 @@ "left": 0, "top": 0, "width": 100, - "height": 108, + "height": 166, "customInputs": [], "customOutputs": [], "style": { @@ -3336,6 +3344,104 @@ "group": "", "groupIndex": 0 }, + { + "objID": "3a5c0243-2877-4e9f-f23f-8022eeb772cd", + "type": "LVGLButtonWidget", + "left": 0, + "top": 0, + "width": 100, + "height": 50, + "customInputs": [], + "customOutputs": [], + "style": { + "objID": "31a3a5fe-d9e6-42ba-dffe-916f7d247168", + "useStyle": "default", + "conditionalStyles": [], + "childStyles": [] + }, + "locked": false, + "hiddenInEditor": false, + "timeline": [], + "eventHandlers": [ + { + "objID": "6a730d9a-c11d-4800-9833-f4d7b5a8a40d", + "eventName": "PRESSED", + "handlerType": "action", + "action": "SwitchToReboot", + "userData": 0 + } + ], + "identifier": "MenuBtnDHCPClient", + "leftUnit": "px", + "topUnit": "px", + "widthUnit": "%", + "heightUnit": "px", + "children": [ + { + "objID": "929d0861-7f4d-43f0-ce71-07fafb9ac719", + "type": "LVGLLabelWidget", + "left": 0, + "top": 0, + "width": 115, + "height": 20, + "customInputs": [], + "customOutputs": [], + "style": { + "objID": "704ef898-9f7c-43a8-ab11-c48b4af1e864", + "useStyle": "default", + "conditionalStyles": [], + "childStyles": [] + }, + "hiddenInEditor": false, + "timeline": [], + "eventHandlers": [], + "identifier": "", + "leftUnit": "px", + "topUnit": "px", + "widthUnit": "content", + "heightUnit": "content", + "children": [], + "widgetFlags": "CLICK_FOCUSABLE|GESTURE_BUBBLE|PRESS_LOCK|SCROLLABLE|SCROLL_CHAIN_HOR|SCROLL_CHAIN_VER|SCROLL_ELASTIC|SCROLL_MOMENTUM|SCROLL_WITH_ARROW|SNAPPABLE", + "hiddenFlagType": "literal", + "clickableFlagType": "literal", + "flagScrollbarMode": "", + "flagScrollDirection": "", + "scrollSnapX": "", + "scrollSnapY": "", + "checkedStateType": "literal", + "disabledStateType": "literal", + "states": "", + "useStyle": "MenuButtonLabel", + "localStyles": { + "objID": "5144f730-9924-47ca-bfb9-c02449de88be" + }, + "group": "", + "groupIndex": 0, + "text": "DHCP Client", + "textType": "literal", + "longMode": "WRAP", + "recolor": false + } + ], + "widgetFlags": "CLICK_FOCUSABLE|GESTURE_BUBBLE|PRESS_LOCK|SCROLL_CHAIN_HOR|SCROLL_CHAIN_VER|SCROLL_ELASTIC|SCROLL_MOMENTUM|SCROLL_ON_FOCUS|SCROLL_WITH_ARROW", + "hiddenFlag": false, + "hiddenFlagType": "literal", + "clickableFlag": true, + "clickableFlagType": "literal", + "flagScrollbarMode": "", + "flagScrollDirection": "", + "scrollSnapX": "", + "scrollSnapY": "", + "checkedStateType": "literal", + "disabledStateType": "literal", + "states": "", + "useStyle": "MenuButton", + "localStyles": { + "objID": "2d17602a-58eb-4a21-9aff-c1f1a7d09bfe" + }, + "group": "", + "groupIndex": 0 + }, { "objID": "1077686a-8cc3-44f5-f09e-000d5e0ef066", "type": "LVGLButtonWidget", @@ -8094,6 +8200,750 @@ "isUsedAsUserWidget": false, "createAtStart": true, "deleteOnScreenUnload": false + }, + { + "objID": "606eb261-e593-41e5-d86b-6487f467eea9", + "components": [ + { + "objID": "61b8bea9-a21d-4498-c0ed-14a4bd2a4858", + "type": "LVGLScreenWidget", + "left": 0, + "top": 0, + "width": 300, + "height": 240, + "customInputs": [], + "customOutputs": [], + "style": { + "objID": "938e0598-29de-4807-b736-8bcda0e9d417", + "useStyle": "default", + "conditionalStyles": [], + "childStyles": [] + }, + "timeline": [], + "eventHandlers": [ + { + "objID": "eeb49a6a-3cfe-4372-8706-b6734bbbceec", + "eventName": "GESTURE", + "handlerType": "action", + "action": "AboutScreenGesture", + "userData": 0 + } + ], + "leftUnit": "px", + "topUnit": "px", + "widthUnit": "px", + "heightUnit": "px", + "children": [ + { + "objID": "0f3e9d37-63ca-45b0-bd92-13fbf1ecf63f", + "type": "LVGLContainerWidget", + "left": 0, + "top": 0, + "width": 100, + "height": 100, + "customInputs": [], + "customOutputs": [], + "style": { + "objID": "e2636ce4-0cbd-4646-a676-26efc3cd3bed", + "useStyle": "default", + "conditionalStyles": [], + "childStyles": [] + }, + "timeline": [], + "eventHandlers": [], + "identifier": "", + "leftUnit": "px", + "topUnit": "px", + "widthUnit": "%", + "heightUnit": "%", + "children": [ + { + "objID": "fd6de3f1-da9d-4bf9-c789-ba4b4b7e6f98", + "type": "LVGLContainerWidget", + "left": 0, + "top": 0, + "width": 100, + "height": 32, + "customInputs": [], + "customOutputs": [], + "style": { + "objID": "6138f675-e136-435f-890d-5841a1faa447", + "useStyle": "default", + "conditionalStyles": [], + "childStyles": [] + }, + "timeline": [], + "eventHandlers": [], + "identifier": "DHCPClientHeader", + "leftUnit": "px", + "topUnit": "px", + "widthUnit": "%", + "heightUnit": "content", + "children": [ + { + "objID": "edd2bee0-2bfa-4db7-930c-2445899a3d7f", + "type": "LVGLButtonWidget", + "left": 0, + "top": 0, + "width": 32, + "height": 32, + "customInputs": [], + "customOutputs": [], + "style": { + "objID": "34a0ab43-9134-405d-d30b-a60c487a18a0", + "useStyle": "default", + "conditionalStyles": [], + "childStyles": [] + }, + "timeline": [], + "eventHandlers": [ + { + "objID": "cfbd687f-29e2-4c6a-de27-f8d10dceeeb8", + "eventName": "CLICKED", + "handlerType": "action", + "action": "SwitchToMenu", + "userData": 0 + } + ], + "leftUnit": "px", + "topUnit": "px", + "widthUnit": "px", + "heightUnit": "px", + "children": [ + { + "objID": "9d5fdeca-711b-4c7d-e9ce-35f506095573", + "type": "LVGLImageWidget", + "left": -1, + "top": 2, + "width": 8, + "height": 12, + "customInputs": [], + "customOutputs": [], + "style": { + "objID": "3dbbc13f-48bc-47d3-cfa1-865309068b4b", + "useStyle": "default", + "conditionalStyles": [], + "childStyles": [] + }, + "timeline": [], + "eventHandlers": [], + "leftUnit": "px", + "topUnit": "px", + "widthUnit": "content", + "heightUnit": "content", + "children": [], + "widgetFlags": "ADV_HITTEST|CLICK_FOCUSABLE|GESTURE_BUBBLE|PRESS_LOCK|SCROLLABLE|SCROLL_CHAIN_HOR|SCROLL_CHAIN_VER|SCROLL_ELASTIC|SCROLL_MOMENTUM|SCROLL_WITH_ARROW|SNAPPABLE", + "hiddenFlagType": "literal", + "clickableFlagType": "literal", + "flagScrollbarMode": "", + "flagScrollDirection": "", + "scrollSnapX": "", + "scrollSnapY": "", + "checkedStateType": "literal", + "disabledStateType": "literal", + "states": "", + "localStyles": { + "objID": "3864abb7-e6ea-4188-cc23-99583e940dde" + }, + "group": "", + "groupIndex": 0, + "image": "back-caret", + "setPivot": false, + "pivotX": 0, + "pivotY": 0, + "zoom": 256, + "angle": 0, + "innerAlign": "CENTER" + } + ], + "widgetFlags": "CLICK_FOCUSABLE|GESTURE_BUBBLE|PRESS_LOCK|SCROLL_CHAIN_HOR|SCROLL_CHAIN_VER|SCROLL_ELASTIC|SCROLL_MOMENTUM|SCROLL_ON_FOCUS|SCROLL_WITH_ARROW|SNAPPABLE", + "hiddenFlagType": "literal", + "clickableFlag": true, + "clickableFlagType": "literal", + "flagScrollbarMode": "", + "flagScrollDirection": "", + "scrollSnapX": "", + "scrollSnapY": "", + "checkedStateType": "literal", + "disabledStateType": "literal", + "states": "", + "useStyle": "BackButton", + "localStyles": { + "objID": "04d66c1f-9518-4905-bd8f-25f99bb40708" + }, + "group": "", + "groupIndex": 0 + }, + { + "objID": "bde5dd77-e61f-4398-f76c-b32d204a1532", + "type": "LVGLLabelWidget", + "left": 0, + "top": 0, + "width": 116, + "height": 20, + "customInputs": [], + "customOutputs": [], + "style": { + "objID": "6cacf93f-877f-46b2-cc3a-85d25ed6725c", + "useStyle": "default", + "conditionalStyles": [], + "childStyles": [] + }, + "timeline": [], + "eventHandlers": [], + "identifier": "", + "leftUnit": "%", + "topUnit": "%", + "widthUnit": "content", + "heightUnit": "content", + "children": [], + "widgetFlags": "CLICK_FOCUSABLE|GESTURE_BUBBLE|PRESS_LOCK|SCROLLABLE|SCROLL_CHAIN_HOR|SCROLL_CHAIN_VER|SCROLL_ELASTIC|SCROLL_MOMENTUM|SCROLL_WITH_ARROW|SNAPPABLE", + "hiddenFlagType": "literal", + "clickableFlagType": "literal", + "checkedStateType": "literal", + "disabledStateType": "literal", + "states": "", + "useStyle": "HeaderLink", + "localStyles": { + "objID": "0ac01432-b282-41c4-b119-316fe81ad79b" + }, + "groupIndex": 0, + "text": "Reset Config", + "textType": "literal", + "longMode": "WRAP", + "recolor": false + } + ], + "widgetFlags": "CLICK_FOCUSABLE|GESTURE_BUBBLE|PRESS_LOCK|SCROLLABLE|SCROLL_CHAIN_HOR|SCROLL_CHAIN_VER|SCROLL_ELASTIC|SCROLL_MOMENTUM|SCROLL_WITH_ARROW|SNAPPABLE", + "hiddenFlagType": "literal", + "clickableFlag": true, + "clickableFlagType": "literal", + "flagScrollbarMode": "", + "flagScrollDirection": "", + "scrollSnapX": "", + "scrollSnapY": "", + "checkedStateType": "literal", + "disabledStateType": "literal", + "states": "", + "useStyle": "FlowRowSpaceBetween", + "localStyles": { + "objID": "318d6e6f-47fc-43b2-d552-78044e89013b", + "definition": { + "MAIN": { + "DEFAULT": { + "pad_right": 4 + } + } + } + }, + "group": "", + "groupIndex": 0 + }, + { + "objID": "be2e4477-a5c6-4fbf-b6ae-41781ba8beb3", + "type": "LVGLContainerWidget", + "left": 0, + "top": 0, + "width": 100, + "height": 80, + "customInputs": [], + "customOutputs": [], + "style": { + "objID": "32002f2f-ef5d-4cb2-861b-64e6d5a7d579", + "useStyle": "default", + "conditionalStyles": [], + "childStyles": [] + }, + "timeline": [], + "eventHandlers": [], + "identifier": "DHCPClientContainer", + "leftUnit": "px", + "topUnit": "px", + "widthUnit": "%", + "heightUnit": "%", + "children": [ + { + "objID": "b54678c4-4a2c-4cb3-f69f-1f5c2af56871", + "type": "LVGLContainerWidget", + "left": 0, + "top": 0, + "width": 100, + "height": 118, + "customInputs": [], + "customOutputs": [], + "style": { + "objID": "e2990e43-732a-4333-fe6b-2ebce8595dbe", + "useStyle": "default", + "conditionalStyles": [], + "childStyles": [] + }, + "timeline": [], + "eventHandlers": [], + "leftUnit": "px", + "topUnit": "px", + "widthUnit": "%", + "heightUnit": "content", + "children": [ + { + "objID": "1eac7e05-d4ef-4f1d-fb76-6d5ed568080c", + "type": "LVGLContainerWidget", + "left": 0, + "top": 0, + "width": 100, + "height": 60, + "customInputs": [], + "customOutputs": [], + "style": { + "objID": "bfe31228-f83e-4e4d-cc0b-a54b11ae977d", + "useStyle": "default", + "conditionalStyles": [], + "childStyles": [] + }, + "timeline": [], + "eventHandlers": [], + "identifier": "DHCPClientLabelContainer", + "leftUnit": "px", + "topUnit": "px", + "widthUnit": "%", + "heightUnit": "content", + "children": [ + { + "objID": "6bc2314a-818b-4dda-bd0d-14fc9e95e335", + "type": "LVGLLabelWidget", + "left": 0, + "top": 0, + "width": 100, + "height": 40, + "customInputs": [], + "customOutputs": [], + "style": { + "objID": "cddebe4d-3ea2-48c6-cd6e-6e9fb0b9b542", + "useStyle": "default", + "conditionalStyles": [], + "childStyles": [] + }, + "timeline": [], + "eventHandlers": [], + "identifier": "DHCPC_Label", + "leftUnit": "px", + "topUnit": "px", + "widthUnit": "%", + "heightUnit": "content", + "children": [], + "widgetFlags": "CLICK_FOCUSABLE|GESTURE_BUBBLE|PRESS_LOCK|SCROLLABLE|SCROLL_CHAIN_HOR|SCROLL_CHAIN_VER|SCROLL_ELASTIC|SCROLL_MOMENTUM|SCROLL_WITH_ARROW|SNAPPABLE", + "hiddenFlagType": "literal", + "clickableFlagType": "literal", + "flagScrollbarMode": "", + "flagScrollDirection": "", + "scrollSnapX": "", + "scrollSnapY": "", + "checkedStateType": "literal", + "disabledStateType": "literal", + "states": "", + "useStyle": "InfoContentLabel", + "localStyles": { + "objID": "120b38c1-a71d-4d16-9716-75f3bb8b6e1e", + "definition": { + "MAIN": { + "DEFAULT": { + "text_font": "FontBook20" + } + } + } + }, + "group": "", + "groupIndex": 0, + "text": "Press and hold for\n10 seconds", + "textType": "literal", + "longMode": "WRAP", + "recolor": false, + "previewValue": "0.0.1" + } + ], + "widgetFlags": "CLICK_FOCUSABLE|GESTURE_BUBBLE|PRESS_LOCK|SCROLL_CHAIN_HOR|SCROLL_CHAIN_VER|SCROLL_ELASTIC|SCROLL_MOMENTUM|SCROLL_WITH_ARROW|SNAPPABLE", + "hiddenFlagType": "literal", + "clickableFlag": true, + "clickableFlagType": "literal", + "flagScrollbarMode": "", + "flagScrollDirection": "", + "scrollSnapX": "", + "scrollSnapY": "", + "checkedStateType": "literal", + "disabledStateType": "literal", + "states": "", + "useStyle": "FlexColumnStart", + "localStyles": { + "objID": "49877fd7-7428-4aa9-de03-7dcfcd6e9c3e", + "definition": { + "MAIN": { + "DEFAULT": { + "pad_right": 10, + "pad_left": 10, + "pad_top": 10, + "pad_bottom": 10 + } + } + } + }, + "group": "", + "groupIndex": 0 + }, + { + "objID": "080e4506-6708-4853-fe18-6fa783466f89", + "type": "LVGLContainerWidget", + "left": 0, + "top": 0, + "width": 100, + "height": 80, + "customInputs": [], + "customOutputs": [], + "style": { + "objID": "433da4ef-fa5a-4d0e-9646-7e0cfb5ca8a1", + "useStyle": "default", + "conditionalStyles": [], + "childStyles": [] + }, + "hiddenInEditor": false, + "timeline": [], + "eventHandlers": [], + "identifier": "DHCPClientSpinner", + "leftUnit": "px", + "topUnit": "px", + "widthUnit": "%", + "heightUnit": "content", + "children": [ + { + "objID": "9ac3d644-13f9-4d1e-c5df-d30f77e060c9", + "type": "LVGLSpinnerWidget", + "left": 0, + "top": 0, + "width": 80, + "height": 80, + "customInputs": [], + "customOutputs": [], + "style": { + "objID": "eecd876c-0d54-40b5-80c9-35b5fed54d49", + "useStyle": "default", + "conditionalStyles": [], + "childStyles": [] + }, + "timeline": [], + "eventHandlers": [], + "leftUnit": "px", + "topUnit": "px", + "widthUnit": "px", + "heightUnit": "px", + "children": [], + "widgetFlags": "CLICK_FOCUSABLE|GESTURE_BUBBLE|PRESS_LOCK|SCROLL_ELASTIC|SCROLL_MOMENTUM|SCROLL_WITH_ARROW|SNAPPABLE", + "hiddenFlagType": "literal", + "clickableFlagType": "literal", + "flagScrollbarMode": "", + "flagScrollDirection": "", + "scrollSnapX": "", + "scrollSnapY": "", + "checkedStateType": "literal", + "disabledStateType": "literal", + "states": "", + "localStyles": { + "objID": "3b02891a-1c25-4bb9-c452-992e29e1b522" + }, + "group": "", + "groupIndex": 0 + } + ], + "widgetFlags": "CLICK_FOCUSABLE|GESTURE_BUBBLE|PRESS_LOCK|SCROLL_CHAIN_HOR|SCROLL_CHAIN_VER|SCROLL_ELASTIC|SCROLL_MOMENTUM|SCROLL_WITH_ARROW|SNAPPABLE", + "hiddenFlag": true, + "hiddenFlagType": "literal", + "clickableFlag": false, + "clickableFlagType": "literal", + "flagScrollbarMode": "", + "flagScrollDirection": "", + "scrollSnapX": "", + "scrollSnapY": "", + "checkedStateType": "literal", + "disabledStateType": "literal", + "states": "", + "useStyle": "FlexColumnStart", + "localStyles": { + "objID": "0261577f-97e3-4b4b-b761-cbb127842798", + "definition": { + "MAIN": { + "DEFAULT": { + "flex_main_place": "CENTER", + "flex_cross_place": "CENTER", + "flex_track_place": "CENTER" + } + } + } + }, + "group": "", + "groupIndex": 0 + }, + { + "objID": "3cd2081b-7f47-44da-ad46-0fec4d6c13af", + "type": "LVGLContainerWidget", + "left": 0, + "top": 0, + "width": 100, + "height": 50, + "customInputs": [], + "customOutputs": [], + "style": { + "objID": "96ae878d-571b-4be0-e408-ba24a005a7c7", + "useStyle": "default", + "conditionalStyles": [], + "childStyles": [] + }, + "hiddenInEditor": false, + "timeline": [], + "eventHandlers": [], + "identifier": "DHCPClientButton", + "leftUnit": "px", + "topUnit": "px", + "widthUnit": "%", + "heightUnit": "content", + "children": [ + { + "objID": "ca25a750-c474-4994-eb13-b2ea9abeb1f1", + "type": "LVGLButtonWidget", + "left": 0, + "top": 0, + "width": 100, + "height": 50, + "customInputs": [], + "customOutputs": [], + "style": { + "objID": "22a3e3ca-a02c-4e43-9b78-7de7d03a7879", + "useStyle": "default", + "conditionalStyles": [], + "childStyles": [] + }, + "hiddenInEditor": false, + "timeline": [], + "eventHandlers": [ + { + "objID": "71ed231c-9bc3-4f0f-81f0-bf83c082974c", + "eventName": "PRESSED", + "handlerType": "action", + "action": "DHCPC", + "userData": 0 + }, + { + "objID": "677825fd-50cd-4d46-ef8e-4b296fef7c76", + "eventName": "PRESSING", + "handlerType": "action", + "action": "DHCPC", + "userData": 0 + }, + { + "objID": "f25e6fa7-45de-4d97-d892-3411d07f2df6", + "eventName": "RELEASED", + "handlerType": "action", + "action": "DHCPC", + "userData": 0 + } + ], + "leftUnit": "px", + "topUnit": "px", + "widthUnit": "%", + "heightUnit": "px", + "children": [ + { + "objID": "9370968e-29f3-411e-8e6e-28874fb3cdd8", + "type": "LVGLLabelWidget", + "left": 0, + "top": 0, + "width": 129, + "height": 16, + "customInputs": [], + "customOutputs": [], + "style": { + "objID": "e81bebce-db31-4a4e-e0d1-2c48865b9e5c", + "useStyle": "default", + "conditionalStyles": [], + "childStyles": [] + }, + "hiddenInEditor": false, + "timeline": [], + "eventHandlers": [], + "identifier": "DHCPClientChangeLabel", + "leftUnit": "px", + "topUnit": "px", + "widthUnit": "content", + "heightUnit": "content", + "children": [], + "widgetFlags": "CLICK_FOCUSABLE|GESTURE_BUBBLE|PRESS_LOCK|SCROLLABLE|SCROLL_CHAIN_HOR|SCROLL_CHAIN_VER|SCROLL_ELASTIC|SCROLL_MOMENTUM|SCROLL_WITH_ARROW|SNAPPABLE", + "hiddenFlagType": "literal", + "clickableFlagType": "literal", + "flagScrollbarMode": "", + "flagScrollDirection": "", + "scrollSnapX": "", + "scrollSnapY": "", + "checkedStateType": "literal", + "disabledStateType": "literal", + "states": "", + "localStyles": { + "objID": "c7acc23d-631e-40ca-e8af-d73735a6b513", + "definition": { + "MAIN": { + "DEFAULT": { + "align": "CENTER", + "text_align": "LEFT" + } + } + } + }, + "group": "", + "groupIndex": 0, + "text": "Switch to udhcpc", + "textType": "literal", + "longMode": "WRAP", + "recolor": false + } + ], + "widgetFlags": "CLICK_FOCUSABLE|GESTURE_BUBBLE|PRESS_LOCK|SCROLL_CHAIN_HOR|SCROLL_CHAIN_VER|SCROLL_ELASTIC|SCROLL_MOMENTUM|SCROLL_ON_FOCUS|SCROLL_WITH_ARROW|SNAPPABLE", + "hiddenFlagType": "literal", + "clickableFlag": true, + "clickableFlagType": "literal", + "flagScrollbarMode": "", + "flagScrollDirection": "", + "scrollSnapX": "", + "scrollSnapY": "", + "checkedStateType": "literal", + "disabledStateType": "literal", + "states": "", + "useStyle": "", + "localStyles": { + "objID": "244a5188-9237-429c-ea0f-0892dffba39d", + "definition": { + "MAIN": { + "DEFAULT": { + "bg_color": "DC2626", + "text_align": "LEFT", + "pad_right": 13 + } + } + } + }, + "group": "", + "groupIndex": 0 + } + ], + "widgetFlags": "CLICK_FOCUSABLE|GESTURE_BUBBLE|PRESS_LOCK|SCROLL_CHAIN_HOR|SCROLL_CHAIN_VER|SCROLL_ELASTIC|SCROLL_MOMENTUM|SCROLL_WITH_ARROW|SNAPPABLE", + "hiddenFlagType": "literal", + "clickableFlag": true, + "clickableFlagType": "literal", + "flagScrollbarMode": "", + "flagScrollDirection": "", + "scrollSnapX": "", + "scrollSnapY": "", + "checkedStateType": "literal", + "disabledStateType": "literal", + "states": "", + "useStyle": "FlexColumnStart", + "localStyles": { + "objID": "98d255ea-498c-4bce-cbd9-5c58f4148905" + }, + "group": "", + "groupIndex": 0 + } + ], + "widgetFlags": "CLICK_FOCUSABLE|GESTURE_BUBBLE|PRESS_LOCK|SCROLL_CHAIN_HOR|SCROLL_CHAIN_VER|SCROLL_ELASTIC|SCROLL_MOMENTUM|SCROLL_WITH_ARROW|SNAPPABLE", + "hiddenFlagType": "literal", + "clickableFlag": true, + "clickableFlagType": "literal", + "flagScrollbarMode": "", + "flagScrollDirection": "", + "scrollSnapX": "", + "scrollSnapY": "", + "checkedStateType": "literal", + "disabledStateType": "literal", + "states": "", + "useStyle": "FlexColumnStart", + "localStyles": { + "objID": "ac0d8cb4-7113-4ad6-f9b2-6d24553c6558", + "definition": { + "MAIN": { + "DEFAULT": { + "pad_right": 10 + } + } + } + }, + "group": "", + "groupIndex": 0 + } + ], + "widgetFlags": "CLICK_FOCUSABLE|GESTURE_BUBBLE|PRESS_LOCK|SCROLL_CHAIN_VER|SNAPPABLE|SCROLL_ELASTIC|SCROLL_WITH_ARROW|SCROLL_MOMENTUM|SCROLL_CHAIN_HOR|SCROLLABLE", + "hiddenFlagType": "literal", + "clickableFlag": true, + "clickableFlagType": "literal", + "flagScrollbarMode": "auto", + "flagScrollDirection": "ver", + "scrollSnapX": "start", + "scrollSnapY": "", + "checkedStateType": "literal", + "disabledStateType": "literal", + "states": "", + "useStyle": "FlexColumnStart", + "localStyles": { + "objID": "b4f4b1a5-fe3d-4114-bb43-68d4a39ff3c2", + "definition": { + "MAIN": { + "DEFAULT": { + "pad_right": 4 + } + } + } + }, + "group": "", + "groupIndex": 0 + } + ], + "widgetFlags": "CLICK_FOCUSABLE|GESTURE_BUBBLE|PRESS_LOCK|SCROLL_CHAIN_HOR|SCROLL_CHAIN_VER|SCROLL_MOMENTUM|SCROLL_WITH_ARROW|SNAPPABLE|SCROLL_ELASTIC", + "hiddenFlagType": "literal", + "clickableFlag": true, + "clickableFlagType": "literal", + "flagScrollbarMode": "", + "flagScrollDirection": "", + "scrollSnapX": "", + "scrollSnapY": "", + "checkedStateType": "literal", + "disabledStateType": "literal", + "states": "", + "useStyle": "FlexStart", + "localStyles": { + "objID": "34c01609-fb79-4d5a-943a-a28e67b73adf" + }, + "group": "", + "groupIndex": 0 + } + ], + "widgetFlags": "CLICKABLE|PRESS_LOCK|CLICK_FOCUSABLE|GESTURE_BUBBLE|SNAPPABLE|SCROLLABLE|SCROLL_ELASTIC|SCROLL_MOMENTUM|SCROLL_CHAIN_HOR|SCROLL_CHAIN_VER", + "hiddenFlagType": "literal", + "clickableFlag": true, + "clickableFlagType": "literal", + "checkedStateType": "literal", + "disabledStateType": "literal", + "states": "", + "useStyle": "FlexScreenMenu", + "localStyles": { + "objID": "cd8e005a-54e3-4ed2-edfb-719d97a7ded8" + }, + "groupIndex": 0 + } + ], + "connectionLines": [], + "localVariables": [], + "userProperties": [], + "name": "SwitchDHCPClientScreen", + "left": 0, + "top": 0, + "width": 300, + "height": 240, + "isUsedAsUserWidget": false, + "createAtStart": true, + "deleteOnScreenUnload": false } ], "userWidgets": [], diff --git a/internal/native/eez/src/ui/actions.c b/internal/native/eez/src/ui/actions.c index 801b03da..135d8938 100644 --- a/internal/native/eez/src/ui/actions.c +++ b/internal/native/eez/src/ui/actions.c @@ -75,15 +75,19 @@ void action_about_screen_gesture(lv_event_t * e) { // user_data doesn't seem to be working, so we use a global variable here static uint32_t t_reset_config; static uint32_t t_reboot; +static uint32_t t_dhcpc; static bool b_reboot = false; static bool b_reset_config = false; +static bool b_dhcpc = false; static bool b_reboot_lock = false; static bool b_reset_config_lock = false; +static bool b_dhcpc_lock = false; const int RESET_CONFIG_HOLD_TIME = 10; const int REBOOT_HOLD_TIME = 5; +const int DHCPC_HOLD_TIME = 5; typedef struct { uint32_t *start_time; @@ -153,6 +157,22 @@ void action_reset_config(lv_event_t * e) { handle_hold_action(e, &config); } +void action_dhcpc(lv_event_t * e) { + hold_action_config_t config = { + .start_time = &t_dhcpc, + .completed = &b_dhcpc, + .lock = &b_dhcpc_lock, + .hold_time_seconds = DHCPC_HOLD_TIME, + .rpc_method = "toggleDHCPClient", + .button_obj = NULL, // No button/spinner for reboot + .spinner_obj = NULL, + .label_obj = objects.dhcpc_label, + .default_text = "Press and hold for\n5 seconds" + }; + + handle_hold_action(e, &config); +} + void action_reboot(lv_event_t * e) { hold_action_config_t config = { .start_time = &t_reboot, diff --git a/internal/native/eez/src/ui/actions.h b/internal/native/eez/src/ui/actions.h index f4a24e44..4ec4a807 100644 --- a/internal/native/eez/src/ui/actions.h +++ b/internal/native/eez/src/ui/actions.h @@ -24,6 +24,7 @@ extern void action_handle_common_press_event(lv_event_t * e); extern void action_reset_config(lv_event_t * e); extern void action_reboot(lv_event_t * e); extern void action_switch_to_reboot(lv_event_t * e); +extern void action_dhcpc(lv_event_t * e); #ifdef __cplusplus diff --git a/internal/native/eez/src/ui/screens.c b/internal/native/eez/src/ui/screens.c index dd5ad98c..566006f1 100644 --- a/internal/native/eez/src/ui/screens.c +++ b/internal/native/eez/src/ui/screens.c @@ -887,6 +887,26 @@ void create_screen_menu_advanced_screen() { } } } + { + // MenuBtnDHCPClient + lv_obj_t *obj = lv_button_create(parent_obj); + objects.menu_btn_dhcp_client = obj; + lv_obj_set_pos(obj, 0, 0); + lv_obj_set_size(obj, LV_PCT(100), 50); + lv_obj_add_event_cb(obj, action_switch_to_reboot, LV_EVENT_PRESSED, (void *)0); + lv_obj_clear_flag(obj, LV_OBJ_FLAG_SNAPPABLE); + add_style_menu_button(obj); + { + lv_obj_t *parent_obj = obj; + { + lv_obj_t *obj = lv_label_create(parent_obj); + lv_obj_set_pos(obj, 0, 0); + lv_obj_set_size(obj, LV_SIZE_CONTENT, LV_SIZE_CONTENT); + add_style_menu_button_label(obj); + lv_label_set_text(obj, "DHCP Client"); + } + } + } { // MenuBtnAdvancedResetConfig lv_obj_t *obj = lv_button_create(parent_obj); @@ -2197,6 +2217,221 @@ void create_screen_rebooting_screen() { void tick_screen_rebooting_screen() { } +void create_screen_switch_dhcp_client_screen() { + lv_obj_t *obj = lv_obj_create(0); + objects.switch_dhcp_client_screen = obj; + lv_obj_set_pos(obj, 0, 0); + lv_obj_set_size(obj, 300, 240); + lv_obj_add_event_cb(obj, action_about_screen_gesture, LV_EVENT_GESTURE, (void *)0); + add_style_flex_screen_menu(obj); + { + lv_obj_t *parent_obj = obj; + { + lv_obj_t *obj = lv_obj_create(parent_obj); + lv_obj_set_pos(obj, 0, 0); + lv_obj_set_size(obj, LV_PCT(100), LV_PCT(100)); + lv_obj_set_style_pad_left(obj, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_top(obj, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_right(obj, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_bottom(obj, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_bg_opa(obj, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_border_width(obj, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_radius(obj, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_clear_flag(obj, LV_OBJ_FLAG_SCROLLABLE); + add_style_flex_start(obj); + { + lv_obj_t *parent_obj = obj; + { + // DHCPClientHeader + lv_obj_t *obj = lv_obj_create(parent_obj); + objects.dhcp_client_header = obj; + lv_obj_set_pos(obj, 0, 0); + lv_obj_set_size(obj, LV_PCT(100), LV_SIZE_CONTENT); + lv_obj_set_style_pad_left(obj, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_top(obj, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_bottom(obj, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_bg_opa(obj, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_border_width(obj, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_radius(obj, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + add_style_flow_row_space_between(obj); + lv_obj_set_style_pad_right(obj, 4, LV_PART_MAIN | LV_STATE_DEFAULT); + { + lv_obj_t *parent_obj = obj; + { + lv_obj_t *obj = lv_button_create(parent_obj); + lv_obj_set_pos(obj, 0, 0); + lv_obj_set_size(obj, 32, 32); + lv_obj_add_event_cb(obj, action_switch_to_menu, LV_EVENT_CLICKED, (void *)0); + add_style_back_button(obj); + { + lv_obj_t *parent_obj = obj; + { + lv_obj_t *obj = lv_image_create(parent_obj); + lv_obj_set_pos(obj, -1, 2); + lv_obj_set_size(obj, LV_SIZE_CONTENT, LV_SIZE_CONTENT); + lv_image_set_src(obj, &img_back_caret); + } + } + } + { + lv_obj_t *obj = lv_label_create(parent_obj); + lv_obj_set_pos(obj, LV_PCT(0), LV_PCT(0)); + lv_obj_set_size(obj, LV_SIZE_CONTENT, LV_SIZE_CONTENT); + add_style_header_link(obj); + lv_label_set_text(obj, "Reset Config"); + } + } + } + { + // DHCPClientContainer + lv_obj_t *obj = lv_obj_create(parent_obj); + objects.dhcp_client_container = obj; + lv_obj_set_pos(obj, 0, 0); + lv_obj_set_size(obj, LV_PCT(100), LV_PCT(80)); + lv_obj_set_style_pad_left(obj, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_top(obj, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_bottom(obj, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_bg_opa(obj, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_border_width(obj, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_radius(obj, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_scrollbar_mode(obj, LV_SCROLLBAR_MODE_AUTO); + lv_obj_set_scroll_dir(obj, LV_DIR_VER); + lv_obj_set_scroll_snap_x(obj, LV_SCROLL_SNAP_START); + add_style_flex_column_start(obj); + lv_obj_set_style_pad_right(obj, 4, LV_PART_MAIN | LV_STATE_DEFAULT); + { + lv_obj_t *parent_obj = obj; + { + lv_obj_t *obj = lv_obj_create(parent_obj); + lv_obj_set_pos(obj, 0, 0); + lv_obj_set_size(obj, LV_PCT(100), LV_SIZE_CONTENT); + lv_obj_set_style_pad_left(obj, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_top(obj, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_bottom(obj, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_bg_opa(obj, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_border_width(obj, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_radius(obj, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_clear_flag(obj, LV_OBJ_FLAG_SCROLLABLE); + add_style_flex_column_start(obj); + lv_obj_set_style_pad_right(obj, 10, LV_PART_MAIN | LV_STATE_DEFAULT); + { + lv_obj_t *parent_obj = obj; + { + // DHCPClientLabelContainer + lv_obj_t *obj = lv_obj_create(parent_obj); + objects.dhcp_client_label_container = obj; + lv_obj_set_pos(obj, 0, 0); + lv_obj_set_size(obj, LV_PCT(100), LV_SIZE_CONTENT); + lv_obj_set_style_bg_opa(obj, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_border_width(obj, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_radius(obj, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_clear_flag(obj, LV_OBJ_FLAG_SCROLLABLE); + add_style_flex_column_start(obj); + lv_obj_set_style_pad_right(obj, 10, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_left(obj, 10, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_top(obj, 10, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_bottom(obj, 10, LV_PART_MAIN | LV_STATE_DEFAULT); + { + lv_obj_t *parent_obj = obj; + { + // DHCPC_Label + lv_obj_t *obj = lv_label_create(parent_obj); + objects.dhcpc_label = obj; + lv_obj_set_pos(obj, 0, 0); + lv_obj_set_size(obj, LV_PCT(100), LV_SIZE_CONTENT); + add_style_info_content_label(obj); + lv_obj_set_style_text_font(obj, &ui_font_font_book20, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_label_set_text(obj, "Press and hold for\n10 seconds"); + } + } + } + { + // DHCPClientSpinner + lv_obj_t *obj = lv_obj_create(parent_obj); + objects.dhcp_client_spinner = obj; + lv_obj_set_pos(obj, 0, 0); + lv_obj_set_size(obj, LV_PCT(100), LV_SIZE_CONTENT); + lv_obj_set_style_pad_left(obj, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_top(obj, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_right(obj, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_bottom(obj, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_bg_opa(obj, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_border_width(obj, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_radius(obj, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_add_flag(obj, LV_OBJ_FLAG_HIDDEN); + lv_obj_clear_flag(obj, LV_OBJ_FLAG_CLICKABLE|LV_OBJ_FLAG_SCROLLABLE); + add_style_flex_column_start(obj); + lv_obj_set_style_flex_main_place(obj, LV_FLEX_ALIGN_CENTER, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_flex_cross_place(obj, LV_FLEX_ALIGN_CENTER, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_flex_track_place(obj, LV_FLEX_ALIGN_CENTER, LV_PART_MAIN | LV_STATE_DEFAULT); + { + lv_obj_t *parent_obj = obj; + { + lv_obj_t *obj = lv_spinner_create(parent_obj); + lv_obj_set_pos(obj, 0, 0); + lv_obj_set_size(obj, 80, 80); + lv_spinner_set_anim_params(obj, 1000, 60); + } + } + } + { + // DHCPClientButton + lv_obj_t *obj = lv_obj_create(parent_obj); + objects.dhcp_client_button = obj; + lv_obj_set_pos(obj, 0, 0); + lv_obj_set_size(obj, LV_PCT(100), LV_SIZE_CONTENT); + lv_obj_set_style_pad_left(obj, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_top(obj, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_right(obj, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_bottom(obj, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_bg_opa(obj, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_border_width(obj, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_radius(obj, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_clear_flag(obj, LV_OBJ_FLAG_SCROLLABLE); + add_style_flex_column_start(obj); + { + lv_obj_t *parent_obj = obj; + { + lv_obj_t *obj = lv_button_create(parent_obj); + objects.obj2 = obj; + lv_obj_set_pos(obj, 0, 0); + lv_obj_set_size(obj, LV_PCT(100), 50); + lv_obj_add_event_cb(obj, action_dhcpc, LV_EVENT_PRESSED, (void *)0); + lv_obj_add_event_cb(obj, action_dhcpc, LV_EVENT_PRESSING, (void *)0); + lv_obj_add_event_cb(obj, action_dhcpc, LV_EVENT_RELEASED, (void *)0); + lv_obj_set_style_bg_color(obj, lv_color_hex(0xffdc2626), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_align(obj, LV_TEXT_ALIGN_LEFT, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_right(obj, 13, LV_PART_MAIN | LV_STATE_DEFAULT); + { + lv_obj_t *parent_obj = obj; + { + // DHCPClientChangeLabel + lv_obj_t *obj = lv_label_create(parent_obj); + objects.dhcp_client_change_label = obj; + lv_obj_set_pos(obj, 0, 0); + lv_obj_set_size(obj, LV_SIZE_CONTENT, LV_SIZE_CONTENT); + lv_obj_set_style_align(obj, LV_ALIGN_CENTER, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_align(obj, LV_TEXT_ALIGN_LEFT, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_label_set_text(obj, "Switch to udhcpc"); + } + } + } + } + } + } + } + } + } + } + } + } + + tick_screen_switch_dhcp_client_screen(); +} + +void tick_screen_switch_dhcp_client_screen() { +} + typedef void (*tick_screen_func_t)(); @@ -2212,6 +2447,7 @@ tick_screen_func_t tick_screen_funcs[] = { tick_screen_reset_config_screen, tick_screen_reboot_screen, tick_screen_rebooting_screen, + tick_screen_switch_dhcp_client_screen, }; void tick_screen(int screen_index) { tick_screen_funcs[screen_index](); @@ -2236,4 +2472,5 @@ void create_screens() { create_screen_reset_config_screen(); create_screen_reboot_screen(); create_screen_rebooting_screen(); + create_screen_switch_dhcp_client_screen(); } diff --git a/internal/native/eez/src/ui/screens.h b/internal/native/eez/src/ui/screens.h index f2d2fc92..d17f6abd 100644 --- a/internal/native/eez/src/ui/screens.h +++ b/internal/native/eez/src/ui/screens.h @@ -19,6 +19,7 @@ typedef struct _objects_t { lv_obj_t *reset_config_screen; lv_obj_t *reboot_screen; lv_obj_t *rebooting_screen; + lv_obj_t *switch_dhcp_client_screen; lv_obj_t *boot_logo; lv_obj_t *boot_screen_version; lv_obj_t *no_network_header_container; @@ -54,6 +55,7 @@ typedef struct _objects_t { lv_obj_t *menu_btn_advanced_developer_mode; lv_obj_t *menu_btn_advanced_usb_emulation; lv_obj_t *menu_btn_advanced_reboot; + lv_obj_t *menu_btn_dhcp_client; lv_obj_t *menu_btn_advanced_reset_config; lv_obj_t *menu_header_container_2; lv_obj_t *menu_items_container_2; @@ -101,6 +103,14 @@ typedef struct _objects_t { lv_obj_t *obj1; lv_obj_t *reboot_in_progress_logo; lv_obj_t *reboot_in_progress_label; + lv_obj_t *dhcp_client_header; + lv_obj_t *dhcp_client_container; + lv_obj_t *dhcp_client_label_container; + lv_obj_t *dhcpc_label; + lv_obj_t *dhcp_client_spinner; + lv_obj_t *dhcp_client_button; + lv_obj_t *obj2; + lv_obj_t *dhcp_client_change_label; } objects_t; extern objects_t objects; @@ -117,6 +127,7 @@ enum ScreensEnum { SCREEN_ID_RESET_CONFIG_SCREEN = 9, SCREEN_ID_REBOOT_SCREEN = 10, SCREEN_ID_REBOOTING_SCREEN = 11, + SCREEN_ID_SWITCH_DHCP_CLIENT_SCREEN = 12, }; void create_screen_boot_screen(); @@ -151,6 +162,9 @@ void tick_screen_reboot_screen(); void create_screen_rebooting_screen(); void tick_screen_rebooting_screen(); + +void create_screen_switch_dhcp_client_screen(); +void tick_screen_switch_dhcp_client_screen(); void tick_screen_by_id(enum ScreensEnum screenId); void tick_screen(int screen_index); diff --git a/native.go b/native.go index e8eea745..4268bf2c 100644 --- a/native.go +++ b/native.go @@ -43,6 +43,8 @@ func initNative(systemVersion *semver.Version, appVersion *semver.Version) { _ = rpcReboot(true) case "reboot": _ = rpcReboot(true) + case "toggleDHCPClient": + _ = rpcToggleDHCPClient() default: nativeLogger.Warn().Str("event", event).Msg("unknown rpc event received") } diff --git a/network.go b/network.go index 61350bd5..b4d3ad37 100644 --- a/network.go +++ b/network.go @@ -193,3 +193,14 @@ func rpcSetNetworkSettings(settings RpcNetworkSettings) (*RpcNetworkSettings, er func rpcRenewDHCPLease() error { return networkManager.RenewDHCPLease(NetIfName) } + +func rpcToggleDHCPClient() error { + switch config.NetworkConfig.DHCPClient.String { + case "jetdhcpc": + config.NetworkConfig.DHCPClient.String = "udhcpc" + case "udhcpc": + config.NetworkConfig.DHCPClient.String = "jetdhcpc" + } + + return rpcReboot(false) +}