Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

openDTU 24.9.27 reboot alle 10min #2314

Closed
4 tasks done
universal-dilettant opened this issue Sep 29, 2024 · 28 comments · Fixed by #2320
Closed
4 tasks done

openDTU 24.9.27 reboot alle 10min #2314

universal-dilettant opened this issue Sep 29, 2024 · 28 comments · Fixed by #2320
Labels
bug Something isn't working

Comments

@universal-dilettant
Copy link

What happened?

Upgrade von v24.5.6 auf v24.9.23 am 26.9. und auf v24.9.27 am 28.9.
Seit v24.9.26 bootet die openDTU alle 10min (und verliert dabei ihren ac/yieldtotal counter, so habe ich das überhaupt erst bemerkt).
Zum Überprüfen auf die 24.5.6 zurückgegangen und sie läuft wieder stabil (erstmal seit 20min).
Anhand der historischen Daten in InfluxDB (dtu/uptime) lässt sich der Zusammenhang gut belegen.

To Reproduce Bug

siehe oben

Expected Behavior

keine reboots :-)

Install Method

Pre-Compiled binary from GitHub releases

What git-hash/version of OpenDTU?

24.9.27

What firmware variant (PIO Environment) are you using?

generic_esp32

Relevant log/trace output

No response

Anything else?

Falls Logs/Traces/etc benötigt werden, gerne.
Ob der Issue nur mich betrifft oder auch andere, kann ich nicht sagen, würde es aber vermuten.

Please confirm the following

  • I believe this issue is a bug that affects all users of OpenDTU, not something specific to my installation.
  • I have already searched for relevant existing issues and discussions before opening this report.
  • I have updated the title field above with a concise description.
  • I have double checked that my inverter does not contain a W in the model name (like HMS-xxxW) as they are not supported.
@universal-dilettant universal-dilettant added the bug Something isn't working label Sep 29, 2024
@rolsch
Copy link

rolsch commented Sep 29, 2024

Welche Hardware läuft bei dir den?

Version v24.9.27 läuft hier ohne Auffälligkeiten

Chip-Modell
ESP32-D0WD-V3
2
240 MHz
4.194.304 Byte (4 MB)

@tbnobody
Copy link
Owner

Interessant wäre auch ein Auszug vom Seriellen Log während des Reboots. Damit kann man eher einschätzen was passiert. Wie @rolsch schon sagt, es scheint kein generelles Problem zu sein, da ich es auf meinen diversen Test-DTUs auch nicht nachvollziehen kann.

@schlimmchen
Copy link
Contributor

Kann ich bestätigen, auch die Zeitangabe von ca. 10 Minuten, was ziemlich genau passt. Es waren bei den unten gezeigten Ausfällen jeweils etwas mehr, gut 11 Minuten bis das Web Ifc nicht mehr erreichbar ist. Grund: Offensichtlich ein Speicherleck. Ich kann unter api/system/status zusehen, wie heap_min_free und heap_max_block kleiner werden.

Log 1 von OpenDTU b206cee (selbst-kompiliert)
abort() was called at PC 0x420ca4af on core 1

Backtrace: 0x40377db6:0x3fceb9b0 0x4037d21d:0x3fceb9d0 0x40383d29:0x3fceb9f0 0x420ca4af:0x3fceba70 0x420ca4f6:0x3fceba90 0x420ca6d1:0x3fcebab0 0x420ca78c:0x3fcebad0 0x4203b381:0x3fcebaf0 0x4203b585:0x3fcebb10 0x4203b0e6:0x3fcebb50 0x42007efd:0x3fcebb80 0x420ec7a5:0x3fcebbd0 0x4202545e:0x3fcebbf0 0x420255d9:0x3fcebc10 0x420255f2:0x3fcebc30 0x42045521:0x3fcebc50

ELF file SHA256: 9338ecf52ed17760

0x40377db6: panic_abort at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/esp_system/panic.c:408
0x4037d21d: esp_system_abort at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/esp_system/esp_system.c:137
0x40383d29: abort at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/newlib/abort.c:46
0x420ca4af: __cxxabiv1::__terminate(void (*)()) at /builds/idf/crosstool-NG/.build/xtensa-esp32s3-elf/src/gcc/libstdc++-v3/libsupc++/eh_terminate.cc:47
0x420ca4f6: std::terminate() at /builds/idf/crosstool-NG/.build/xtensa-esp32s3-elf/src/gcc/libstdc++-v3/libsupc++/eh_terminate.cc:57
0x420ca6d1: __cxa_allocate_exception at /builds/idf/crosstool-NG/.build/xtensa-esp32s3-elf/src/gcc/libstdc++-v3/libsupc++/eh_alloc.cc:300
0x420ca78c: operator new(unsigned int) at /builds/idf/crosstool-NG/.build/xtensa-esp32s3-elf/src/gcc/libstdc++-v3/libsupc++/new_op.cc:54
0x4203b381: __gnu_cxx::new_allocator<std::_List_node<ChannelNum_t> >::allocate(unsigned int, void const*) at /home/schlimmchen/.platformio/packages/toolchain-xtensa-esp32s3/xtensa-esp32s3-elf/include/c++/8.4.0/ext/new_allocator.h:111
 (inlined by) std::allocator_traits<std::allocator<std::_List_node<ChannelNum_t> > >::allocate(std::allocator<std::_List_node<ChannelNum_t> >&, unsigned int) at /home/schlimmchen/.platformio/packages/toolchain-xtensa-esp32s3/xtensa-esp32s3-elf/include/c++/8.4.0/bits/alloc_traits.h:436
 (inlined by) std::__cxx11::_List_base<ChannelNum_t, std::allocator<ChannelNum_t> >::_M_get_node() at /home/schlimmchen/.platformio/packages/toolchain-xtensa-esp32s3/xtensa-esp32s3-elf/include/c++/8.4.0/bits/stl_list.h:450
 (inlined by) std::_List_node<ChannelNum_t>* std::__cxx11::list<ChannelNum_t, std::allocator<ChannelNum_t> >::_M_create_node<ChannelNum_t const&>(ChannelNum_t const&) at /home/schlimmchen/.platformio/packages/toolchain-xtensa-esp32s3/xtensa-esp32s3-elf/include/c++/8.4.0/bits/stl_list.h:642
 (inlined by) void std::__cxx11::list<ChannelNum_t, std::allocator<ChannelNum_t> >::_M_insert<ChannelNum_t const&>(std::_List_iterator<ChannelNum_t>, ChannelNum_t const&) at /home/schlimmchen/.platformio/packages/toolchain-xtensa-esp32s3/xtensa-esp32s3-elf/include/c++/8.4.0/bits/stl_list.h:1903
 (inlined by) std::__cxx11::list<ChannelNum_t, std::allocator<ChannelNum_t> >::push_back(ChannelNum_t const&) at /home/schlimmchen/.platformio/packages/toolchain-xtensa-esp32s3/xtensa-esp32s3-elf/include/c++/8.4.0/bits/stl_list.h:1220
 (inlined by) StatisticsParser::getChannelsByType[abi:cxx11](ChannelType_t) const at /home/schlimmchen/Documents/OpenDTU-OnBattery/lib/Hoymiles/src/parser/StatisticsParser.cpp:297
