Skip to content

Commit 98d5eb1

Browse files
committed
Embed system settings vars/GUI
- Add system-related vars to the embui initialization code - Predefined code for "settings' web-page - generic example changed to adopt predefined settings UI Signed-off-by: Emil Muratov <gpm@hotplug.ru>
1 parent 86dc340 commit 98d5eb1

14 files changed

+489
-313
lines changed

EmbUI/EmbUI.cpp

+30-3
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,11 @@
2727
#define GZ_HEADER 0x1F
2828
#endif
2929

30-
3130
#ifdef ESP32
3231
#define U_FS U_SPIFFS
3332
#endif
3433

34+
3535
EmbUI embui;
3636

3737
void section_main_frame(Interface *interf, JsonObject *data) {}
@@ -204,8 +204,9 @@ void notFound(AsyncWebServerRequest *request) {
204204
}
205205

206206
void EmbUI::begin(){
207-
load(); // try to load config from file
208-
create_parameters(); // use defaults for params missing in config
207+
load(); // try to load config from file
208+
create_sysvars(); // create system variables (if missing)
209+
create_parameters(); // weak function, creates user-defined variables
209210

210211
LOG(println, String(F("UI CONFIG: ")) + embui.deb());
211212
#ifdef ESP8266
@@ -422,6 +423,11 @@ void EmbUI::handle(){
422423
send_pub();
423424
}
424425

426+
/**
427+
* метод для установки коллбеков на системные события, типа:
428+
* - WiFi подключиля/отключился
429+
* - получено время от NTP
430+
*/
425431
void EmbUI::set_callback(CallBack set, CallBack action, callback_function_t callback){
426432

427433
switch (action){
@@ -456,3 +462,24 @@ uint8_t uploadProgress(size_t len, size_t total){
456462
}
457463
return progress;
458464
}
465+
466+
/**
467+
* call to create system-dependent variables,
468+
* both run-time and persistent
469+
*/
470+
void EmbUI::create_sysvars(){
471+
LOG(println, F("UI: Creating system vars"));
472+
var_create(FPSTR(P_hostname), ""); // device hostname (autogenerated on first-run)
473+
var_create(FPSTR(P_APonly), FPSTR(P_false)); // режим AP-only (только точка доступа), не трогать
474+
var_create(FPSTR(P_APpwd), ""); // пароль внутренней точки доступа
475+
// параметры подключения к MQTT
476+
var_create(FPSTR(P_m_host), ""); // MQTT server hostname
477+
var_create(FPSTR(P_m_port), ""); // MQTT port
478+
var_create(FPSTR(P_m_user), ""); // MQTT login
479+
var_create(FPSTR(P_m_pass), ""); // MQTT pass
480+
var_create(FPSTR(P_m_pref), embui.mc); // MQTT topic == use ESP MAC address
481+
var_create(FPSTR(P_m_tupd), ""); // интервал отправки данных по MQTT в секундах
482+
// date/time related vars
483+
var_create(FPSTR(P_TZSET), ""); // TimeZone/DST rule (empty value == GMT/no DST)
484+
var_create(FPSTR(P_userntp), ""); // Backup NTP server
485+
}

EmbUI/EmbUI.h

+15-4
Original file line numberDiff line numberDiff line change
@@ -255,12 +255,21 @@ class EmbUI
255255
*/
256256
void wifi_connect(const char *ssid=nullptr, const char *pwd=nullptr);
257257

258-
258+
/**
259+
* метод для установки коллбеков на системные события, типа:
260+
* - WiFi подключиля/отключился
261+
* - получено время от NTP
262+
*/
259263
void set_callback(CallBack set, CallBack action, callback_function_t callback=nullptr);
260264

261265

262266

263267
private:
268+
/**
269+
* call to create system-dependent variables,
270+
* both run-time and persistent
271+
*/
272+
void create_sysvars();
264273
//void led_handle(); // пока убираю
265274
void led_on();
266275
void led_off();
@@ -274,7 +283,9 @@ class EmbUI
274283
void mqtt_handle();
275284
void subscribeAll(bool isOnlyGetSet=true);
276285
void mqtt_reconnect();
277-
286+
287+
// WiFi-related
288+
Ticker embuischedw; // планировщик WiFi
278289
/**
279290
* устанавлием режим WiFi
280291
*/
@@ -295,8 +306,6 @@ class EmbUI
295306

296307
void connectToMqtt();
297308
void onMqttConnect();
298-
void setup_mDns();
299-
Ticker embuischedw; // планировщик WiFi
300309

301310
static void onMqttDisconnect(AsyncMqttClientDisconnectReason reason);
302311
static void onMqttSubscribe(uint16_t packetId, uint8_t qos);
@@ -316,6 +325,8 @@ class EmbUI
316325
callback_function_t _cb_STADisconnected = nullptr;
317326
callback_function_t _cb_STAGotIP = nullptr;
318327

328+
void setup_mDns();
329+
319330
#ifdef USE_SSDP
320331
void ssdp_begin() {
321332
String hn = param(FPSTR(P_hostname));

EmbUI/basicui.cpp

+243
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,243 @@
1+
#include "basicui.h"
2+
3+
/**
4+
* Define configuration variables and controls handlers
5+
*
6+
* Variables has literal names and are kept within json-configuration file on flash
7+
* Control handlers are bound by literal name with a particular method. This method is invoked
8+
* by manipulating controls
9+
*
10+
* this method owerrides weak definition in framework
11+
*
12+
*/
13+
void BasicUI::add_sections(){
14+
LOG(println, F("UI: Creating webui vars"));
15+
16+
// variable for UI language (specific to basicui translations)
17+
embui.var_create(FPSTR(P_LANGUAGE), String((uint8_t)lang));
18+
19+
/**
20+
* обработчики действий
21+
*/
22+
// вывод BasicUI секций
23+
embui.section_handle_add(FPSTR(T_SETTINGS), section_settings_frame); // generate "settings" UI section
24+
embui.section_handle_add(FPSTR(T_SH_NETW), block_settings_netw); // generate "network settings" UI section
25+
embui.section_handle_add(FPSTR(T_SH_TIME), block_settings_time); // generate "time settings" UI section
26+
//embui.section_handle_add(FPSTR(T_SH_OTHER), show_settings_other);
27+
28+
// обработка базовых настроек
29+
embui.section_handle_add(FPSTR(T_SET_WIFI), set_settings_wifi); // обработка настроек WiFi Client
30+
embui.section_handle_add(FPSTR(T_SET_WIFIAP), set_settings_wifiAP); // обработка настроек WiFi AP
31+
embui.section_handle_add(FPSTR(T_SET_MQTT), set_settings_mqtt); // обработка настроек MQTT
32+
embui.section_handle_add(FPSTR(T_SET_TIME), set_settings_time); // установки даты/времени
33+
embui.section_handle_add(FPSTR(P_LANGUAGE), set_language); // смена языка интерфейса
34+
35+
//embui.section_handle_add(FPSTR(T_004B), set_settings_other);
36+
}
37+
38+
/**
39+
* This code adds "Settings" section to the MENU
40+
* it is up to you to properly open/close Interface menu json_section
41+
*/
42+
void BasicUI::opt_setup(Interface *interf, JsonObject *data){
43+
if (!interf) return;
44+
interf->option(FPSTR(T_SETTINGS), FPSTR(T_DICT[lang][TD::D_SETTINGS])); // пункт меню "настройки"
45+
}
46+
47+
/**
48+
* формирование секции "настроек",
49+
* вызывается либо по выбору из "меню" либо при вызове из
50+
* других блоков/обработчиков
51+
*
52+
*/
53+
void BasicUI::section_settings_frame(Interface *interf, JsonObject *data){
54+
if (!interf) return;
55+
interf->json_frame_interface(""); // саму секцию целиком не обрабатываем
56+
57+
interf->json_section_main(FPSTR(T_SETTINGS), FPSTR(T_DICT[lang][TD::D_SETTINGS]));
58+
59+
interf->select(FPSTR(P_LANGUAGE), String(lang), String(FPSTR(T_DICT[lang][TD::D_LANG])), true);
60+
interf->option("0", "Rus");
61+
interf->option("1", "Eng");
62+
interf->json_section_end();
63+
64+
interf->spacer();
65+
66+
interf->button(FPSTR(T_SH_NETW), FPSTR(T_DICT[lang][TD::D_WIFI_MQTT])); // кнопка перехода в настройки сети
67+
interf->button(FPSTR(T_SH_TIME), FPSTR(T_DICT[lang][TD::D_Time])); // кнопка перехода в настройки времени
68+
69+
interf->spacer();
70+
block_settings_update(interf, data); // добавляем блок интерфейса "обновления ПО"
71+
72+
interf->json_section_end();
73+
interf->json_frame_flush();
74+
}
75+
76+
/**
77+
* BasicUI блок интерфейса настроек WiFi/MQTT
78+
*/
79+
void BasicUI::block_settings_netw(Interface *interf, JsonObject *data){
80+
if (!interf) return;
81+
interf->json_frame_interface();
82+
83+
// Headline
84+
interf->json_section_main(FPSTR(T_OPT_NETW), FPSTR(T_DICT[lang][TD::D_WIFI_MQTT]));
85+
86+
// форма настроек Wi-Fi Client
87+
interf->json_section_hidden(FPSTR(T_SET_WIFI), FPSTR(T_DICT[lang][TD::D_WiFiClient]));
88+
interf->spacer(FPSTR(T_DICT[lang][TD::D_WiFiClientOpts]));
89+
interf->text(FPSTR(P_hostname), FPSTR(T_DICT[lang][TD::D_Hostname]));
90+
interf->text(FPSTR(P_WCSSID), WiFi.SSID(), FPSTR(T_DICT[lang][TD::D_WiFiSSID]), false);
91+
interf->password(FPSTR(P_WCPASS), "", FPSTR(T_DICT[lang][TD::D_Password]));
92+
interf->button_submit(FPSTR(T_SET_WIFI), FPSTR(T_DICT[lang][TD::D_CONNECT]), FPSTR(P_GRAY));
93+
interf->json_section_end();
94+
95+
// форма настроек Wi-Fi AP
96+
interf->json_section_hidden(FPSTR(T_SET_WIFIAP), FPSTR(T_DICT[lang][TD::D_WiFiAP]));
97+
interf->text(FPSTR(P_hostname), FPSTR(T_DICT[lang][TD::D_Hostname]));
98+
interf->spacer(FPSTR(T_DICT[lang][TD::D_WiFiAPOpts]));
99+
interf->comment(FPSTR(T_DICT[lang][TD::D_MSG_APOnly]));
100+
interf->checkbox(FPSTR(P_APonly), FPSTR(T_DICT[lang][TD::D_APOnlyMode]));
101+
interf->password(FPSTR(P_APpwd), FPSTR(T_DICT[lang][TD::D_MSG_APProtect]));
102+
interf->button_submit(FPSTR(T_SET_WIFIAP), FPSTR(T_DICT[lang][TD::D_SAVE]), FPSTR(P_GRAY));
103+
interf->json_section_end();
104+
105+
// форма настроек MQTT
106+
interf->json_section_hidden(FPSTR(T_SET_MQTT), FPSTR(T_DICT[lang][TD::D_MQTT]));
107+
interf->text(FPSTR(P_m_host), FPSTR(T_DICT[lang][TD::D_MQTT_Host]));
108+
interf->number(FPSTR(P_m_port), FPSTR(T_DICT[lang][TD::D_MQTT_Port]));
109+
interf->text(FPSTR(P_m_user), FPSTR(T_DICT[lang][TD::D_User]));
110+
interf->text(FPSTR(P_m_pass), FPSTR(T_DICT[lang][TD::D_Password]));
111+
interf->text(FPSTR(P_m_pref), FPSTR(T_DICT[lang][TD::D_MQTT_Topic]));
112+
interf->number(FPSTR(P_m_tupd), FPSTR(T_DICT[lang][TD::D_MQTT_Interval]));
113+
interf->button_submit(FPSTR(T_SET_MQTT), FPSTR(T_DICT[lang][TD::D_CONNECT]), FPSTR(P_GRAY));
114+
interf->json_section_end();
115+
116+
interf->spacer();
117+
interf->button(FPSTR(T_SETTINGS), FPSTR(T_DICT[lang][TD::D_EXIT]));
118+
119+
interf->json_section_end();
120+
121+
interf->json_frame_flush();
122+
}
123+
124+
/**
125+
* BasicUI блок загрузки обновлений ПО
126+
*/
127+
void BasicUI::block_settings_update(Interface *interf, JsonObject *data){
128+
if (!interf) return;
129+
interf->json_section_hidden(FPSTR(T_DO_OTAUPD), FPSTR(T_DICT[lang][TD::D_Update]));
130+
interf->spacer(FPSTR(T_DICT[lang][TD::D_FWLOAD]));
131+
interf->file(FPSTR(T_DO_OTAUPD), FPSTR(T_DO_OTAUPD), FPSTR(T_DICT[lang][TD::D_UPLOAD]));
132+
}
133+
134+
/**
135+
* BasicUI блок настройки даты/времени
136+
*/
137+
void BasicUI::block_settings_time(Interface *interf, JsonObject *data){
138+
if (!interf) return;
139+
interf->json_frame_interface();
140+
141+
// Headline
142+
interf->json_section_main(FPSTR(T_SET_TIME), FPSTR(T_DICT[lang][TD::D_DATETIME]));
143+
144+
interf->comment(FPSTR(T_DICT[lang][TD::D_MSG_TZSet01])); // комментарий-описание секции
145+
interf->text(FPSTR(P_TZSET), FPSTR(T_DICT[lang][TD::D_MSG_TZONE]));
146+
interf->text(FPSTR(P_userntp), FPSTR(T_DICT[lang][TD::D_NTP_Secondary]));
147+
interf->text(FPSTR(P_DTIME), "", FPSTR(T_DICT[lang][TD::D_MSG_DATETIME]), false);
148+
interf->button_submit(FPSTR(T_SET_TIME), FPSTR(T_DICT[lang][TD::D_SAVE]), FPSTR(P_GRAY));
149+
150+
interf->spacer();
151+
interf->button(FPSTR(T_SETTINGS), FPSTR(T_DICT[lang][TD::D_EXIT]));
152+
153+
interf->json_section_end();
154+
interf->json_frame_flush();
155+
}
156+
157+
/**
158+
* Обработчик настроек WiFi в режиме клиента
159+
*/
160+
void BasicUI::set_settings_wifi(Interface *interf, JsonObject *data){
161+
if (!data) return;
162+
163+
SETPARAM(FPSTR(P_hostname)); // сохраняем hostname в конфиг
164+
165+
const char *ssid = (*data)[FPSTR(P_WCSSID)]; // переменные доступа в конфиге не храним
166+
const char *pwd = (*data)[FPSTR(P_WCPASS)]; // фреймворк хранит последнюю доступную точку самостоятельно
167+
168+
if(ssid){
169+
embui.wifi_connect(ssid, pwd);
170+
} else {
171+
LOG(println, F("UI WiFi: No SSID defined!"));
172+
}
173+
174+
section_settings_frame(interf, data); // переходим в раздел "настройки"
175+
}
176+
177+
/**
178+
* Обработчик настроек WiFi в режиме AP
179+
*/
180+
void BasicUI::set_settings_wifiAP(Interface *interf, JsonObject *data){
181+
if (!data) return;
182+
183+
SETPARAM(FPSTR(P_hostname)); // эти переменные будут сохранены в конфиг-файл
184+
SETPARAM(FPSTR(P_APonly));
185+
SETPARAM(FPSTR(P_APpwd));
186+
187+
embui.save();
188+
embui.wifi_connect(); // иницируем WiFi-подключение с новыми параметрами
189+
190+
section_settings_frame(interf, data); // переходим в раздел "настройки"
191+
}
192+
193+
/**
194+
* Обработчик настроек MQTT
195+
*/
196+
void BasicUI::set_settings_mqtt(Interface *interf, JsonObject *data){
197+
if (!data) return;
198+
// сохраняем настройки в конфиг
199+
SETPARAM(FPSTR(P_m_host));
200+
SETPARAM(FPSTR(P_m_port));
201+
SETPARAM(FPSTR(P_m_user));
202+
SETPARAM(FPSTR(P_m_pass));
203+
SETPARAM(FPSTR(P_m_pref));
204+
SETPARAM(FPSTR(P_m_tupd));
205+
//SETPARAM(FPSTR(P_m_tupd), some_mqtt_object.semqtt_int((*data)[FPSTR(P_m_tupd)]));
206+
207+
embui.save();
208+
209+
section_settings_frame(interf, data);
210+
}
211+
212+
/**
213+
* Обработчик настроек даты/времени
214+
*/
215+
void BasicUI::set_settings_time(Interface *interf, JsonObject *data){
216+
if (!data) return;
217+
218+
String datetime=(*data)[FPSTR(P_DTIME)];
219+
if (datetime.length())
220+
embui.timeProcessor.setTime(datetime);
221+
SETPARAM(FPSTR(P_TZSET), embui.timeProcessor.tzsetup((*data)[FPSTR(P_TZSET)]));
222+
SETPARAM(FPSTR(P_userntp), embui.timeProcessor.setcustomntp((*data)[FPSTR(P_userntp)]));
223+
224+
section_settings_frame(interf, data);
225+
}
226+
227+
void BasicUI::set_language(Interface *interf, JsonObject *data){
228+
if (!data) return;
229+
230+
//lang = (*data)[FPSTR(P_LANGUAGE)].as<unsigned char>();
231+
SETPARAM(FPSTR(P_LANGUAGE), lang = (*data)[FPSTR(P_LANGUAGE)].as<unsigned char>() );
232+
233+
section_settings_frame(interf, data);
234+
}
235+
236+
void BasicUI::embuistatus(Interface *interf){
237+
if (!interf) return;
238+
interf->json_frame_value();
239+
interf->value(F("pTime"), embui.timeProcessor.getFormattedShortTime(), true);
240+
interf->value(F("pMem"), String(ESP.getFreeHeap()), true);
241+
interf->value(F("pUptime"), String(millis()/1000), true);
242+
interf->json_frame_flush();
243+
}

0 commit comments

Comments
 (0)