From 4a529d6fbd281ba8349c17e01fcbbf5c6dcab1d6 Mon Sep 17 00:00:00 2001 From: Sebastien Date: Wed, 14 Apr 2021 18:16:18 -0400 Subject: [PATCH] Firmware update UI revamp with support for local proxy --- components/platform_console/cmd_config.c | 8 +- components/squeezelite-ota/squeezelite-ota.c | 4 +- components/wifi-manager/webapp/.eslintcache | 2 +- .../webapp/mock/messages_ota.json | 116 ++++++-- .../webapp/mock/messages_ota_flash.json | 117 ++++++++ .../wifi-manager/webapp/mock/status.json | 5 +- components/wifi-manager/webapp/src/index.ejs | 24 +- .../wifi-manager/webapp/src/js/custom.js | 272 +++++++++++++----- .../webapp/src/sass/utils/_style.css | 3 + components/wifi-manager/webapp/webapp.cmake | 6 +- components/wifi-manager/webapp/webpack.c | 30 +- components/wifi-manager/webapp/webpack.h | 50 ++-- .../webapp/webpack/dist/index.html | 2 +- .../webapp/webpack/dist/index.html.br | Bin 4899 -> 4863 bytes .../webapp/webpack/dist/index.html.gz | Bin 5922 -> 5894 bytes .../webapp/webpack/webpack.dev.js | 135 +++++++-- 16 files changed, 585 insertions(+), 189 deletions(-) create mode 100644 components/wifi-manager/webapp/mock/messages_ota_flash.json diff --git a/components/platform_console/cmd_config.c b/components/platform_console/cmd_config.c index f7f2d2e9..906bc3cc 100644 --- a/components/platform_console/cmd_config.c +++ b/components/platform_console/cmd_config.c @@ -1001,8 +1001,12 @@ void register_config_cmd(void){ register_audio_config(); // register_squeezelite_config(); register_bt_source_config(); - register_i2s_config(); - register_spdif_config(); + if(!is_dac_config_locked()){ + register_i2s_config(); + } + if(!is_spdif_config_locked()){ + register_spdif_config(); + } register_rotary_config(); } diff --git a/components/squeezelite-ota/squeezelite-ota.c b/components/squeezelite-ota/squeezelite-ota.c index fa83151b..b31777fe 100644 --- a/components/squeezelite-ota/squeezelite-ota.c +++ b/components/squeezelite-ota/squeezelite-ota.c @@ -633,7 +633,7 @@ void ota_task(void *pvParameter) gettimeofday(&tv, NULL); uint32_t elapsed_ms= (tv.tv_sec-ota_status->OTA_start.tv_sec )*1000+(tv.tv_usec-ota_status->OTA_start.tv_usec)/1000; ESP_LOGI(TAG,"OTA progress : %d/%.0f (%d pct), %d KB/s", ota_status->actual_image_len, ota_status->total_image_len, ota_status->newpct, elapsed_ms>0?ota_status->actual_image_len*1000/elapsed_ms/1024:0); - sendMessaging(MESSAGING_INFO,"Writing binary file %%%3d.",ota_status->newpct); + sendMessaging(MESSAGING_INFO,"Writing binary file %3d %%.",ota_status->newpct); ota_status->lastpct=ota_status->newpct; } taskYIELD(); @@ -662,7 +662,7 @@ void ota_task(void *pvParameter) ESP_LOGI(TAG,"OTA Process completed successfully!"); sendMessaging(MESSAGING_INFO,"Success!"); IF_DISPLAY(GDS_TextLine(display, 2, GDS_TEXT_LEFT, GDS_TEXT_CLEAR | GDS_TEXT_UPDATE, "Success!")); - vTaskDelay(1500/ portTICK_PERIOD_MS); // wait here to give the UI a chance to refresh + vTaskDelay(3500/ portTICK_PERIOD_MS); // wait here to give the UI a chance to refresh IF_DISPLAY(GDS_Clear(display,GDS_COLOR_BLACK)); esp_restart(); } else { diff --git a/components/wifi-manager/webapp/.eslintcache b/components/wifi-manager/webapp/.eslintcache index a3a26952..50e15714 100644 --- a/components/wifi-manager/webapp/.eslintcache +++ b/components/wifi-manager/webapp/.eslintcache @@ -1 +1 @@ -[{"C:\\Users\\sle11\\Documents\\VSCode\\squeezelite-esp32\\components\\wifi-manager\\webapp\\src\\js\\test.js":"1","C:\\Users\\sle11\\Documents\\VSCode\\squeezelite-esp32\\components\\wifi-manager\\webapp\\src\\js\\custom.js":"2"},{"size":4775,"mtime":1608244817341,"results":"3","hashOfConfig":"4"},{"size":57729,"mtime":1618063084495,"results":"5","hashOfConfig":"4"},{"filePath":"6","messages":"7","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"8"},"1lj4yrw",{"filePath":"9","messages":"10","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},"C:\\Users\\sle11\\Documents\\VSCode\\squeezelite-esp32\\components\\wifi-manager\\webapp\\src\\js\\test.js",[],[],"C:\\Users\\sle11\\Documents\\VSCode\\squeezelite-esp32\\components\\wifi-manager\\webapp\\src\\js\\custom.js",[]] \ No newline at end of file +[{"C:\\Users\\sle11\\Documents\\VSCode\\squeezelite-esp32\\components\\wifi-manager\\webapp\\src\\js\\test.js":"1","C:\\Users\\sle11\\Documents\\VSCode\\squeezelite-esp32\\components\\wifi-manager\\webapp\\src\\js\\custom.js":"2"},{"size":4775,"mtime":1608244817341,"results":"3","hashOfConfig":"4"},{"size":61704,"mtime":1618437799595,"results":"5","hashOfConfig":"4"},{"filePath":"6","messages":"7","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"8"},"1275pne",{"filePath":"9","messages":"10","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},"C:\\Users\\sle11\\Documents\\VSCode\\squeezelite-esp32\\components\\wifi-manager\\webapp\\src\\js\\test.js",[],[],"C:\\Users\\sle11\\Documents\\VSCode\\squeezelite-esp32\\components\\wifi-manager\\webapp\\src\\js\\custom.js",[]] \ No newline at end of file diff --git a/components/wifi-manager/webapp/mock/messages_ota.json b/components/wifi-manager/webapp/mock/messages_ota.json index 1fa12cac..5aa452e2 100644 --- a/components/wifi-manager/webapp/mock/messages_ota.json +++ b/components/wifi-manager/webapp/mock/messages_ota.json @@ -1,51 +1,123 @@ -[{ +[ + { + "message": "Save Success", + "type": "MESSAGING_INFO", + "class": "MESSAGING_CLASS_SYSTEM", + "sent_time": 14084, + "current_time": 16958 + }, { "message": "{\"ota_dsc\":\"Initializing...\",\"ota_pct\":0}", "type": "MESSAGING_INFO", "class": "MESSAGING_CLASS_OTA", - "sent_time": 119203, - "current_time": 121837 + "sent_time": 14110, + "current_time": 16958 }, { "message": "{\"ota_dsc\":\"Starting OTA...\",\"ota_pct\":0}", "type": "MESSAGING_INFO", "class": "MESSAGING_CLASS_OTA", - "sent_time": 119255, - "current_time": 121838 + "sent_time": 14146, + "current_time": 16958 }, { - "message": "{\"ota_dsc\":\"Erasing...\",\"ota_pct\":0}", + "message": "{\"ota_dsc\":\"Downloading firmware\",\"ota_pct\":0}", "type": "MESSAGING_INFO", "class": "MESSAGING_CLASS_OTA", - "sent_time": 119255, - "current_time": 121838 - }, { - "message": "{\"ota_dsc\":\"Erasing...\",\"ota_pct\":10}", + "sent_time": 15208, + "current_time": 16958 + }, + { + "message": "{\"ota_dsc\":\"Download success\",\"ota_pct\":0}", "type": "MESSAGING_INFO", "class": "MESSAGING_CLASS_OTA", - "sent_time": 119255, - "current_time": 121838 + "sent_time": 18825, + "current_time": 22219 }, { - "message": "{\"ota_dsc\":\"Erasing...\",\"ota_pct\":100}", + "message": "{\"ota_dsc\":\"New version is : mock version \",\"ota_pct\":0}", "type": "MESSAGING_INFO", "class": "MESSAGING_CLASS_OTA", - "sent_time": 119255, - "current_time": 121838 + "sent_time": 18849, + "current_time": 22220 }, { - "message": "{\"ota_dsc\":\"Flashing...\",\"ota_pct\":10}", + "message": "{\"ota_dsc\":\"Formatting OTA partition\",\"ota_pct\":0}", "type": "MESSAGING_INFO", "class": "MESSAGING_CLASS_OTA", - "sent_time": 119255, - "current_time": 121838 + "sent_time": 18850, + "current_time": 22220 }, { - "message": "{\"ota_dsc\":\"Erasing...\",\"ota_pct\":90}", + "message": "{\"ota_dsc\":\"Erasing flash (1/11)\",\"ota_pct\":0}", "type": "MESSAGING_INFO", "class": "MESSAGING_CLASS_OTA", - "sent_time": 119255, - "current_time": 121838 + "sent_time": 22217, + "current_time": 22220 + }, + { + "message": "{\"ota_dsc\":\"Erasing flash (5/11)\",\"ota_pct\":0}", + "type": "MESSAGING_INFO", + "class": "MESSAGING_CLASS_OTA", + "sent_time": 29896, + "current_time": 29902 + }, + { + "message": "{\"ota_dsc\":\"Erasing flash (7/11)\",\"ota_pct\":0}", + "type": "MESSAGING_INFO", + "class": "MESSAGING_CLASS_OTA", + "sent_time": 33395, + "current_time": 33408 + }, + { + "message": "{\"ota_dsc\":\"Erasing flash (9/11)\",\"ota_pct\":0}", + "type": "MESSAGING_INFO", + "class": "MESSAGING_CLASS_OTA", + "sent_time": 36843, + "current_time": 54597 }, { + "message": "{\"ota_dsc\":\"Erasing flash complete.\",\"ota_pct\":0}", + "type": "MESSAGING_INFO", + "class": "MESSAGING_CLASS_OTA", + "sent_time": 39463, + "current_time": 54597 + }, { + "message": "{\"ota_dsc\":\"Writing binary file\",\"ota_pct\":5}", + "type": "MESSAGING_INFO", + "class": "MESSAGING_CLASS_OTA", + "sent_time": 41862, + "current_time": 54597 + }, { + "message": "{\"ota_dsc\":\"Writing binary file\",\"ota_pct\":10}", + "type": "MESSAGING_INFO", + "class": "MESSAGING_CLASS_OTA", + "sent_time": 44003, + "current_time": 54597 + }, { + "message": "{\"ota_dsc\":\"Writing binary file\",\"ota_pct\":40}", + "type": "MESSAGING_INFO", + "class": "MESSAGING_CLASS_OTA", + "sent_time": 56678, + "current_time": 65185 + }, { + "message": "{\"ota_dsc\":\"Writing binary file\",\"ota_pct\":70}", + "type": "MESSAGING_INFO", + "class": "MESSAGING_CLASS_OTA", + "sent_time": 69407, + "current_time": 77858 + }, { + "message": "{\"ota_dsc\":\"Writing binary file\",\"ota_pct\":95}", + "type": "MESSAGING_INFO", + "class": "MESSAGING_CLASS_OTA", + "sent_time": 80010, + "current_time": 82592 + }, { + "message": "{\"ota_dsc\":\"Writing binary file\",\"ota_pct\":100}", + "type": "MESSAGING_INFO", + "class": "MESSAGING_CLASS_OTA", + "sent_time": 82084, + "current_time": 82592 + }, + { "message": "{\"ota_dsc\":\"Success!\",\"ota_pct\":100}", "type": "MESSAGING_INFO", "class": "MESSAGING_CLASS_OTA", "sent_time": 119255, "current_time": 121838 } - + ] \ No newline at end of file diff --git a/components/wifi-manager/webapp/mock/messages_ota_flash.json b/components/wifi-manager/webapp/mock/messages_ota_flash.json new file mode 100644 index 00000000..fddd83b9 --- /dev/null +++ b/components/wifi-manager/webapp/mock/messages_ota_flash.json @@ -0,0 +1,117 @@ +[ + { + "message": "{\"ota_dsc\":\"Initializing...\",\"ota_pct\":0}", + "type": "MESSAGING_INFO", + "class": "MESSAGING_CLASS_OTA", + "sent_time": 14110, + "current_time": 16958 + }, { + "message": "{\"ota_dsc\":\"Starting OTA...\",\"ota_pct\":0}", + "type": "MESSAGING_INFO", + "class": "MESSAGING_CLASS_OTA", + "sent_time": 14146, + "current_time": 16958 + }, { + "message": "{\"ota_dsc\":\"New version is : mock version \",\"ota_pct\":0}", + "type": "MESSAGING_INFO", + "class": "MESSAGING_CLASS_OTA", + "sent_time": 18849, + "current_time": 22220 + }, { + "message": "{\"ota_dsc\":\"Formatting OTA partition\",\"ota_pct\":0}", + "type": "MESSAGING_INFO", + "class": "MESSAGING_CLASS_OTA", + "sent_time": 18850, + "current_time": 22220 + }, { + "message": "{\"ota_dsc\":\"Erasing flash (1/11)\",\"ota_pct\":0}", + "type": "MESSAGING_INFO", + "class": "MESSAGING_CLASS_OTA", + "sent_time": 22217, + "current_time": 22220 + }, + { + "message": "{\"ota_dsc\":\"Erasing flash (5/11)\",\"ota_pct\":0}", + "type": "MESSAGING_INFO", + "class": "MESSAGING_CLASS_OTA", + "sent_time": 29896, + "current_time": 29902 + }, + { + "message": "{\"ota_dsc\":\"Erasing flash (7/11)\",\"ota_pct\":0}", + "type": "MESSAGING_INFO", + "class": "MESSAGING_CLASS_OTA", + "sent_time": 33395, + "current_time": 33408 + }, + { + "message": "{\"ota_dsc\":\"Erasing flash (9/11)\",\"ota_pct\":0}", + "type": "MESSAGING_INFO", + "class": "MESSAGING_CLASS_OTA", + "sent_time": 36843, + "current_time": 54597 + }, { + "message": "{\"ota_dsc\":\"Erasing flash complete.\",\"ota_pct\":0}", + "type": "MESSAGING_INFO", + "class": "MESSAGING_CLASS_OTA", + "sent_time": 39463, + "current_time": 54597 + }, { + "message": "{\"ota_dsc\":\"Writing binary file\",\"ota_pct\":5}", + "type": "MESSAGING_INFO", + "class": "MESSAGING_CLASS_OTA", + "sent_time": 41862, + "current_time": 54597 + }, { + "message": "{\"ota_dsc\":\"Writing binary file\",\"ota_pct\":25}", + "type": "MESSAGING_INFO", + "class": "MESSAGING_CLASS_OTA", + "sent_time": 50307, + "current_time": 54598 + }, { + "message": "{\"ota_dsc\":\"Writing binary file\",\"ota_pct\":30}", + "type": "MESSAGING_INFO", + "class": "MESSAGING_CLASS_OTA", + "sent_time": 52455, + "current_time": 54598 + }, + { + "message": "{\"ota_dsc\":\"Writing binary file\",\"ota_pct\":35}", + "type": "MESSAGING_INFO", + "class": "MESSAGING_CLASS_OTA", + "sent_time": 54603, + "current_time": 65184 + }, { + "message": "{\"ota_dsc\":\"Writing binary file\",\"ota_pct\":55}", + "type": "MESSAGING_INFO", + "class": "MESSAGING_CLASS_OTA", + "sent_time": 63042, + "current_time": 65185 + }, + { + "message": "{\"ota_dsc\":\"Writing binary file\",\"ota_pct\":60}", + "type": "MESSAGING_INFO", + "class": "MESSAGING_CLASS_OTA", + "sent_time": 65190, + "current_time": 77858 + }, { + "message": "{\"ota_dsc\":\"Writing binary file\",\"ota_pct\":95}", + "type": "MESSAGING_INFO", + "class": "MESSAGING_CLASS_OTA", + "sent_time": 80010, + "current_time": 82592 + }, { + "message": "{\"ota_dsc\":\"Writing binary file\",\"ota_pct\":100}", + "type": "MESSAGING_INFO", + "class": "MESSAGING_CLASS_OTA", + "sent_time": 82084, + "current_time": 82592 + }, + { + "message": "{\"ota_dsc\":\"Success!\",\"ota_pct\":100}", + "type": "MESSAGING_INFO", + "class": "MESSAGING_CLASS_OTA", + "sent_time": 119255, + "current_time": 121838 + } + ] \ No newline at end of file diff --git a/components/wifi-manager/webapp/mock/status.json b/components/wifi-manager/webapp/mock/status.json index 29890ed6..dafbadf1 100644 --- a/components/wifi-manager/webapp/mock/status.json +++ b/components/wifi-manager/webapp/mock/status.json @@ -18,6 +18,9 @@ "lms_cport": 9090, "lms_port": 9100, "lms_ip": "127.0.0.1", + "platform_name": "SqueezeAmp", "mock_plugin_has_proxy": "x", - "platform_name": "SqueezeAmp" + "mock_fail_fw_update":"", + "mock_fail_recovery":"", + "mock_old_recovery":"" } \ No newline at end of file diff --git a/components/wifi-manager/webapp/src/index.ejs b/components/wifi-manager/webapp/src/index.ejs index 94ef8fb5..60b8da16 100644 --- a/components/wifi-manager/webapp/src/index.ejs +++ b/components/wifi-manager/webapp/src/index.ejs @@ -26,11 +26,11 @@ -
+
@@ -185,10 +185,10 @@ -
\ No newline at end of file +SqueezeESP32
Software Updates
VersionDate/TimePlatformBranchBit Depth
Local Firmware Upload
KeyValue
Usage Templates
Output
WiFi Status
JoinedNameSignalSecurity
Logs
TimestampMessage
Tasks
#Task NameCPUStateMin StackBase PriorityCur Priority
Credits

squeezelite-esp32
© 2020, philippe44, sle118, daduke
This software is released under the MIT License.

This app would not be possible without the following libraries:

  • squeezelite, © 2012-2019, Adrian Smith and Ralph Irving. Licensed under the GPL License.
  • esp32-wifi-manager, © 2017-2019, Tony Pottier. Licensed under the MIT License.
  • SpinKit, © 2015, Tobias Ahlin. Licensed under the MIT License.
  • jQuery, The jQuery Foundation. Licensed under the MIT License.
  • cJSON, © 2009-2017, Dave Gamble and cJSON contributors. Licensed under the MIT License.
  • esp32-rotary-encoder, © 2011-2019, David Antliff and Ben Buxton. Licensed under the GPL License.
  • tarablessd1306, © 2017-2018, Tara Keeling. Licensed under the MIT license.
Extras/Overrides
\ No newline at end of file diff --git a/components/wifi-manager/webapp/webpack/dist/index.html.br b/components/wifi-manager/webapp/webpack/dist/index.html.br index c739e49c7a92511768ff4425dd0493dfe686e9b3..d66be4e4aaf0e2dd9afc2f9a20d879fd96c86790 100644 GIT binary patch literal 4863 zcmV7T9&DRtOpcbK@Aea4B8`y?b_zJ<`!2v~Bz{K?Tk(S%956X;IUx;SoXeH&`E-Z)bR&!y+b}3PQW5z*$H_B z=}j2+1>NUt6r9*Xd*nrfjQjg%E{pYQ+0;Q%HyqMAL@xoW<#uJV_eXLpsiCrFD;5eE zMVYOEGXC}UnDJ0wVt*@7)xZ&onK?96|AGgsgPArJW0r9Q3ct`< zx6PBen6oTGeMxX;BZE*;VwNnxYL+L8XXqcz$J}&nI?TJ7|4U|v;m-HgF9F$+Fw47^d=-8%!#4@u;1v(W|MA0Z(xP1VnPZJVdpBC;o8M^V z-ao!_ng;9zkYjDa*D;}vE<~vk_p4}k&Gkp z5%g(Xl+&8{Hs*t*)=JehzX(uoAwJ)e?GJelJ_1rfXvy+pAqFGX@&b16{p0~LAlHCd zhSYR;i2z__g)to2;hyrIMUE_n*XU%Rr9{?g{A1mg24qD#MW2 zE#%RLWN3T>K+doR_lLOM^LHfaNajM|_xFDFK8_FE3x9K3=3jNp)jHiQk~yWAors;O z%(QmAEIwz|{O0pMPn-T9NETa|gzS&djj7CH=lz@xyuC)ri^<-X^Rnj)Izmf*Uk(A| z?K89ZnA7FRD;GEZJZ#(ka{G82=P2E^eD%}Q$$zADJjihlcKf_Fk~V^9yx#9=Tr0C3 zpFzs8OHOU4%&+;R(x*wRaRi>5w}hrQV}ClTP(gB({#2I%@bii3m*OaVA_maR4qS4i z&h|w>=gnl**QljaLmjlma3^5=<(_s8a!O{44s^4MHoDPt$I=*YKO+AVYJ zA?^4NIs=QvffW7z#}+ShP*Yj|XtlpjL$tY5ZBzn+{HJ!uzs;4s0bQ9?8@!J?@TQX9 z5arGQ?e7R(@s88|)v06W(;P}ax7f2bC}xZj;I60+9J$IvsVrGW4oU{GSO8;e0&u$# z*z^-r4GhqX*^>`qg4lT>9!u|Z4iX1gZkKm*(5b>ek?miS-iAylVl@r)kv}!!L=kQa zf;fM9kT~aqkh@Gf+c}4jb}%cv_z1wYLlm~GdQwV+eR;O?1Bo^rqdCdy$*iTeNQNrXG(7Cam9t@WOdFuX1>p24q%z>mvg`1PSYakQ zTP#(_N2#2t(P4O>gKu<2ubO`}A|3bx za35sK#|n?VfSQ0JL^HLTy{sD;pZ*q40Yu%Fk?Nr~Hvg>~F4rw~@O&A+RYi{p)lh%Q z;gYN0Jq&WH+(BkK@yY3AsjO*jYBBg7uJ4lSVs!VZ3sMKu*4WUNr7-K+2xfV4gm{>F z)0}N`3Xu!rwK-TpSLLDkz1Be99%B-mS$3P+s-$LGgA5m@b_)?|7gX`)IEmruLcC0Z zxB`=)K{`c8U^NoBW8DA zeiwex=zHJ}5yhjKy(5O^Q3wVuiw^(m{T51O+uS-y^doRn8$SSdG4V_3w6A3Ua{JCQ z8|Mi908C~|V}j9Xl6|L#cgV@BDk-H*F#4)A>H?Q#MEmXsM3mO_18@^_Bs*8dO^KwR zI&nO~dF>o^wnz5ZUT#VxH7PgmDo)aCOven)Yv+K`UG=H3anFcGwTb9p;2Dm6JzU#2 zcL4aWf3K-}dtM)+kHPNc``rC?|98C^dwtnBM>+G(-6Cb1a>y|Y=V9P#*g6RxV{Vw` zCfOl9^!rVX{IR)z*UpAxteCAbYsRs0&Q@t~jU+BMEWP_7A`oesF#G7d_w7ULjlo5H zA-=2|$I9(7NNg<>-i)SCh`}sJ=m+2~rooxldt;AuIM3A=8nsQBL1Lp2c!py&=f%6L zY0p2l{uw2{VJl#a@z{m986h_^lF@;To8)VXlede*#j&q(&j^S%6)~9QCfO@3H$VLX zQ=Hdku12X>BX6o3C%hV@59KFE-9O+hxjnX*n-Zp_%4eBiiu2kYx=bxRY}>YN+qP}n z_IkZuuXo(*lrU4W38uJQk6VwM67Z(T`4JM4vf8o%{ABD=k9M1Lbb4G zvP1d|$KoqVFUO6YaLBDVYUj)rm+)%I*Fm{;jJ+0-n-7`non^bZAImUtB5Ya4)8KJd z;2P)eQT7GIFJGmNun?_+#q!T1H#B8Gm=+C&IGhUrMu0`!DsZI1*6tLtT(H^wCXUX9l16GQ z{_$d?vIivv`)4h&Ew=~7ttjuzGNg1foEKEd#Jm>2o%1g;T>~C}ldJk|WJfEfRL`Ou zSpni+?Dx!RA~ZUZ^m_1^si0(_vD*qWVvBNRcWBAw^UvkvHebx=zK8tvsQG6UBhnUQ z36ePs5>*RnH?#-(xeSpwN4k0`7DfS?FVm-2shCh~78SPxUL5wJl413ycoqb?`YFUa zN%wQ@)yB;itj2>uNZDM)C`tg|p;fR-j)GZ&gorN-&%~O|C$NvRl8dwfmvRuYrq7Ho z&z|0(zw|PTCWAqZ?@@`1oAt%FD zc!vkoQ!e)=(NlT#wu?^0^c!0Zv~Y;%#0~#V|ISiDZ9|X!I;R3Cd&S_l^M!fyOh@1H z@A&-g+tTM}P$z=(4AhZwbf$(ghScIBHqtdcDqze2?LeSaR+UK6VRZ?ti2;$q067#F z=CJQVNE=Vy(hfDFS4|*54{T&SVzzTzn982UjXH~mCVvTj2obkAJC;K`J9)t_`9qFNUZ!4Y7 z<=)`r{M(bCTy|~)fP_(Z^8mzJ-<{h978kxkNpVU)>Z;gliljh(RJssCWpFOWtA@OnjBz9?>& zg}9Jq>_>ziWawb^%0DxTVtsLYH7!sP#aZR7=Sw#sw5W+=n`DSu0ruj05%ee$yd?Q) z7F(KODH{1>k%Op+fVAaoqf#esElE$psD>}XtSb2a}F+A*bN zF5IMBrSk(53Xh=@WJg>~yNE(uATmCg(n*f$7&-fk?c*uCIh_WRj|;ES(JwT|-GRzb zv;~MF)SgX@gr3Y8i?hT!(s2~;X7Q>52a4btu*PNurnVNAY+_U>X|sB4oImTV@_v^m zZM54{G#!<(zC{1$smVy3Sd_|33F{C9Ns>Rb{2k2Jl#7%(ST>%Uh_cn8*kgiN4MDa~ z=Q+yPdJ?iC zQ@gsdeKar(&j&_|b}J1^!}BIxBd9DQ*w%hUu?UDwa`8{sT$Ni=l+qOq0Ui)(`~`9I zOdgNM5KyRAs0}>@YKY=oL5FTU?sO#V{ z5t6>Wj${a^Z5wl&u3%qE?-5)0{LV^iesd)B9WpEsKuzIZ>6?~3wb@J;`ZYAM0I1NT zTrDLtzy_Le6`jA+7*Gc3+&7uDgBZ5~y*7FqjNOav0E``yOTL89E@*b=kY{Kog2+Ql zQ1zEy&QU_2ikVPS1hT}2nKXKc)S2KsQT2&xUEprOl8usJGQ*D=yXo;f$Ppyqr^kwn z2$vDyI40i=7$w zh$jJ>(Fse+>riuQpCej1Z8i_-wJVC-3yM*nE~>y|K#U`Qx+8S*YZkq7CW=SN??)#! zrp=b2Q&{yN^yGE9QBJ27^{Y&=1j8`KzrK)n1I(Hg`x%wW^g)fXq{;_-;)TSQU6~Zp zP>G6si}UfG>-5N{^b=HAfgWy~ZkCPg_<}APw5vo0Dn-V6TSe)DaB@fm`^@D;W0-)| z5(Hl|*>nC5fUBp)I`#2$AVo<~J74jrAR5X3qL~ZOA?VozSy@UjDf9#q1LDHdTuGWL*{DCiQ;}P1$rW~>u*;jgNh1DuxT?^B57r(=U zg9=rf&{PL4EujL1MD|8Z>`GNPzrnhM=sHOBe6Z3mRr(`~*q?B9iQ{~u5-zrXMIR#N zLgCE=fRH;@rz0}$u8JHphoVTl#G0Hq<#-k{ydVMfJzcWc9@jI_h9H@lBw{XcF(!$Q=$lJoVSjo8Jb&pVGI zC#<89S3l3&H+#E8k1LIaTgxEGRLRrZ;3@HUPL#{*Ko1Odx+$q1%QiUR(=R*QC?vV;U zY!bzq0+-_1j?v1hT&(qeH+K$#OyMcY^mOSgc z_F4#}D@JRr!Lt=V!1czO?1-A84ExeB?Rz7t@46O4$*sks>9n0n&(cxY#%3v@tw0ME zDqCkoWu>A!p@PUnA0b3(v@Bd-cvxv>@Ms-C4?~0<@mruaX9PF_Zt~@LYoSPSIO)8a< lRhgAb2A? literal 4899 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 Hh9IfYx(R>~w=}p2F^2@Z#kK ze)t!O_OM^DdW857bqsU#f?bB-xX6bU?h6 zCziosfc4DV{R~wl!T1B{egHQhu&C1N~Tk(I2-gR$QKT=a8H z&BR=HXM=eV=(82lr++S3$mcvC6GU9pY`=K|_Dh3B%?d2dV{y>eCnq-kKi5X^SL0Ry E0EJ3Wh5!Hn diff --git a/components/wifi-manager/webapp/webpack/webpack.dev.js b/components/wifi-manager/webapp/webpack/webpack.dev.js index 45a0c5ae..1ec43ca3 100644 --- a/components/wifi-manager/webapp/webpack/webpack.dev.js +++ b/components/wifi-manager/webapp/webpack/webpack.dev.js @@ -15,7 +15,9 @@ const data = { messages: require("../mock/messages.json"), messagequeue: require("../mock/messages.json"), message_queue_sequence: [], + status_queue_sequence:[], message_queue_sequence_post_empty: null, + status_queue_sequence_post_empty: null, commands: require("../mock/commands.json"), scan: require("../mock/scan.json"), ap: require("../mock/ap.json"), @@ -23,6 +25,7 @@ const data = { statusdefinition: require("../mock/statusdefinition.json"), status: require("../mock/status.json"), messages_ota_fail: require("../mock/messages_ota_fail.json"), + messages_ota_flash: require("../mock/messages_ota_flash.json"), messages_ota: require("../mock/messages_ota.json") }; const messagingTypes= { @@ -123,8 +126,47 @@ module.exports = merge(common, { app.use(bodyParser.urlencoded({ extended: true })) // for parsing application/x-www-form-urlencoded app.get('/ap.json', function(req, res) { res.json( data.ap ); }); app.get('/scan.json', function(req, res) { res.json( data.scan ); }); - app.get('/config.json', function(req, res) { res.json( data.config ); }); - app.get('/status.json', function(req, res) { res.json( data.status ); }); + app.get('/config.json', function(req, res) { + if(data.status.recovery==1 && (data.status.mock_old_recovery??'')!==''){ + res.json( data.config.config ); + console.log('Mock old recovery - return config structure without gpio'); + } + else { + res.json( data.config ); + } + }); + + app.get('/status.json', function(req, res) { + if(data.status_queue_sequence.length>0){ + const curstatus = JSON.parse(data.status_queue_sequence_queue_sequence.shift()); + data.status.ota_pct=curstatus.ota_pct??0; + data.status.ota_dsc=curstatus.ota_dsc??''; + console.log(`Mock firmware update @${data.status.ota_pct}%, ${data.status.ota_dsc}`) + } + else if (data.status_queue_sequence_post_empty){ + data.status_queue_sequence_post_emptyy(); + console.log(`Mock old firmware update: simulating a restart`); + data.status_queue_sequence_post_empty = null; + } + else if(data.status.ota_pct!=undefined || data.status.ota_dsc!=undefined) { + if(data.status.ota_pct!=undefined) delete data.status.ota_pct; + if(data.status.ota_dsc!=undefined) delete data.status.ota_dsc; + } + if(data.status.message) delete data.status.message; + if(data.status.recovery==1 && (data.status.mock_old_recovery??'')!==''){ + if(data.message_queue_sequence.length>0){ + + const msgpayload = JSON.parse(data.message_queue_sequence.shift()); + data.status.message = msgpayload.message??''; + console.log(`Mocking recovery, setting status message to ${data.status.message}`) + } + else if (data.message_queue_sequence_post_empty){ + data.message_queue_sequence_post_empty(); + data.message_queue_sequence_post_empty = null; + } + } + res.json( data.status ); + }); app.get('/plugins/SqueezeESP32/firmware/-99', function(req, res) { let has_proxy= data.status.mock_plugin_has_proxy ?? 'n'; const statusCode='xy'.includes((has_proxy).toLowerCase())?200:500; @@ -132,6 +174,11 @@ module.exports = merge(common, { res.status(statusCode ).json(); }); app.get('/messages.json', function(req, res) { + if(data.status.recovery==1 && (data.status.mock_old_recovery??'')!==''){ + console.log('Mocking old recovery, with no commands backend' ); + res.status(404).end(); + return; + } if(data.message_queue_sequence.length>0){ data.messagequeue.push(data.message_queue_sequence.shift()); } @@ -144,8 +191,22 @@ module.exports = merge(common, { }); app.get('/statusdefinition.json', function(req, res) { res.json( data.statusdefinition ); }); - app.get('/commands.json', function(req, res) { res.json( data.commands ); }); + app.get('/commands.json', function(req, res) { + if(data.status.recovery==1 && (data.status.mock_old_recovery??'')!==''){ + console.log('Mocking old recovery, with no commands backend' ); + res.status(404).end(); + } + else { + res.json( data.commands ); + } + + }); app.post('/commands.json', function(req, res) { + if(data.status.recovery==1 && (data.status.mock_old_recovery??'')!==''){ + console.log('Mocking old recovery, with no commands backend' ); + res.status(404).end(); + return; + } console.log(req.body.command); try { const cmdName=req.body.command.split(" ")[0]; @@ -189,23 +250,29 @@ module.exports = merge(common, { } res.json( {} ); if(fwurl!=='' ){ + const ota_msg_list= ((data.status.mock_fail_fw_update ?? '')!=='')?data.messages_ota_fail:data.messages_ota; if(data.status.recovery!=1) { // we're not yet in recovery. Simulate reboot to recovery data.status.recovery=1; - requeueMessages(); - } - if(fwurl.toLowerCase().includes('fail')){ - console.log(`queuing ${data.messages_ota_fail.length} ota messages `); - data.message_queue_sequence.push(...data.messages_ota_fail); - - } - else { - console.log(`queuing ${data.messages_ota.length} ota messages `); - data.message_queue_sequence.push(...data.messages_ota); - data.message_queue_sequence_post_empty = function(){ - data.status.recovery=0; + if((data.status.mock_old_recovery??'')===''){ + // older recovery partitions possibly aren't + // sending messages requeueMessages(); - } + } + + } + var targetQueue='message_queue_sequence'; + var targetPostEmpty='message_queue_sequence_post_empty'; + if((data.status.mock_old_recovery??'')!==''){ + console.log('Mocking old firmware flashing mechanism. Starting!'); + targetQueue='status_queue_sequence'; + targetPostEmpty='status_queue_sequence_post_empty'; + } + console.log(`queuing ${ota_msg_list.length} ota messages `); + data[targetQueue].push(...ota_msg_list); + data[targetPostEmpty] = function(){ + data.status.recovery=0; + requeueMessages(); } } }); @@ -220,7 +287,7 @@ module.exports = merge(common, { console.log(`Updated status value ${property}\nFrom: ${data.status[property]}\nTo: ${req.body.status[property]}`); data.status[property]=req.body.status[property]; } - } + } res.json( {} ); }); app.post('/connect.json', function(req, res) { @@ -251,17 +318,37 @@ module.exports = merge(common, { requeueMessages(); }); app.post('/recovery.json', function(req, res) { - data.status.recovery=1; - requeueMessages(); - res.json( { } ); + if((data.status.mock_fail_recovery ?? '')!==''){ + res.status(404).end(); + } + else { + data.status.recovery=1; + requeueMessages(); + res.json( { } ); + } }); app.post('/flash.json', function(req, res) { + if(data.status.recovery>0){ - res.json({}); - } - else { + if((data.status.mock_fail_fw_update ?? '')!=='' || (data.status.mock_old_recovery??'')!==''){ + console.log('Old recovery mock, or fw fail requested' ); + res.status(404).end(); + } + else { + console.log(`queuing ${data.messages_ota_flash.length} flash ota messages `); + data.message_queue_sequence.push(...data.messages_ota_flash); + data.message_queue_sequence_post_empty = function(){ + data.status.recovery=0; + requeueMessages(); + + } + res.json({}); + } + + } + else { res.status(404).end(); - } + } }); app.delete('/connect.json', function(req, res) { data.status.ssid='';