0x4203b585: calcTotalYieldTotal(StatisticsParser*, unsigned char) at /home/schlimmchen/Documents/OpenDTU-OnBattery/lib/Hoymiles/src/parser/StatisticsParser.cpp:394
0x4203b0e6: StatisticsParser::getChannelFieldValue(ChannelType_t, ChannelNum_t, FieldId_t) at /home/schlimmchen/Documents/OpenDTU-OnBattery/lib/Hoymiles/src/parser/StatisticsParser.cpp:182
0x42007efd: DatastoreClass::loop() at /home/schlimmchen/Documents/OpenDTU-OnBattery/src/Datastore.cpp:86
0x420ec7a5: void std::__invoke_impl<void, void (DatastoreClass::*&)(), DatastoreClass*&>(std::__invoke_memfun_deref, void (DatastoreClass::*&)(), DatastoreClass*&) at /home/schlimmchen/.platformio/packages/toolchain-xtensa-esp32s3/xtensa-esp32s3-elf/include/c++/8.4.0/bits/invoke.h:73
 (inlined by) std::__invoke_result<void (DatastoreClass::*&)(), DatastoreClass*&>::type std::__invoke<void (DatastoreClass::*&)(), DatastoreClass*&>(void (DatastoreClass::*&)(), DatastoreClass*&) at /home/schlimmchen/.platformio/packages/toolchain-xtensa-esp32s3/xtensa-esp32s3-elf/include/c++/8.4.0/bits/invoke.h:95
 (inlined by) void std::_Bind<void (DatastoreClass::*(DatastoreClass*))()>::__call<void, , 0u>(std::tuple<>&&, std::_Index_tuple<0u>) at /home/schlimmchen/.platformio/packages/toolchain-xtensa-esp32s3/xtensa-esp32s3-elf/include/c++/8.4.0/functional:400
 (inlined by) void std::_Bind<void (DatastoreClass::*(DatastoreClass*))()>::operator()<, void>() at /home/schlimmchen/.platformio/packages/toolchain-xtensa-esp32s3/xtensa-esp32s3-elf/include/c++/8.4.0/functional:484
 (inlined by) std::_Function_handler<void (), std::_Bind<void (DatastoreClass::*(DatastoreClass*))()> >::_M_invoke(std::_Any_data const&) at /home/schlimmchen/.platformio/packages/toolchain-xtensa-esp32s3/xtensa-esp32s3-elf/include/c++/8.4.0/bits/std_function.h:297
0x4202545e: std::function<void ()>::operator()() const at /home/schlimmchen/.platformio/packages/toolchain-xtensa-esp32s3/xtensa-esp32s3-elf/include/c++/8.4.0/bits/std_function.h:687
0x420255d9: Scheduler::execute() at /home/schlimmchen/Documents/OpenDTU-OnBattery/.pio/libdeps/generic_esp32s3_usb/TaskScheduler/src/TaskScheduler.h:1552
 (inlined by) Scheduler::execute() at /home/schlimmchen/Documents/OpenDTU-OnBattery/.pio/libdeps/generic_esp32s3_usb/TaskScheduler/src/TaskScheduler.h:1351
0x420255f2: loop() at /home/schlimmchen/Documents/OpenDTU-OnBattery/src/main.cpp:172
0x42045521: loopTask(void*) at /home/schlimmchen/.platformio/packages/framework-arduinoespressif32/cores/esp32/main.cpp:50
Log 2 von OpenDTU b206cee (selbst-kompiliert)
abort() was called at PC 0x420ca4af on core 1

Backtrace: 0x40377db6:0x3fcebc40 0x4037d21d:0x3fcebc60 0x40383d29:0x3fcebc80 0x420ca4af:0x3fcebd00 0x420ca4f6:0x3fcebd20 0x420ca83b:0x3fcebd40 0x420ca79a:0x3fcebd60 0x420397ef:0x3fcebd80 0x42036515:0x3fcebde0 0x420095f2:0x3fcebe10 0x420ec93d:0x3fcebe30 0x4202545e:0x3fcebe50 0x420255d9:0x3fcebe70 0x420255f2:0x3fcebe90 0x42045521:0x3fcebeb0

ELF file SHA256: 9338ecf52ed17760

0x40377db6: panic_abort at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/esp_system/panic.c:408
0x4037d21d: esp_system_abort at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/esp_system/esp_system.c:137
0x40383d29: abort at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/newlib/abort.c:46
0x420ca4af: __cxxabiv1::__terminate(void (*)()) at /builds/idf/crosstool-NG/.build/xtensa-esp32s3-elf/src/gcc/libstdc++-v3/libsupc++/eh_terminate.cc:47
0x420ca4f6: std::terminate() at /builds/idf/crosstool-NG/.build/xtensa-esp32s3-elf/src/gcc/libstdc++-v3/libsupc++/eh_terminate.cc:57
0x420ca83b: __cxa_throw at /builds/idf/crosstool-NG/.build/xtensa-esp32s3-elf/src/gcc/libstdc++-v3/libsupc++/eh_throw.cc:95
0x420ca79a: operator new(unsigned int) at /builds/idf/crosstool-NG/.build/xtensa-esp32s3-elf/src/gcc/libstdc++-v3/libsupc++/new_op.cc:54
0x420397ef: __gnu_cxx::new_allocator<std::_Sp_counted_ptr_inplace<SystemConfigParaCommand, std::allocator<SystemConfigParaCommand>, (__gnu_cxx::_Lock_policy)2> >::allocate(unsigned int, void const*) at /home/schlimmchen/.platformio/packages/toolchain-xtensa-esp32s3/xtensa-esp32s3-elf/include/c++/8.4.0/ext/new_allocator.h:111
 (inlined by) std::allocator_traits<std::allocator<std::_Sp_counted_ptr_inplace<SystemConfigParaCommand, std::allocator<SystemConfigParaCommand>, (__gnu_cxx::_Lock_policy)2> > >::allocate(std::allocator<std::_Sp_counted_ptr_inplace<SystemConfigParaCommand, std::allocator<SystemConfigParaCommand>, (__gnu_cxx::_Lock_policy)2> >&, unsigned int) at /home/schlimmchen/.platformio/packages/toolchain-xtensa-esp32s3/xtensa-esp32s3-elf/include/c++/8.4.0/bits/alloc_traits.h:436
 (inlined by) std::__allocated_ptr<std::allocator<std::_Sp_counted_ptr_inplace<SystemConfigParaCommand, std::allocator<SystemConfigParaCommand>, (__gnu_cxx::_Lock_policy)2> > > std::__allocate_guarded<std::allocator<std::_Sp_counted_ptr_inplace<SystemConfigParaCommand, std::allocator<SystemConfigParaCommand>, (__gnu_cxx::_Lock_policy)2> > >(std::allocator<std::_Sp_counted_ptr_inplace<SystemConfigParaCommand, std::allocator<SystemConfigParaCommand>, (__gnu_cxx::_Lock_policy)2> >&) at /home/schlimmchen/.platformio/packages/toolchain-xtensa-esp32s3/xtensa-esp32s3-elf/include/c++/8.4.0/bits/allocated_ptr.h:97
 (inlined by) std::__shared_count<(__gnu_cxx::_Lock_policy)2>::__shared_count<SystemConfigParaCommand, std::allocator<SystemConfigParaCommand>, InverterAbstract*&>(SystemConfigParaCommand*&, std::_Sp_alloc_shared_tag<std::allocator<SystemConfigParaCommand> >, InverterAbstract*&) at /home/schlimmchen/.platformio/packages/toolchain-xtensa-esp32s3/xtensa-esp32s3-elf/include/c++/8.4.0/bits/shared_ptr_base.h:675
 (inlined by) std::__shared_ptr<SystemConfigParaCommand, (__gnu_cxx::_Lock_policy)2>::__shared_ptr<std::allocator<SystemConfigParaCommand>, InverterAbstract*&>(std::_Sp_alloc_shared_tag<std::allocator<SystemConfigParaCommand> >, InverterAbstract*&) at /home/schlimmchen/.platformio/packages/toolchain-xtensa-esp32s3/xtensa-esp32s3-elf/include/c++/8.4.0/bits/shared_ptr_base.h:1342
 (inlined by) std::shared_ptr<SystemConfigParaCommand>::shared_ptr<std::allocator<SystemConfigParaCommand>, InverterAbstract*&>(std::_Sp_alloc_shared_tag<std::allocator<SystemConfigParaCommand> >, InverterAbstract*&) at /home/schlimmchen/.platformio/packages/toolchain-xtensa-esp32s3/xtensa-esp32s3-elf/include/c++/8.4.0/bits/shared_ptr.h:359
 (inlined by) std::shared_ptr<SystemConfigParaCommand> std::allocate_shared<SystemConfigParaCommand, std::allocator<SystemConfigParaCommand>, InverterAbstract*&>(std::allocator<SystemConfigParaCommand> const&, InverterAbstract*&) at /home/schlimmchen/.platformio/packages/toolchain-xtensa-esp32s3/xtensa-esp32s3-elf/include/c++/8.4.0/bits/shared_ptr.h:706
 (inlined by) std::shared_ptr<SystemConfigParaCommand> std::make_shared<SystemConfigParaCommand, InverterAbstract*&>(InverterAbstract*&) at /home/schlimmchen/.platformio/packages/toolchain-xtensa-esp32s3/xtensa-esp32s3-elf/include/c++/8.4.0/bits/shared_ptr.h:722
 (inlined by) std::shared_ptr<SystemConfigParaCommand> HoymilesRadio::prepareCommand<SystemConfigParaCommand>(InverterAbstract*) at /home/schlimmchen/Documents/OpenDTU-OnBattery/lib/Hoymiles/src/HoymilesRadio.h:27
 (inlined by) HM_Abstract::sendSystemConfigParaRequest() at /home/schlimmchen/Documents/OpenDTU-OnBattery/lib/Hoymiles/src/inverters/HM_Abstract.cpp:111
0x42036515: HoymilesClass::loop() at /home/schlimmchen/Documents/OpenDTU-OnBattery/lib/Hoymiles/src/Hoymiles.cpp:84
0x420095f2: InverterSettingsClass::hoyLoop() at /home/schlimmchen/Documents/OpenDTU-OnBattery/src/InverterSettings.cpp:119
0x420ec93d: void std::__invoke_impl<void, void (InverterSettingsClass::*&)(), InverterSettingsClass*&>(std::__invoke_memfun_deref, void (InverterSettingsClass::*&)(), InverterSettingsClass*&) at /home/schlimmchen/.platformio/packages/toolchain-xtensa-esp32s3/xtensa-esp32s3-elf/include/c++/8.4.0/bits/invoke.h:73
 (inlined by) std::__invoke_result<void (InverterSettingsClass::*&)(), InverterSettingsClass*&>::type std::__invoke<void (InverterSettingsClass::*&)(), InverterSettingsClass*&>(void (InverterSettingsClass::*&)(), InverterSettingsClass*&) at /home/schlimmchen/.platformio/packages/toolchain-xtensa-esp32s3/xtensa-esp32s3-elf/include/c++/8.4.0/bits/invoke.h:95
 (inlined by) void std::_Bind<void (InverterSettingsClass::*(InverterSettingsClass*))()>::__call<void, , 0u>(std::tuple<>&&, std::_Index_tuple<0u>) at /home/schlimmchen/.platformio/packages/toolchain-xtensa-esp32s3/xtensa-esp32s3-elf/include/c++/8.4.0/functional:400
 (inlined by) void std::_Bind<void (InverterSettingsClass::*(InverterSettingsClass*))()>::operator()<, void>() at /home/schlimmchen/.platformio/packages/toolchain-xtensa-esp32s3/xtensa-esp32s3-elf/include/c++/8.4.0/functional:484
 (inlined by) std::_Function_handler<void (), std::_Bind<void (InverterSettingsClass::*(InverterSettingsClass*))()> >::_M_invoke(std::_Any_data const&) at /home/schlimmchen/.platformio/packages/toolchain-xtensa-esp32s3/xtensa-esp32s3-elf/include/c++/8.4.0/bits/std_function.h:297
0x4202545e: std::function<void ()>::operator()() const at /home/schlimmchen/.platformio/packages/toolchain-xtensa-esp32s3/xtensa-esp32s3-elf/include/c++/8.4.0/bits/std_function.h:687
0x420255d9: Scheduler::execute() at /home/schlimmchen/Documents/OpenDTU-OnBattery/.pio/libdeps/generic_esp32s3_usb/TaskScheduler/src/TaskScheduler.h:1552
 (inlined by) Scheduler::execute() at /home/schlimmchen/Documents/OpenDTU-OnBattery/.pio/libdeps/generic_esp32s3_usb/TaskScheduler/src/TaskScheduler.h:1351
0x420255f2: loop() at /home/schlimmchen/Documents/OpenDTU-OnBattery/src/main.cpp:172
0x42045521: loopTask(void*) at /home/schlimmchen/.platformio/packages/framework-arduinoespressif32/cores/esp32/main.cpp:50
Log von OpenDTU-OnBattery (genauen Stand weiß ich nicht mehr, aber b206cee ist ge-merge't)
abort() was called at PC 0x421052a3 on core 1

Backtrace: 0x403780ee:0x3fceb9c0 0x4037d625:0x3fceb9e0 0x403842f1:0x3fceba00 0x421052a3:0x3fceba80 0x421052ea:0x3fcebaa0 0x4210562f:0x3fcebac0 0x4210558e:0x3fcebae0 0x420690c1:0x3fcebb00 0x42069271:0x3fcebb20 0x420673eb:0x3fcebb80 0x42014fb6:0x3fcebbb0 0x42125319:0x3fcebbd0 0x420531fe:0x3fcebbf0 0x42053379:0x3fcebc10 0x42053392:0x3fcebc30 0x42079bfd:0x3fcebc50

ELF file SHA256: 71160a47517da131
0x403780ee: panic_abort at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/esp_system/panic.c:408
0x4037d625: esp_system_abort at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/esp_system/esp_system.c:137
0x403842f1: abort at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/newlib/abort.c:46
0x421052a3: __cxxabiv1::__terminate(void (*)()) at /builds/idf/crosstool-NG/.build/xtensa-esp32s3-elf/src/gcc/libstdc++-v3/libsupc++/eh_terminate.cc:47
0x421052ea: std::terminate() at /builds/idf/crosstool-NG/.build/xtensa-esp32s3-elf/src/gcc/libstdc++-v3/libsupc++/eh_terminate.cc:57
0x4210562f: __cxa_throw at /builds/idf/crosstool-NG/.build/xtensa-esp32s3-elf/src/gcc/libstdc++-v3/libsupc++/eh_throw.cc:95
0x4210558e: operator new(unsigned int) at /builds/idf/crosstool-NG/.build/xtensa-esp32s3-elf/src/gcc/libstdc++-v3/libsupc++/new_op.cc:54
0x420690c1: __gnu_cxx::new_allocator<fragment_t>::allocate(unsigned int, void const*) at /home/schlimmchen/.platformio/packages/toolchain-xtensa-esp32s3/xtensa-esp32s3-elf/include/c++/8.4.0/ext/new_allocator.h:111
 (inlined by) std::allocator_traits<std::allocator<fragment_t> >::allocate(std::allocator<fragment_t>&, unsigned int) at /home/schlimmchen/.platformio/packages/toolchain-xtensa-esp32s3/xtensa-esp32s3-elf/include/c++/8.4.0/bits/alloc_traits.h:436
 (inlined by) std::_Deque_base<fragment_t, std::allocator<fragment_t> >::_M_allocate_node() at /home/schlimmchen/.platformio/packages/toolchain-xtensa-esp32s3/xtensa-esp32s3-elf/include/c++/8.4.0/bits/stl_deque.h:603
 (inlined by) void std::deque<fragment_t, std::allocator<fragment_t> >::_M_push_back_aux<fragment_t const&>(fragment_t const&) at /home/schlimmchen/.platformio/packages/toolchain-xtensa-esp32s3/xtensa-esp32s3-elf/include/c++/8.4.0/bits/deque.tcc:488
0x42069271: std::deque<fragment_t, std::allocator<fragment_t> >::push_back(fragment_t const&) at /home/schlimmchen/.platformio/packages/toolchain-xtensa-esp32s3/xtensa-esp32s3-elf/include/c++/8.4.0/bits/stl_deque.h:1562
 (inlined by) std::queue<fragment_t, std::deque<fragment_t, std::allocator<fragment_t> > >::push(fragment_t const&) at /home/schlimmchen/.platformio/packages/toolchain-xtensa-esp32s3/xtensa-esp32s3-elf/include/c++/8.4.0/bits/stl_queue.h:252
 (inlined by) HoymilesRadio_CMT::loop() at /home/schlimmchen/Documents/OpenDTU-OnBattery/lib/Hoymiles/src/HoymilesRadio_CMT.cpp:143
0x420673eb: HoymilesClass::loop() at /home/schlimmchen/Documents/OpenDTU-OnBattery/lib/Hoymiles/src/Hoymiles.cpp:44
0x42014fb6: InverterSettingsClass::hoyLoop() at /home/schlimmchen/Documents/OpenDTU-OnBattery/src/InverterSettings.cpp:127
0x42125319: void std::__invoke_impl<void, void (InverterSettingsClass::*&)(), InverterSettingsClass*&>(std::__invoke_memfun_deref, void (InverterSettingsClass::*&)(), InverterSettingsClass*&) at /home/schlimmchen/.platformio/packages/toolchain-xtensa-esp32s3/xtensa-esp32s3-elf/include/c++/8.4.0/bits/invoke.h:73
 (inlined by) std::__invoke_result<void (InverterSettingsClass::*&)(), InverterSettingsClass*&>::type std::__invoke<void (InverterSettingsClass::*&)(), InverterSettingsClass*&>(void (InverterSettingsClass::*&)(), InverterSettingsClass*&) at /home/schlimmchen/.platformio/packages/toolchain-xtensa-esp32s3/xtensa-esp32s3-elf/include/c++/8.4.0/bits/invoke.h:95
 (inlined by) void std::_Bind<void (InverterSettingsClass::*(InverterSettingsClass*))()>::__call<void, , 0u>(std::tuple<>&&, std::_Index_tuple<0u>) at /home/schlimmchen/.platformio/packages/toolchain-xtensa-esp32s3/xtensa-esp32s3-elf/include/c++/8.4.0/functional:400
 (inlined by) void std::_Bind<void (InverterSettingsClass::*(InverterSettingsClass*))()>::operator()<, void>() at /home/schlimmchen/.platformio/packages/toolchain-xtensa-esp32s3/xtensa-esp32s3-elf/include/c++/8.4.0/functional:484
 (inlined by) std::_Function_handler<void (), std::_Bind<void (InverterSettingsClass::*(InverterSettingsClass*))()> >::_M_invoke(std::_Any_data const&) at /home/schlimmchen/.platformio/packages/toolchain-xtensa-esp32s3/xtensa-esp32s3-elf/include/c++/8.4.0/bits/std_function.h:297
0x420531fe: std::function<void ()>::operator()() const at /home/schlimmchen/.platformio/packages/toolchain-xtensa-esp32s3/xtensa-esp32s3-elf/include/c++/8.4.0/bits/std_function.h:687
0x42053379: Scheduler::execute() at /home/schlimmchen/Documents/OpenDTU-OnBattery/.pio/libdeps/generic_esp32s3_usb/TaskScheduler/src/TaskScheduler.h:1552
 (inlined by) Scheduler::execute() at /home/schlimmchen/Documents/OpenDTU-OnBattery/.pio/libdeps/generic_esp32s3_usb/TaskScheduler/src/TaskScheduler.h:1351
0x42053392: loop() at /home/schlimmchen/Documents/OpenDTU-OnBattery/src/main.cpp:206
0x42079bfd: loopTask(void*) at /home/schlimmchen/.platformio/packages/framework-arduinoespressif32/cores/esp32/main.cpp:50

Besonderheiten an diesem schmutzigen Test-Aufbau:

  • Mehrere Inverter sind konfiguriert, die nicht erreichbar sind.
  • MQTT ist konfiguriert, aber der Server läuft nicht.

Sonst sollte nichts außergewöhnliches dran sein. Bei mir handelt es sich um Firmware Variante generic_esp32s3_usb auf einem Fusion Board.

@schlimmchen
Copy link
Contributor

MQTT ausschalten bringt keine Veränderung.

Den nicht-erreichbaren Inverter löschen bringt auch keine Veränderung.

Ich sehe auf der Konsole nur noch "Admin AP remaining seconds: 40 / 180" hochzählen, dennoch sinkt heap_min_free.

@tbnobody
Copy link
Owner

Habe hier aus anderen Gründen gerade einen Test laufen... 10 inverter konfiguriert. keiner erreichbar. mqtt aber erreichbar... --> Klappt erstmal problemlos. Bin gerade bei 15min Uptime. Heap und max Heap sind unverändert.
@schlimmchen was ist denn dein MQTT Poll Intervall? Welches RF Modul ist im Einsatz?
Werde jetzt noch einen Versuch machen und den MQTT broker deaktivieren.

@tbnobody
Copy link
Owner

Ich sehe auf der Konsole nur noch "Admin AP remaining seconds: 40 / 180" hochzählen, dennoch sinkt heap_min_free.

Nope alles gut hier.. MQTT ist auf eine IP umgebogen auf der kein broker lauscht. läuft also jedes mal in eine "connection reset by peer".

Hast du dabei die Live View offen oder die system view?

@tbnobody
Copy link
Owner

Ok, habe jetzt auch noch die Live View offen... Uptime ist bei 15min. 10 Inverter am CMT Modul verbunden. MQTT kann sich nicht verbinden.... Heap ist normal.

Werde es jetzt nochmal mit einem esp32s3 testen.

@tbnobody
Copy link
Owner

Hm auch keine Probleme mit einem esp32s3 mit w5500.
Habe jetzt auch nochmal die version 24.9.27 geflashed um auszuschließen das es an meinen lokalen änderungen liegt.
Klappt immer noch alles.

@schlimmchen machst du mir deine config schicken? (wifi credentials usw. bitte vorher entfernen). dann spiele ich die hier mal ein und schaue was passiert.

@universal-dilettant
Copy link
Author

Scheint, wie @schlimmchen vermutet, am Heap zu liegen. Free geht von irgendwas um die 140.000 nach reboot beginnend konstant runter. Nach 400s ist er um die 75.000.

grafik
grafik
grafik
Auf dem Chip steht esp-32s

Das Bootlog nach dem unexpected reboot, diesmal nach etwa 7min
`Request SystemConfigPara
[536055][E][WiFiClient.cpp:429] write(): fail on fd 49, errno: 11, "No more processes"
[536774][E][WiFiClient.cpp:429] write(): fail on fd 49, errno: 11, "No more processes"
[537784][E][WiFiClient.cpp:429] write(): fail on fd 49, errno: 11, "No more processes"
[538784][E][WiFiClient.cpp:429] write(): fail on fd 49, errno: 11, "No more processes"
[539784][E][WiFiClient.cpp:429] write(): fail on fd 49, errno: 11, "No more processes"
[540793][E][WiFiClient.cpp:429] write(): fail on fd 49, errno: 11, "No more processes"
[541793][E][WiFiClient.cpp:429] write(): fail on fd 49, errno: 11, "No more processes"
[542793][E][WiFiClient.cpp:429] write(): fail on fd 49, errno: 11, "No more processes"
[543793][E][WiFiClient.cpp:429] write(): fail on fd 49, errno: 11, "No more processes"
[544794][E][WiFiClient.cpp:429] write(): fail on fd 49, errno: 11, "No more processes"
[545794][E][WiFiClient.cpp:429] write(): fail on fd 49, errno: 11, "No more processes"
[546807][E][WiFiClient.cpp:429] write(): fail on fd 49, errno: 11, "No more processes"
[547807][E][WiFiClient.cpp:429] write(): fail on fd 49, errno: 11, "No more processes"
[548807][E][WiFiClient.cpp:429] write(): fail on fd 49, errno: 11, "No more processes"
[549807][E][WiFiClient.cpp:429] write(): fail on fd 49, errno: 11, "No more processes"
[550807][E][WiFiClient.cpp:429] write(): fail on fd 49, errno: 11, "No more processes"
[551807][E][WiFiClient.cpp:429] write(): fail on fd 49, errno: 11, "No more processes"
[552807][E][WiFiClient.cpp:429] write(): fail on fd 49, errno: 11, "No more processes"
[553807][E][WiFiClient.cpp:429] write(): fail on fd 49, errno: 11, "No more processes"
[554807][E][WiFiClient.cpp:429] write(): fail on fd 49, errno: 11, "No more processes"
[555807][E][WiFiClient.cpp:429] write(): fail on fd 49, errno: 11, "No more processes"
[556807][E][WiFiClient.cpp:429] write(): fail on fd 49, errno: 11, "No more processes"
[557807][E][WiFiClient.cpp:429] write(): fail on fd 49, errno: 11, "No more processes"
[558822][E][WiFiClient.cpp:429] write(): fail on fd 49, errno: 11, "No more processes"
[559822][E][WiFiClient.cpp:429] write(): fail on fd 49, errno: 11, "No more processes"
[560822][E][WiFiClient.cpp:429] write(): fail on fd 49, errno: 11, "No more processes"
[561822][E][WiFiClient.cpp:429] write(): fail on fd 49, errno: 11, "No more processes"
[562822][E][WiFiClient.cpp:429] write(): fail on fd 49, errno: 11, "No more processes"
[563822][E][WiFiClient.cpp:429] write(): fail on fd 49, errno: 11, "No more processes"
[564822][E][WiFiClient.cpp:429] write(): fail on fd 49, errno: 11, "No more processes"
[565822][E][WiFiClient.cpp:429] write(): fail on fd 49, errno: 11, "No more processes"
[566822][E][WiFiClient.cpp:429] write(): fail on fd 49, errno: 11, "No more processes"
[567822][E][WiFiClient.cpp:429] write(): fail on fd 49, errno: 11, "No more processes"
[568822][E][WiFiClient.cpp:429] write(): fail on fd 49, errno: 11, "No more processes"
[569822][E][WiFiClient.cpp:429] write(): fail on fd 49, errno: 11, "No more processes"
[570822][E][WiFiClient.cpp:429] write(): fail on fd 49, errno: 11, "No more processes"
Disconnected from MQTT.
Disconnect reason:TCP_DISCONNECTED
TX ChannelChangeCommand 868.00 MHz --> 56 80 15 51 94 80 11 19 80 02 15 21 14 14 38
RX Period End
All missing
Nothing received, resend whole request
TX ChannelChangeCommand 868.00 MHz --> 56 80 15 51 94 80 11 19 80 02 15 21 14 14 38

abort() was called at PC 0x401a8b23 on core 1

Backtrace: 0x40083d8d:0x3ffb2080 0x4008ee99:0x3ffb20a0 0x400950a9:0x3ffb20c0 0x401a8b23:0x3ffb2140 0x401a8b6a:0x3ffb2160 0x401a8d45:0x3ffb2180 0x401a8e00:0x3ffb21a0 0x400f2833:0x3ffb21c0 0x400f2aef:0x3ffb21f0 0x401c8cf1:0x3ffb2210 0x400f53a6:0x3ffb2230 0x400f5521:0x3ffb2250 0x400f553a:0x3ffb2270 0x40115eb1:0x3ffb2290

ELF file SHA256: 40ab189640df9f1c

E (16223) esp_core_dump_flash: Core dump flash config is corrupted! CRC=0x7bd5c66f instead of 0x0
Rebooting...
ets Jun 8 2016 00:22:57

rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3fff0030,len:1184
load:0x40078000,len:13192
load:0x40080400,len:3028
entry 0x400805e4
E (691) esp_core_dump_flash: No core dum▒▒▒▒ѥѥ▒▒▒found!
E (691) esp_core_dump_flash: No core dump partition found!

Starting OpenDTU
Initialize FS... done
Reading configuration... done
Reading PinMapping... found valid mapping done
Initialize Network... done
Setting Hostname... Configuring WiFi STA using new credentials... done
Initialize NTP... done
Initialize SunPosition... done
Initialize MqTT... done
Initialize WebApi... done
Initialize Display... done
Initialize LEDs... done
Check for default DTU serial... done
Initialize Hoymiles interface... CMT: Connection successful
Setting country mode...
Setting CMT target frequency...
Setting radio PA level...
CMT TX power set to 20 dBm
Setting DTU serial...
Setting poll interval...
Adding inverter: 1164801xxxxx - WR1 done
Adding inverter: 1164801yyyyy - WR2 done
done
Switch to WiFi mode
Setting Hostname... done
Configuring WiFi STA using new credentials... done
Configuring WiFi STA static IP... done
Fetch inverter: 116480155194
TX RealTimeRunData 865.00 MHz --> 15 80 15 51 94 80 11 19 80 80 0B 00 66 FA 2E DA 00 00 00 00 00 00 00 00 63 88 45
RX Period End
All missing
Nothing received, resend whole request
TX RealTimeRunData 865.00 MHz --> 15 80 15 51 94 80 11 19 80 80 0B 00 66 FA 2E DA 00 00 00 00 00 00 00 00 63 88 45
WiFi connected
WiFi got ip: 192.168.0.229
Network connected
Connecting to MQTT...
Connected to MQTT.
RX Period End
All missing`

Wie gesagt, die 24.5.6 lief/läuft stabil.

@schlimmchen
Copy link
Contributor

Hast du dabei die Live View offen oder die system view?

Tritt auch auf, wenn ich die System Status View anschaue und (soweit ich weiß) kein Browsertab habe, das die Live-View anzeigt.

machst du mir deine config schicken?

Ja, gerne, daran habe ich auch schon gedacht. Ging nicht eher.

config1_pretty.json ist die Version, die OpenDTU geschrieben hat, nachdem ich den AP timeout heruntergesetzt habe. config_pretty.json (ohne 1) ist jene von OpenDTU-OnBattery, die im flash übrig blieb nach dem Flashen von OpenDTU. Hab die Büchse dann nochmal neu gestartet mit der "reinen" OpenDTU Konfig, und das Problem besteht wie erwartet weiterhin.

config_and_pinmapping.zip

Display ist übrigens keins angeschlossen, aber konfiguriert. PoE hat ist keins drauf.

Klappt immer noch alles.

Jup, undankbares Problem, aber da es "einfach auftritt" beir mir und universal-dilettant und es auch nicht weg geht, wird wohl was dran sein.

Ich hab mal den diff zwischen v24.9.27 und v24.9.26 nach "new" durchsucht, aber da ist mir nichts ins Gesicht gesprungen. Heute Abend wäre dann git bisect angesagt, wenn es sich nur bei mir reproduzieren lässt.

Der Themenstarter sagt, er habe die Release-Binary genommen. Wird dann wohl kein platformio cache oder non-clean-build Problem sein, nehme ich an.

@stefan123t
Copy link

@universal-dilettant @schlimmchen was für WR Typen habt Ihr denn konfiguriert auf Euren (Test-) Systemen ? Nur HM oder HMS/HMT oder beides, evtl ein besonderes Modell ?

@schlimmchen
Copy link
Contributor

Gar keinen (mehr), siehe die hochgeladene config oben, das Problem tritt trotzdem auf.

@universal-dilettant
Copy link
Author

2x HMS-2000-4T

@tbnobody
Copy link
Owner

@schlimmchen ich kann das problem mit deiner config nachvollziehen. Den unterschied an den configs konnte ich in der Einstellung mit dem "Allow anonymous readonly access" festmachen. Wenn ich diese Funktion aktiviere klappt alles. Es scheint in der aktuellen version des webservers beim handling der authenfizierung irgendetwas schief zu laufen.

@schlimmchen
Copy link
Contributor

Gute Neuigkeiten. Dann behaupte ich, dass #2316 doch kein weiterer Typ Panic ist, sondern ebenfalls mit dieser Funktion zusammenhängt. Da ist der Kontext ja ebenfalls die Basic-Athentication.

Das Problem ist bei mir ebenfalls sofort verschwunden, wenn ich "Allow anonymous readonly access" einschalte.

Mit diesem Wissen wäre meine erste Vermutung nun, dass die Einführung von Middlewares beim AsyncWebServer etwas damit zu tun hat. Muss da noch etwas an das neue Schema angepasst werden?

@schlimmchen
Copy link
Contributor

Ich behaupte, dass

_ws.setAuthentication(AUTH_USERNAME, Configuration.get().Security.Password);

und

_ws.setAuthentication(AUTH_USERNAME, Configuration.get().Security.Password);

wegen der Einführung von Middlewares umgebaut werden müssen.

Ansonsten wird Security.AllowReadonly nur bei checkCredentialsReadonly() verwendet, doch dort wird bei ausgeschalteten "allow readonly access" lediglich Code durchlaufen, der ansonsten in checkCredentials() ebenfalls und häufig durchlaufen wird und keine Probleme zu machen scheint.

Es macht auch Sinn, dass der Speicher kontinuierlich und von selbst sinkt, weil setAuthentication() periodisch aufgerufen wird. Das ist vielleicht auch keine Absicht?

setAuthentication() gibt es ja noch....

AsyncWebHandler& AsyncWebHandler::setAuthentication(const char* username, const char* password) {
  if (username == nullptr || password == nullptr || strlen(username) == 0 || strlen(password) == 0)
    return *this;
  AuthenticationMiddleware* m = new AuthenticationMiddleware();
  m->setUsername(username);
  m->setPassword(password);
  m->_freeOnRemoval = true;
  addMiddleware(m);
  return *this;
};

Aha, okay. Ein Leak ist es nicht wirklich, es werden so lange Middlewares instanziiert und dem Server hinzugefügt, bis kein Speicher mehr da ist. Das erklärt auch den langen Backtrace in #2316. Und das erklärt auch, warum ich den gefühlt immer gesehen habe, wenn ich den Live-View (neu) aufgerufen habe.

Ich hab einen Fix gebastelt und scheinbar erfolgreich getestet. Kommt gleich per PR.

@schlimmchen
Copy link
Contributor

weil setAuthentication() periodisch aufgerufen wird. Das ist vielleicht auch keine Absicht?

Doch, das sorgte dafür, dass beim Verändern der Option "allow readonly access" die websockets spätestens nach einer Sekunde mit der neuen Einstellung versehen wurden.

Das ist ohnehin eine Regression, denn wenn der readonly access einmal ausgeschaltet wurde, ist die Middelware für immer in der Chain und würde auch beim Wiedereinschalten des readonly access dafür sorgen, dass Authentifiziert werden muss (vermute ich, habs nicht getestet).

@universal-dilettant
Copy link
Author

bestätige @schlimmchen. Mit "Allow anonymous readonly access" = on (war bei mir schon immer off) pendelt der freie Heap um die 150.000. Testweise erneut auf off und der freie Heap ist wieder geschrumpft. Nochmal auf on und er hat sich auf dem dann niedrigen Stand erneut stabilisiert.
(war jetzt nur ein quick&dirty Test)

@stefan123t
Copy link

stefan123t commented Sep 30, 2024

@schlimmchen es gibt zwei Punkte bei der Einführung der AuthenticationMiddleware des ESPAsyncWebServer zu beachten:

How to use authentication with AuthenticationMiddleware
Do not use the setUsername() and setPassword() methods on the handlers anymore. They are deprecated. These methods were causing a copy of the username and password for each handler, which is not efficient.
Now, you can use the AuthenticationMiddleware to handle authentication globally or per handler.

AuthenticationMiddleware authMiddleware;

// [...]

authMiddleware.setAuthType(AuthenticationMiddleware::AuthType::AUTH_DIGEST);
authMiddleware.setRealm("My app name");
authMiddleware.setUsername("admin");
authMiddleware.setPassword("admin");

// [...]

server.addMiddleware(&authMiddleware); // globally add authentication to the server

// [...]

myHandler.addMiddleware(&authMiddleware); // add authentication to a specific handler

Migration to Middleware to improve performance and memory usage
AsyncWebHandler.setAuthentication(...) => do not use this method anymore: add a common AuthenticationMiddleware to the handler or server

@schlimmchen yes this is the culprit, it will create a new AuthenticationMiddleware for each call to setAuthentication():

https://github.com/mathieucarbou/ESPAsyncWebServer/blob/2e65ee60df093dad4caf2c05c93ae4f897e19b9d/src/ESPAsyncWebServer.h#L840

    AsyncWebHandler& setAuthentication(const char* username, const char* password) {
      if (username == nullptr || password == nullptr || strlen(username) == 0 || strlen(password) == 0)
        return *this;
      AuthenticationMiddleware* m = new AuthenticationMiddleware();
      m->setUsername(username);
      m->setPassword(password);
      m->_freeOnRemoval = true;
      addMiddleware(m);
      return *this;
    };

Eventually the memory may get _freeOnRemoval though only when the AsyncWebHandler has been handled and the request processed. So the handlers may queue up and fill up the memory.


Rest of my train of thoughts follows in english for no reason 😁

We are currently attaching the method to AsyncWebSocket _ws

    AsyncWebSocket _ws;
...
        _ws.setAuthentication(AUTH_USERNAME, Configuration.get().Security.Password);

I do not know if adding a BASIC Auth check - actually base64 encoded username:password string comparison - to OpenDTU using a complex AuthHandler class with an overcomplex AuthenticationMiddleware is actually a good-idea (tm) in the first place ?

As you can see it in the following source upstream, for each request the base64 encoded username:password hash will be encoded again, even though this Token does not change, once the Attributes are set. And the actual comparison memcmp(hash, encoded, encodedLen) == 0 only takes place in line 59.

https://github.com/mathieucarbou/ESPAsyncWebServer/blob/main/src/WebAuthentication.cpp#L34-67

ESPAsyncWebServer.h:

    // hash is the string representation of:
    //  base64(user:pass) for basic or
    //  user:realm:md5(user:realm:pass) for digest
    bool authenticate(const char* hash);
    bool authenticate(const char* username, const char* password, const char* realm = NULL, bool passwordIsHash = false);

As we are using HTTP for the user-interface and REST endpoints of OpenDTU this is kind of superstitious IMHO.

@tbnobody
Copy link
Owner

Das ist ohnehin eine Regression, denn wenn der readonly access einmal ausgeschaltet wurde, ist die Middelware für immer in der Chain und würde auch beim Wiedereinschalten des readonly access dafür sorgen, dass Authentifiziert werden muss (vermute ich, habs nicht getestet).

Das ist richtig. Habe schon gesehen, dass es neben addMiddleware auch ein removeMiddleware gibt. In der "alten" API war es so, dass setAuthentication mit leeren Parametern die Authentifizierung wieder deaktiviert hat.
Entsprechend

Ich glaube sowas hier würde es tun:

void WebApiWsLiveClass::wsCleanupTaskCb()
{
    // see: https://github.com/me-no-dev/ESPAsyncWebServer#limiting-the-number-of-web-socket-clients
    _ws.cleanupClients();

    if (Configuration.get().Security.AllowReadonly == _lastAuthType) {
        return;
    }

    if (Configuration.get().Security.AllowReadonly) {
        MessageOutput.println("Remove Auth");
        _ws.removeMiddleware(&_authMiddleware);
    } else {
        MessageOutput.println("Add Auth");
        _authMiddleware.setUsername(AUTH_USERNAME);
        _authMiddleware.setPassword(Configuration.get().Security.Password);
        _ws.addMiddleware(&_authMiddleware);
    }

    _lastAuthType = Configuration.get().Security.AllowReadonly;
}

@stefan123t
Copy link

stefan123t commented Sep 30, 2024

@tbnobody prinzipiell ja, vielleicht können wir den Aufruf irgendwie so umbiegen, dass die AuthenticationMiddleware anstelle von BASIC Auth mit username:password nur den von uns gesetzten Hash verwendet (siehe bool authenticate(const char* hash); oben) ?
Dann könnten wir uns das aufwendige neu berechnen des hashes bei jedem Aufruf sparen.

@schlimmchen
Copy link
Contributor

Ich glaube sowas hier würde es tun:

An meinem PR finde ich besser, dass die Anpassung der Einstellungen event-driven ist. _lastAuthType braucht man dann nicht.

Dann könnten wir uns das aufwendige neu berechnen des hashes bei jedem Aufruf sparen.

Das wäre dann was für ESPAsyncWebserver, weil Thomas und ich gerade den empfohlenen, neuen Weg vorschlagen, wie man so eine Authentication per Middleware umsetzen sollte. Diese AuthenticationMiddleware ist nicht schwergewichtig. Die ruft am Ende maßgeblich auch nur request->authenticate() auf, aber beherrscht inbesondere die Handhabung des Middleware-Konzeptes, was wir sonst nachimplementieren müssten.

@stefan123t
Copy link

stefan123t commented Sep 30, 2024

@schlimmchen Dein PR #2320 ändert auch unser Auth Verfahren von BASIC Auth auf DIGEST Auth, also Username:Realm:Password anstelle von Username:Password und dem entsprechend angepaßten X-Authentication: DIGEST username:realm:md5(username:realm:base64) Header.
Das müssten dann alle Nutzer der REST API auch berücksichtigen.

@schlimmchen
Copy link
Contributor

Dein PR #2320 ändert auch unser Auth Verfahren von BASIC Auth auf DIGEST Auth

Wenn dem so ist, müssen wir drüber sprechen. Wäre aber eine gute Gelegenheit, BASIC wegzuwerfen -- meine Meinung.

Das müssten dann alle Nutzer der REST API auch berücksichtigen.

Nein, denn es geht nur um die Websockets.

@stefan123t
Copy link

stefan123t commented Sep 30, 2024

@schlimmchen ja, das Default Verfahren der AuthenticationMiddleware ist auch / sowieso DIGEST Auth.

Abgesehen von der etwas komplizierteren Erstellung (MD5 statt base64) eines passenden Tokens / Hashes um den Endpunkt per curl, etc. aufzufrufen spricht m.E. nur dagegen, daß man auch noch eine Realm, bzw. NULL angeben muß und der Aufwand den Request zu bearbeiten dadurch auf Seite des ESP32 noch größer wird.

$ echo 'username:password' | base64 -
dXNlcm5hbWU6cGFzc3dvcmQK
$ echo 'username:realm:password' | md5sum -
a7c190273e23666520d7ccfec748de18  -

Also einmal

Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQK

das andere Mal sendet der Server (wir) die nonce / das Passwort

WWW-Authenticate password

Und der Client muss dann die Authorization dazu passend berechnen:

Authorization: Digest username:realm:a7c190273e23666520d7ccfec748de18

Wir haben m.E. auch keinen echten Sicherheitsgewinn dadurch, da wir m.W. immer noch per http mit der OpenDTU sprechen, oder täusche ich mich da ?

Ich versuche gerade noch zu verstehen, wie man die AuthenticationMiddleware dazu bringt, ggf. nur den Hash zu speichern und gegen diesen zu authentifizieren mit der o.g. Signatur bool authenticate(const char* hash);

@schlimmchen
Copy link
Contributor

Wenn man BASIC authentication mitschickt, wird diese auch akzeptiert. Es wird kein Challenge-Response erwzwungen um DIGEST zu machen. Das heißt: Ist ech schon "abwärtskompatibel" und der Hash, vor dessen Berechnung sich @stefan123t fürchtet, wird vermutlich auch nur dann berechnet, wenn der Client auf DIGEST besteht.

Wir haben m.E. auch keinen echten Sicherheitsgewinn dadurch

Der Punkt ist, dass man bei DIGEST Authentication nicht durch Mithören das Passwort (trivial) bestimmen kann, das überreicht wurde. Das mag nicht "kritisch" sein für unsere Anwendung, aber es ist pauschal Unfug, sowas noch zu tun, finde ich.

@stefan123t
Copy link

@schlimmchen prinzipiell gebe ich Dir Recht dass DIGEST Auth vorzuziehen ist, aber dann bräuchten wir auch pro Client eine eigene Client Nonce die wir bei jedem 401 Request entsprechend aktualisieren. Sonst ist es nur ein etwas komplizierteres BASIC Auth mit fester nonce 😉

Und ich "fürchte" mich nicht vor dem Berechnen des MD5 Hashes bzw. des Base64 Encodierten BASIC Auth tokens 😁, aber der Code zeigt klar, dass dies bei jedem Aufruf von AsyncWebServerRequest::authenticate() in der Unterroutine checkBasicAuthentication() oder checkDigestAuthentication() auf dem Heap erneut zusammen gebastelt und dann erst geprüft wird. Das könnte man sich bei BASIC Auth mit einem quasi über die Zeit fixen Hash/Token prinzipiell sparen.

Aber da hast Du natürlich Recht, das gehört eigentlich upstream in der ESPAsyncWebServer Implementierung adressiert und gefixt.

@stefan123t
Copy link

stefan123t commented Sep 30, 2024

Und was auch richtig ist, man kann in der Tat DIGEST Auth in der AuthenticationMiddleware einstellen und dann aber beim Request nur einen BASIC Auth mitschicken, dann landet der Code in WebRequest.cpp m.E. im BASIC Auth Zweig:

bool AsyncWebServerRequest::authenticate(const char* username, const char* password, const char* realm, bool passwordIsHash) {
  if (_authorization.length()) {
    if (_isDigest)
      return checkDigestAuthentication(_authorization.c_str(), methodToString(), username, password, realm, passwordIsHash, NULL, NULL, NULL);
    else if (!passwordIsHash)
      return checkBasicAuthentication(_authorization.c_str(), username, password);
    else
      return _authorization.equals(password);
  }
  return false;
}

_isDigest und _hash bzw. passwordIsHash werden beim parsen des Request Headers einfach blind übernommen und mit den Client Werten aus dem Request Header gefüllt. D.h. man kann (aktuell) m.E. auch bei DIGEST Auth einen BASIC Auth Request absetzen.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants
@tbnobody @schlimmchen @rolsch @stefan123t @universal-dilettant and others