mirror of
https://github.com/sle118/squeezelite-esp32.git
synced 2025-12-06 11:36:59 +03:00
Merge remote-tracking branch 'origin/httpd' into master-cmake
Conflicts: .cproject .gitmodules .project .pydevproject .settings/language.settings.xml .settings/org.eclipse.cdt.core.prefs components/cmd_i2c/CMakeLists.txt components/cmd_i2c/cmd_i2ctools.c components/cmd_i2c/component.mk components/cmd_nvs/cmd_nvs.c components/cmd_nvs/component.mk components/cmd_system/cmd_system.c components/cmd_system/component.mk components/config/config.c components/config/config.h components/config/nvs_utilities.c components/display/CMakeLists.txt components/driver_bt/CMakeLists.txt components/driver_bt/component.mk components/raop/raop.c components/services/CMakeLists.txt components/squeezelite-ota/cmd_ota.c components/squeezelite-ota/squeezelite-ota.c components/squeezelite-ota/squeezelite-ota.h components/squeezelite/component.mk components/telnet/CMakeLists.txt components/wifi-manager/CMakeLists.txt components/wifi-manager/dns_server.c components/wifi-manager/http_server.c components/wifi-manager/http_server.h components/wifi-manager/wifi_manager.c components/wifi-manager/wifi_manager.h main/CMakeLists.txt main/console.c main/esp_app_main.c main/platform_esp32.h
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -66,3 +66,6 @@ libs/
|
||||
/cdump.cmd
|
||||
/_*
|
||||
squeezelite-esp32-jsonblob.zip
|
||||
/flash_cmd.txt
|
||||
/writeSequeezeEsp.bat
|
||||
/writeSequeezeEsp.sh
|
||||
|
||||
4
.gitmodules
vendored
4
.gitmodules
vendored
@@ -2,6 +2,6 @@
|
||||
path = components/telnet/libtelnet
|
||||
url = https://github.com/seanmiddleditch/libtelnet
|
||||
branch = develop
|
||||
[submodule "esp-dsp"]
|
||||
[submodule "components/esp-dsp"]
|
||||
path = components/esp-dsp
|
||||
url = https://github.com/philippe44/esp-dsp
|
||||
url = https://github.com/philippe44/esp-dsp.git
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<?eclipse-pydev version="1.0"?><pydev_project>
|
||||
|
||||
<pydev_property name="org.python.pydev.PYTHON_PROJECT_INTERPRETER">Default</pydev_property>
|
||||
|
||||
<pydev_property name="org.python.pydev.PYTHON_PROJECT_VERSION">python interpreter</pydev_property>
|
||||
|
||||
</pydev_project>
|
||||
|
||||
2
.settings/com.googlecode.cppcheclipse.core.prefs
Normal file
2
.settings/com.googlecode.cppcheclipse.core.prefs
Normal file
@@ -0,0 +1,2 @@
|
||||
eclipse.preferences.version=1
|
||||
suppressions=rO0ABXNyAAxqYXZhLmlvLkZpbGUELaRFDg3k/wMAAUwABHBhdGh0ABJMamF2YS9sYW5nL1N0cmluZzt4cHQAJWNvbXBvbmVudHNcd2lmaS1tYW5hZ2VyXGh0dHBfc2VydmVyLmN3AgBceA\=\=;comparePointers;395\!rO0ABXNyAAxqYXZhLmlvLkZpbGUELaRFDg3k/wMAAUwABHBhdGh0ABJMamF2YS9sYW5nL1N0cmluZzt4cHQAE21haW5cZXNwX2FwcF9tYWluLmN3AgBceA\=\=;comparePointers;176\!rO0ABXNyAAxqYXZhLmlvLkZpbGUELaRFDg3k/wMAAUwABHBhdGh0ABJMamF2YS9sYW5nL1N0cmluZzt4cHQAJ2NvbXBvbmVudHNcdGVsbmV0XGxpYnRlbG5ldFxsaWJ0ZWxuZXQuY3cCAFx4;va_list_usedBeforeStarted;2147483647\!
|
||||
89
.settings/org.eclipse.cdt.codan.core.prefs
Normal file
89
.settings/org.eclipse.cdt.codan.core.prefs
Normal file
@@ -0,0 +1,89 @@
|
||||
eclipse.preferences.version=1
|
||||
org.eclipse.cdt.codan.checkers.errnoreturn=Warning
|
||||
org.eclipse.cdt.codan.checkers.errnoreturn.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"No return\\")",implicit\=>false}
|
||||
org.eclipse.cdt.codan.checkers.errreturnvalue=Error
|
||||
org.eclipse.cdt.codan.checkers.errreturnvalue.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Unused return value\\")"}
|
||||
org.eclipse.cdt.codan.checkers.nocommentinside=-Error
|
||||
org.eclipse.cdt.codan.checkers.nocommentinside.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Nesting comments\\")"}
|
||||
org.eclipse.cdt.codan.checkers.nolinecomment=-Error
|
||||
org.eclipse.cdt.codan.checkers.nolinecomment.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Line comments\\")"}
|
||||
org.eclipse.cdt.codan.checkers.noreturn=Error
|
||||
org.eclipse.cdt.codan.checkers.noreturn.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"No return value\\")",implicit\=>false}
|
||||
org.eclipse.cdt.codan.internal.checkers.AbstractClassCreation=Error
|
||||
org.eclipse.cdt.codan.internal.checkers.AbstractClassCreation.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Abstract class cannot be instantiated\\")"}
|
||||
org.eclipse.cdt.codan.internal.checkers.AmbiguousProblem=Error
|
||||
org.eclipse.cdt.codan.internal.checkers.AmbiguousProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Ambiguous problem\\")"}
|
||||
org.eclipse.cdt.codan.internal.checkers.AssignmentInConditionProblem=Warning
|
||||
org.eclipse.cdt.codan.internal.checkers.AssignmentInConditionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Assignment in condition\\")"}
|
||||
org.eclipse.cdt.codan.internal.checkers.AssignmentToItselfProblem=Error
|
||||
org.eclipse.cdt.codan.internal.checkers.AssignmentToItselfProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Assignment to itself\\")"}
|
||||
org.eclipse.cdt.codan.internal.checkers.CStyleCastProblem=-Warning
|
||||
org.eclipse.cdt.codan.internal.checkers.CStyleCastProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"C-Style cast instead of C++ cast\\")"}
|
||||
org.eclipse.cdt.codan.internal.checkers.CaseBreakProblem=Warning
|
||||
org.eclipse.cdt.codan.internal.checkers.CaseBreakProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"No break at end of case\\")",no_break_comment\=>"no break",last_case_param\=>false,empty_case_param\=>false,enable_fallthrough_quickfix_param\=>false}
|
||||
org.eclipse.cdt.codan.internal.checkers.CatchByReference=Warning
|
||||
org.eclipse.cdt.codan.internal.checkers.CatchByReference.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Catching by reference is recommended\\")",unknown\=>false,exceptions\=>()}
|
||||
org.eclipse.cdt.codan.internal.checkers.CircularReferenceProblem=Error
|
||||
org.eclipse.cdt.codan.internal.checkers.CircularReferenceProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Circular inheritance\\")"}
|
||||
org.eclipse.cdt.codan.internal.checkers.ClassMembersInitialization=Warning
|
||||
org.eclipse.cdt.codan.internal.checkers.ClassMembersInitialization.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Class members should be properly initialized\\")",skip\=>true}
|
||||
org.eclipse.cdt.codan.internal.checkers.CopyrightProblem=-Warning
|
||||
org.eclipse.cdt.codan.internal.checkers.CopyrightProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Lack of copyright information\\")",regex\=>".*Copyright.*"}
|
||||
org.eclipse.cdt.codan.internal.checkers.DecltypeAutoProblem=Error
|
||||
org.eclipse.cdt.codan.internal.checkers.DecltypeAutoProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid 'decltype(auto)' specifier\\")"}
|
||||
org.eclipse.cdt.codan.internal.checkers.FieldResolutionProblem=Error
|
||||
org.eclipse.cdt.codan.internal.checkers.FieldResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Field cannot be resolved\\")"}
|
||||
org.eclipse.cdt.codan.internal.checkers.FunctionResolutionProblem=Error
|
||||
org.eclipse.cdt.codan.internal.checkers.FunctionResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Function cannot be resolved\\")"}
|
||||
org.eclipse.cdt.codan.internal.checkers.GotoStatementProblem=-Warning
|
||||
org.eclipse.cdt.codan.internal.checkers.GotoStatementProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Goto statement used\\")"}
|
||||
org.eclipse.cdt.codan.internal.checkers.InvalidArguments=Error
|
||||
org.eclipse.cdt.codan.internal.checkers.InvalidArguments.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid arguments\\")"}
|
||||
org.eclipse.cdt.codan.internal.checkers.InvalidTemplateArgumentsProblem=Error
|
||||
org.eclipse.cdt.codan.internal.checkers.InvalidTemplateArgumentsProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid template argument\\")"}
|
||||
org.eclipse.cdt.codan.internal.checkers.LabelStatementNotFoundProblem=Error
|
||||
org.eclipse.cdt.codan.internal.checkers.LabelStatementNotFoundProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Label statement not found\\")"}
|
||||
org.eclipse.cdt.codan.internal.checkers.MemberDeclarationNotFoundProblem=Error
|
||||
org.eclipse.cdt.codan.internal.checkers.MemberDeclarationNotFoundProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Member declaration not found\\")"}
|
||||
org.eclipse.cdt.codan.internal.checkers.MethodResolutionProblem=Error
|
||||
org.eclipse.cdt.codan.internal.checkers.MethodResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Method cannot be resolved\\")"}
|
||||
org.eclipse.cdt.codan.internal.checkers.MissCaseProblem=-Warning
|
||||
org.eclipse.cdt.codan.internal.checkers.MissCaseProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Missing cases in switch\\")"}
|
||||
org.eclipse.cdt.codan.internal.checkers.MissDefaultProblem=-Warning
|
||||
org.eclipse.cdt.codan.internal.checkers.MissDefaultProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Missing default in switch\\")",defaultWithAllEnums\=>false}
|
||||
org.eclipse.cdt.codan.internal.checkers.NamingConventionFunctionChecker=-Info
|
||||
org.eclipse.cdt.codan.internal.checkers.NamingConventionFunctionChecker.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Name convention for function\\")",pattern\=>"^[a-z]",macro\=>true,exceptions\=>()}
|
||||
org.eclipse.cdt.codan.internal.checkers.NonVirtualDestructorProblem=Warning
|
||||
org.eclipse.cdt.codan.internal.checkers.NonVirtualDestructorProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Class has a virtual method and non-virtual destructor\\")"}
|
||||
org.eclipse.cdt.codan.internal.checkers.OverloadProblem=Error
|
||||
org.eclipse.cdt.codan.internal.checkers.OverloadProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid overload\\")"}
|
||||
org.eclipse.cdt.codan.internal.checkers.RedeclarationProblem=Error
|
||||
org.eclipse.cdt.codan.internal.checkers.RedeclarationProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid redeclaration\\")"}
|
||||
org.eclipse.cdt.codan.internal.checkers.RedefinitionProblem=Error
|
||||
org.eclipse.cdt.codan.internal.checkers.RedefinitionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid redefinition\\")"}
|
||||
org.eclipse.cdt.codan.internal.checkers.ReturnStyleProblem=-Warning
|
||||
org.eclipse.cdt.codan.internal.checkers.ReturnStyleProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Return with parenthesis\\")"}
|
||||
org.eclipse.cdt.codan.internal.checkers.ScanfFormatStringSecurityProblem=-Warning
|
||||
org.eclipse.cdt.codan.internal.checkers.ScanfFormatStringSecurityProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Format String Vulnerability\\")"}
|
||||
org.eclipse.cdt.codan.internal.checkers.StatementHasNoEffectProblem=Warning
|
||||
org.eclipse.cdt.codan.internal.checkers.StatementHasNoEffectProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Statement has no effect\\")",macro\=>true,exceptions\=>()}
|
||||
org.eclipse.cdt.codan.internal.checkers.SuggestedParenthesisProblem=Warning
|
||||
org.eclipse.cdt.codan.internal.checkers.SuggestedParenthesisProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Suggested parenthesis around expression\\")",paramNot\=>false}
|
||||
org.eclipse.cdt.codan.internal.checkers.SuspiciousSemicolonProblem=Warning
|
||||
org.eclipse.cdt.codan.internal.checkers.SuspiciousSemicolonProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Suspicious semicolon\\")",else\=>false,afterelse\=>false}
|
||||
org.eclipse.cdt.codan.internal.checkers.TypeResolutionProblem=Error
|
||||
org.eclipse.cdt.codan.internal.checkers.TypeResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Type cannot be resolved\\")"}
|
||||
org.eclipse.cdt.codan.internal.checkers.UnusedFunctionDeclarationProblem=Warning
|
||||
org.eclipse.cdt.codan.internal.checkers.UnusedFunctionDeclarationProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Unused function declaration\\")",macro\=>true}
|
||||
org.eclipse.cdt.codan.internal.checkers.UnusedStaticFunctionProblem=Warning
|
||||
org.eclipse.cdt.codan.internal.checkers.UnusedStaticFunctionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Unused static function\\")",macro\=>true}
|
||||
org.eclipse.cdt.codan.internal.checkers.UnusedVariableDeclarationProblem=Warning
|
||||
org.eclipse.cdt.codan.internal.checkers.UnusedVariableDeclarationProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Unused variable declaration in file scope\\")",macro\=>true,exceptions\=>("@(\#)","$Id")}
|
||||
org.eclipse.cdt.codan.internal.checkers.UsingInHeaderProblem=-Warning
|
||||
org.eclipse.cdt.codan.internal.checkers.UsingInHeaderProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Using directive in header\\")"}
|
||||
org.eclipse.cdt.codan.internal.checkers.VariableResolutionProblem=Error
|
||||
org.eclipse.cdt.codan.internal.checkers.VariableResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Symbol is not resolved\\")"}
|
||||
org.eclipse.cdt.codan.internal.checkers.VirtualMethodCallProblem=-Error
|
||||
org.eclipse.cdt.codan.internal.checkers.VirtualMethodCallProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Virtual method call in constructor/destructor\\")"}
|
||||
org.eclipse.cdt.qt.core.qtproblem=Warning
|
||||
org.eclipse.cdt.qt.core.qtproblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>false,RUN_ON_INC_BUILD\=>false,RUN_ON_FILE_OPEN\=>true,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>null}
|
||||
10
Makefile
10
Makefile
@@ -10,9 +10,13 @@
|
||||
|
||||
|
||||
#recovery: PROJECT_NAME:=recovery.$(PROJECT_CONFIG_TARGET)
|
||||
#recovery: CPPFLAGS+=-DRECOVERY_APPLICATION=1
|
||||
#recovery: EXTRA_CPPFLAGS+=-DRECOVERY_APPLICATION=1
|
||||
|
||||
PROJECT_NAME?=squeezelite
|
||||
EXTRA_COMPONENT_DIRS := esp-dsp
|
||||
EXTRA_CPPFLAGS+= -I$(PROJECT_PATH)/main
|
||||
|
||||
#/-Wno-error=maybe-uninitialized
|
||||
include $(IDF_PATH)/make/project.mk
|
||||
CPPFLAGS+= -Wno-error=maybe-uninitialized
|
||||
|
||||
# for future gcc version, this could be needed: CPPFLAGS+= -Wno-error=format-overflow -Wno-error=stringop-truncation
|
||||
|
||||
|
||||
@@ -512,7 +512,7 @@ CONFIG_ESP_EVENT_POST_FROM_ISR=y
|
||||
CONFIG_ESP_EVENT_POST_FROM_IRAM_ISR=y
|
||||
CONFIG_ESP_HTTP_CLIENT_ENABLE_HTTPS=y
|
||||
|
||||
CONFIG_HTTPD_MAX_REQ_HDR_LEN=512
|
||||
CONFIG_HTTPD_MAX_REQ_HDR_LEN=1024
|
||||
CONFIG_HTTPD_MAX_URI_LEN=512
|
||||
CONFIG_HTTPD_ERR_RESP_NO_DELAY=y
|
||||
CONFIG_HTTPD_PURGE_BUF_LEN=32
|
||||
@@ -596,6 +596,7 @@ CONFIG_FREERTOS_NO_AFFINITY=0x7FFFFFFF
|
||||
CONFIG_FREERTOS_CORETIMER_0=y
|
||||
|
||||
CONFIG_FREERTOS_HZ=100
|
||||
CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER=y
|
||||
CONFIG_FREERTOS_ASSERT_ON_UNTESTED_FUNCTION=y
|
||||
|
||||
|
||||
|
||||
@@ -512,7 +512,7 @@ CONFIG_ESP_EVENT_POST_FROM_ISR=y
|
||||
CONFIG_ESP_EVENT_POST_FROM_IRAM_ISR=y
|
||||
CONFIG_ESP_HTTP_CLIENT_ENABLE_HTTPS=y
|
||||
|
||||
CONFIG_HTTPD_MAX_REQ_HDR_LEN=512
|
||||
CONFIG_HTTPD_MAX_REQ_HDR_LEN=1024
|
||||
CONFIG_HTTPD_MAX_URI_LEN=512
|
||||
CONFIG_HTTPD_ERR_RESP_NO_DELAY=y
|
||||
CONFIG_HTTPD_PURGE_BUF_LEN=32
|
||||
@@ -594,7 +594,7 @@ CONFIG_FMB_TIMER_INDEX=0
|
||||
|
||||
CONFIG_FREERTOS_NO_AFFINITY=0x7FFFFFFF
|
||||
CONFIG_FREERTOS_CORETIMER_0=y
|
||||
|
||||
CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER=y
|
||||
CONFIG_FREERTOS_HZ=100
|
||||
CONFIG_FREERTOS_ASSERT_ON_UNTESTED_FUNCTION=y
|
||||
|
||||
|
||||
@@ -513,7 +513,7 @@ CONFIG_ESP_EVENT_POST_FROM_ISR=y
|
||||
CONFIG_ESP_EVENT_POST_FROM_IRAM_ISR=y
|
||||
CONFIG_ESP_HTTP_CLIENT_ENABLE_HTTPS=y
|
||||
|
||||
CONFIG_HTTPD_MAX_REQ_HDR_LEN=512
|
||||
CONFIG_HTTPD_MAX_REQ_HDR_LEN=1024
|
||||
CONFIG_HTTPD_MAX_URI_LEN=512
|
||||
CONFIG_HTTPD_ERR_RESP_NO_DELAY=y
|
||||
CONFIG_HTTPD_PURGE_BUF_LEN=32
|
||||
@@ -597,6 +597,7 @@ CONFIG_FREERTOS_NO_AFFINITY=0x7FFFFFFF
|
||||
CONFIG_FREERTOS_CORETIMER_0=y
|
||||
|
||||
CONFIG_FREERTOS_HZ=100
|
||||
CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER=y
|
||||
CONFIG_FREERTOS_ASSERT_ON_UNTESTED_FUNCTION=y
|
||||
|
||||
|
||||
|
||||
@@ -512,7 +512,7 @@ CONFIG_ESP_EVENT_POST_FROM_ISR=y
|
||||
CONFIG_ESP_EVENT_POST_FROM_IRAM_ISR=y
|
||||
CONFIG_ESP_HTTP_CLIENT_ENABLE_HTTPS=y
|
||||
|
||||
CONFIG_HTTPD_MAX_REQ_HDR_LEN=512
|
||||
CONFIG_HTTPD_MAX_REQ_HDR_LEN=1024
|
||||
CONFIG_HTTPD_MAX_URI_LEN=512
|
||||
CONFIG_HTTPD_ERR_RESP_NO_DELAY=y
|
||||
CONFIG_HTTPD_PURGE_BUF_LEN=32
|
||||
@@ -596,6 +596,7 @@ CONFIG_FREERTOS_NO_AFFINITY=0x7FFFFFFF
|
||||
CONFIG_FREERTOS_CORETIMER_0=y
|
||||
|
||||
CONFIG_FREERTOS_HZ=100
|
||||
CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER=y
|
||||
CONFIG_FREERTOS_ASSERT_ON_UNTESTED_FUNCTION=y
|
||||
|
||||
|
||||
|
||||
@@ -512,7 +512,7 @@ CONFIG_ESP_EVENT_POST_FROM_ISR=y
|
||||
CONFIG_ESP_EVENT_POST_FROM_IRAM_ISR=y
|
||||
CONFIG_ESP_HTTP_CLIENT_ENABLE_HTTPS=y
|
||||
|
||||
CONFIG_HTTPD_MAX_REQ_HDR_LEN=512
|
||||
CONFIG_HTTPD_MAX_REQ_HDR_LEN=1024
|
||||
CONFIG_HTTPD_MAX_URI_LEN=512
|
||||
CONFIG_HTTPD_ERR_RESP_NO_DELAY=y
|
||||
CONFIG_HTTPD_PURGE_BUF_LEN=32
|
||||
@@ -596,6 +596,7 @@ CONFIG_FREERTOS_NO_AFFINITY=0x7FFFFFFF
|
||||
CONFIG_FREERTOS_CORETIMER_0=y
|
||||
|
||||
CONFIG_FREERTOS_HZ=100
|
||||
CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER=y
|
||||
CONFIG_FREERTOS_ASSERT_ON_UNTESTED_FUNCTION=y
|
||||
|
||||
|
||||
|
||||
@@ -506,7 +506,7 @@ CONFIG_ESP_EVENT_POST_FROM_ISR=y
|
||||
CONFIG_ESP_EVENT_POST_FROM_IRAM_ISR=y
|
||||
CONFIG_ESP_HTTP_CLIENT_ENABLE_HTTPS=y
|
||||
|
||||
CONFIG_HTTPD_MAX_REQ_HDR_LEN=512
|
||||
CONFIG_HTTPD_MAX_REQ_HDR_LEN=1024
|
||||
CONFIG_HTTPD_MAX_URI_LEN=512
|
||||
CONFIG_HTTPD_ERR_RESP_NO_DELAY=y
|
||||
CONFIG_HTTPD_PURGE_BUF_LEN=32
|
||||
@@ -590,6 +590,7 @@ CONFIG_FREERTOS_NO_AFFINITY=0x7FFFFFFF
|
||||
CONFIG_FREERTOS_CORETIMER_0=y
|
||||
|
||||
CONFIG_FREERTOS_HZ=100
|
||||
CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER=y
|
||||
CONFIG_FREERTOS_ASSERT_ON_UNTESTED_FUNCTION=y
|
||||
|
||||
|
||||
|
||||
113
build_flash_cmd.sh
Normal file
113
build_flash_cmd.sh
Normal file
@@ -0,0 +1,113 @@
|
||||
#!/bin/bash
|
||||
echo
|
||||
echo =================================================================
|
||||
echo Build flash command
|
||||
echo =================================================================
|
||||
# Location of partitions.csv relative to this script
|
||||
partitionsCsv="../partitions.csv"
|
||||
|
||||
# File to output readme instructions to
|
||||
outputReadme="./flash_cmd.txt"
|
||||
|
||||
# File to output bash script to
|
||||
outputBashScript="./writeSequeezeEsp.sh"
|
||||
|
||||
# File to output bat script to
|
||||
outputBatScript="./writeSequeezeEsp.bat"
|
||||
|
||||
# The name of partitions to ignore from partitions.csv
|
||||
paritionsToIgnore=(
|
||||
"nvs"
|
||||
"phy_init"
|
||||
"storage"
|
||||
"coredump"
|
||||
"settings"
|
||||
)
|
||||
|
||||
# Function that maps partition name to actual bin file
|
||||
# defaults to "[PARTION_NAME_FROM_CSV].bin"
|
||||
function partitionNameToBinFile {
|
||||
if [[ "$1" == "otadata" ]]; then
|
||||
echo "ota_data_initial.bin"
|
||||
elif [[ "$1" == "ota_0" || "$1" == "factory" ]]; then
|
||||
echo "squeezelite.bin"
|
||||
else
|
||||
echo $1.bin
|
||||
fi
|
||||
}
|
||||
|
||||
# write parameters for esptool.py
|
||||
writeParameters="$writeParameters write_flash"
|
||||
writeParameters="$writeParameters --flash_mode dio --flash_freq 80m --flash_size detect"
|
||||
|
||||
# bootloader.bin and partitions.bin not in partitions.csv so manually add here
|
||||
partitionsParameters=" 0x1000 bootloader/bootloader.bin"
|
||||
partitionsParameters="$partitionsParameters 0x8000 partitions.bin"
|
||||
|
||||
# ==============================================================================
|
||||
|
||||
# Loop over partitions.csv and add partition bins and offsets to partitionsParameters
|
||||
|
||||
for line in $($IDF_PATH/components/partition_table/gen_esp32part.py --quiet build/partitions.bin | grep '^[^#]')
|
||||
do
|
||||
partitionName=$(echo $line | awk -F',' '{printf "%s", $1}' )
|
||||
partitionOffset=$(echo $line |awk -F',' '{printf "%s", $4}' )
|
||||
partitionFile=$(partitionNameToBinFile $partitionName)
|
||||
|
||||
if [[ " ${paritionsToIgnore[@]} " =~ " ${partitionName} " ]]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
partitionsParameters="$partitionsParameters $partitionOffset $partitionFile"
|
||||
echo "$partitionsParameters"
|
||||
|
||||
done
|
||||
|
||||
# Write README Instructions
|
||||
if [ ! -f "$outputReadme" ]; then
|
||||
touch $outputReadme
|
||||
fi
|
||||
|
||||
echo "" >> $outputReadme
|
||||
echo "====LINUX====" >> $outputReadme
|
||||
echo "To flash sequeezelite run the following script:" >> $outputReadme
|
||||
echo "$outputBashScript [PORT_HERE] [BAUD_RATE]" >> $outputReadme
|
||||
echo "e.g. $outputBashScript /dev/ttyUSB0 115200" >> $outputReadme
|
||||
echo "" >> $outputReadme
|
||||
echo "====WINDOWS====" >> $outputReadme
|
||||
echo "To flash sequeezelite run the following script:" >> $outputReadme
|
||||
echo "$outputBatScript [PORT_HERE] [BAUD_RATE]" >> $outputReadme
|
||||
echo "e.g. $outputBatScript COM11 115200" >> $outputReadme
|
||||
echo "" >> $outputReadme
|
||||
echo "If you don't know how to run the BAT file with arguments then you can" >> $outputReadme
|
||||
echo "edit the bat file in Notepad. Open the file up and edit the following:" >> $outputReadme
|
||||
echo "Change 'set port=%1' to 'set port=[PORT_HERE]'. E.g. 'set port=COM11'" >> $outputReadme
|
||||
echo "Change 'set baud=%2' to 'set baud=[BAUD_RATE]'. E.g. 'set baud=115200'" >> $outputReadme
|
||||
echo "" >> $outputReadme
|
||||
echo "====MANUAL====" >> $outputReadme
|
||||
echo "Python esptool.py --port [PORT_HERE] --baud [BAUD_RATE] $writeParameters $partitionsParameters" >> $outputReadme
|
||||
|
||||
# Write Linux BASH File
|
||||
if [ ! -f "$outputBashScript" ]; then
|
||||
touch $outputBashScript
|
||||
fi
|
||||
|
||||
echo "#!/bin/bash" >> $outputBashScript
|
||||
echo >> $outputBashScript
|
||||
echo "port=\$1" >> $outputBashScript
|
||||
echo "baud=\$2" >> $outputBashScript
|
||||
linuxFlashCommand="Python esptool.py --port \$port --baud \$baud"
|
||||
echo "$linuxFlashCommand $writeParameters $partitionsParameters" >> $outputBashScript
|
||||
|
||||
# Write Windows BAT File
|
||||
if [ ! -f "$outputBatScript" ]; then
|
||||
touch $outputBatScript
|
||||
fi
|
||||
|
||||
echo "echo off" >> $outputBatScript
|
||||
echo "" >> $outputBatScript
|
||||
echo "set port=%1" >> $outputBatScript
|
||||
echo "set baud=%2" >> $outputBatScript
|
||||
windowsFlashCommand="Python esptool.py --port %port% --baud %baud%"
|
||||
echo "$windowsFlashCommand $writeParameters $partitionsParameters" >> $outputBatScript
|
||||
|
||||
@@ -21,6 +21,6 @@ COMPONENT_ADD_LDFLAGS=-l$(COMPONENT_NAME) \
|
||||
#$(COMPONENT_PATH)/lib/libesp-tremor.a
|
||||
#$(COMPONENT_PATH)/lib/libesp-ogg-container.a
|
||||
|
||||
|
||||
COMPONENT_ADD_INCLUDEDIRS := /inc
|
||||
|
||||
|
||||
|
||||
@@ -559,7 +559,7 @@ void config_delete_key(const char *key){
|
||||
ESP_LOGD(TAG, "Deleting nvs entry for [%s]", key);
|
||||
if(!config_lock(LOCK_MAX_WAIT/portTICK_PERIOD_MS)){
|
||||
ESP_LOGE(TAG, "Unable to lock config for delete");
|
||||
return false;
|
||||
return ;
|
||||
}
|
||||
esp_err_t err = nvs_open_from_partition(settings_partition, current_namespace, NVS_READWRITE, &nvs);
|
||||
if (err == ESP_OK) {
|
||||
@@ -663,7 +663,7 @@ char * config_alloc_get_json(bool bFormatted){
|
||||
config_unlock();
|
||||
return json_buffer;
|
||||
}
|
||||
esp_err_t config_set_value(nvs_type_t nvs_type, const char *key, void * value){
|
||||
esp_err_t config_set_value(nvs_type_t nvs_type, const char *key, const void * value){
|
||||
esp_err_t result = ESP_OK;
|
||||
if(!config_lock(LOCK_MAX_WAIT/portTICK_PERIOD_MS)){
|
||||
ESP_LOGE(TAG, "Unable to lock config after %d ms",LOCK_MAX_WAIT);
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <string.h>
|
||||
#include "nvs.h"
|
||||
#include "assert.h"
|
||||
#include "cJSON.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -12,7 +13,9 @@ extern "C" {
|
||||
#endif
|
||||
#define DECLARE_SET_DEFAULT(t) void config_set_default_## t (const char *key, t value);
|
||||
#define DECLARE_GET_NUM(t) esp_err_t config_get_## t (const char *key, t * value);
|
||||
|
||||
#ifndef FREE_RESET
|
||||
#define FREE_RESET(p) if(p!=NULL) { free(p); p=NULL; }
|
||||
#endif
|
||||
|
||||
DECLARE_SET_DEFAULT(uint8_t);
|
||||
DECLARE_SET_DEFAULT(uint16_t);
|
||||
@@ -37,5 +40,7 @@ void config_set_default(nvs_type_t type, const char *key, void * default_value,
|
||||
void * config_alloc_get(nvs_type_t nvs_type, const char *key) ;
|
||||
bool wait_for_commit();
|
||||
char * config_alloc_get_json(bool bFormatted);
|
||||
esp_err_t config_set_value(nvs_type_t nvs_type, const char *key, void * value);
|
||||
esp_err_t config_set_value(nvs_type_t nvs_type, const char *key, const void * value);
|
||||
nvs_type_t config_get_item_type(cJSON * entry);
|
||||
void * config_safe_alloc_get_entry_value(nvs_type_t nvs_type, cJSON * entry);
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include "platform_config.h"
|
||||
#include "esp_sleep.h"
|
||||
#include "driver/uart.h" // for the uart driver access
|
||||
#include "messaging.h"
|
||||
|
||||
#ifdef CONFIG_FREERTOS_USE_STATS_FORMATTING_FUNCTIONS
|
||||
#define WITH_TASKS_INFO 1
|
||||
@@ -105,8 +106,8 @@ if(is_recovery_running){
|
||||
if(!wait_for_commit()){
|
||||
ESP_LOGW(TAG,"Unable to commit configuration. ");
|
||||
}
|
||||
ESP_LOGW(TAG, "Restarting after tx complete");
|
||||
uart_wait_tx_done(UART_NUM_1, 500 / portTICK_RATE_MS);
|
||||
|
||||
vTaskDelay(750/ portTICK_PERIOD_MS);
|
||||
esp_restart();
|
||||
return ESP_OK;
|
||||
}
|
||||
@@ -117,8 +118,8 @@ else {
|
||||
if(!wait_for_commit()){
|
||||
ESP_LOGW(TAG,"Unable to commit configuration. ");
|
||||
}
|
||||
ESP_LOGW(TAG, "Restarting after tx complete");
|
||||
uart_wait_tx_done(UART_NUM_1, 500 / portTICK_RATE_MS);
|
||||
|
||||
vTaskDelay(750/ portTICK_PERIOD_MS);
|
||||
esp_restart();
|
||||
return ESP_OK;
|
||||
}
|
||||
@@ -131,7 +132,7 @@ else {
|
||||
|
||||
if(it == NULL){
|
||||
ESP_LOGE(TAG,"Unable initialize partition iterator!");
|
||||
set_status_message(ERROR, "Reboot failed. Cannot iterate through partitions");
|
||||
messaging_post_message(MESSAGING_ERROR,MESSAGING_CLASS_SYSTEM,"Reboot failed. Cannot iterate through partitions");
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -145,18 +146,19 @@ else {
|
||||
if(err!=ESP_OK){
|
||||
ESP_LOGE(TAG,"Unable to set partition as active for next boot. %s",esp_err_to_name(err));
|
||||
bFound=false;
|
||||
set_status_message(ERROR, "Unable to select partition for reboot.");
|
||||
messaging_post_message(MESSAGING_ERROR,MESSAGING_CLASS_SYSTEM,"Unable to select partition for reboot.");
|
||||
}
|
||||
else{
|
||||
ESP_LOGW(TAG, "Application partition %s sub type %u is selected for boot", partition->label,partition_subtype);
|
||||
bFound=true;
|
||||
set_status_message(WARNING, "Rebooting!");
|
||||
messaging_post_message(MESSAGING_WARNING,MESSAGING_CLASS_SYSTEM,"Reboot failed. Cannot iterate through partitions");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ESP_LOGE(TAG,"partition type %u not found! Unable to reboot to recovery.",partition_subtype);
|
||||
set_status_message(ERROR, "Partition not found.");
|
||||
messaging_post_message(MESSAGING_ERROR,MESSAGING_CLASS_SYSTEM,"partition type %u not found! Unable to reboot to recovery.",partition_subtype);
|
||||
|
||||
}
|
||||
ESP_LOGD(TAG, "Yielding to other processes");
|
||||
taskYIELD();
|
||||
@@ -165,8 +167,7 @@ else {
|
||||
if(!wait_for_commit()){
|
||||
ESP_LOGW(TAG,"Unable to commit configuration. ");
|
||||
}
|
||||
ESP_LOGW(TAG, "Restarting after tx complete");
|
||||
uart_wait_tx_done(UART_NUM_1, 500 / portTICK_RATE_MS);
|
||||
vTaskDelay(750/ portTICK_PERIOD_MS);
|
||||
esp_restart();
|
||||
}
|
||||
}
|
||||
@@ -180,8 +181,7 @@ static int restart(int argc, char **argv)
|
||||
if(!wait_for_commit()){
|
||||
ESP_LOGW(TAG,"Unable to commit configuration. ");
|
||||
}
|
||||
ESP_LOGW(TAG, "Restarting after tx complete");
|
||||
uart_wait_tx_done(UART_NUM_1, 500 / portTICK_RATE_MS);
|
||||
vTaskDelay(750/ portTICK_PERIOD_MS);
|
||||
esp_restart();
|
||||
return 0;
|
||||
}
|
||||
@@ -193,8 +193,8 @@ void simple_restart()
|
||||
ESP_LOGW(TAG,"Unable to commit configuration. ");
|
||||
}
|
||||
|
||||
ESP_LOGW(TAG, "Restarting after tx complete");
|
||||
uart_wait_tx_done(UART_NUM_1, 500 / portTICK_RATE_MS);
|
||||
|
||||
vTaskDelay(750/ portTICK_PERIOD_MS);
|
||||
esp_restart();
|
||||
}
|
||||
|
||||
|
||||
@@ -28,6 +28,15 @@
|
||||
#include "wifi_manager.h"
|
||||
|
||||
#include "platform_config.h"
|
||||
#include "telnet.h"
|
||||
#include "gds.h"
|
||||
#include "gds_default_if.h"
|
||||
#include "gds_draw.h"
|
||||
#include "gds_text.h"
|
||||
#include "gds_font.h"
|
||||
#include "display.h"
|
||||
#include "cmd_squeezelite.h"
|
||||
#include "config.h"
|
||||
pthread_t thread_console;
|
||||
static void * console_thread();
|
||||
void console_start();
|
||||
@@ -152,9 +161,24 @@ void initialize_console() {
|
||||
}
|
||||
|
||||
void console_start() {
|
||||
|
||||
if(is_recovery_running){
|
||||
GDS_ClearExt(display, true);
|
||||
GDS_SetFont(display, &Font_droid_sans_fallback_15x17 );
|
||||
GDS_TextPos(display, GDS_FONT_MEDIUM, GDS_TEXT_CENTERED, GDS_TEXT_CLEAR | GDS_TEXT_UPDATE, "RECOVERY");
|
||||
}
|
||||
if(!is_serial_suppressed()){
|
||||
initialize_console();
|
||||
|
||||
}
|
||||
else {
|
||||
/* Initialize the console */
|
||||
esp_console_config_t console_config = { .max_cmdline_args = 22,
|
||||
.max_cmdline_length = 600,
|
||||
#if CONFIG_LOG_COLORS
|
||||
.hint_color = atoi(LOG_COLOR_CYAN)
|
||||
#endif
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_console_init(&console_config));
|
||||
}
|
||||
/* Register commands */
|
||||
esp_console_register_help_command();
|
||||
register_system();
|
||||
@@ -167,6 +191,8 @@ void console_start() {
|
||||
register_ota_cmd();
|
||||
}
|
||||
register_i2ctools();
|
||||
|
||||
if(!is_serial_suppressed()){
|
||||
printf("\n");
|
||||
if(is_recovery_running){
|
||||
printf("****************************************************************\n"
|
||||
@@ -194,13 +220,12 @@ void console_start() {
|
||||
"On Windows, try using Putty instead.\n"
|
||||
"****************************\n");
|
||||
linenoiseSetDumbMode(1);
|
||||
#if CONFIG_LOG_COLORS
|
||||
#if CONFIG_LOG_COLORS
|
||||
/* Since the terminal doesn't support escape sequences,
|
||||
* don't use color codes in the prompt.
|
||||
*/
|
||||
prompt = "squeezelite-esp32> ";
|
||||
#endif //CONFIG_LOG_COLORS
|
||||
|
||||
#endif //CONFIG_LOG_COLORS
|
||||
}
|
||||
esp_pthread_cfg_t cfg = esp_pthread_get_default_config();
|
||||
cfg.thread_name= "console";
|
||||
@@ -214,6 +239,11 @@ void console_start() {
|
||||
|
||||
pthread_create(&thread_console, &attr, console_thread, NULL);
|
||||
pthread_attr_destroy(&attr);
|
||||
}
|
||||
else if(!is_recovery_running){
|
||||
process_autoexec();
|
||||
}
|
||||
|
||||
}
|
||||
void run_command(char * line){
|
||||
/* Try to run the command */
|
||||
@@ -221,15 +251,16 @@ void run_command(char * line){
|
||||
esp_err_t err = esp_console_run(line, &ret);
|
||||
|
||||
if (err == ESP_ERR_NOT_FOUND) {
|
||||
ESP_LOGE(TAG,"Unrecognized command: %s\n", line);
|
||||
ESP_LOGE(TAG,"Unrecognized command: %s", line);
|
||||
} else if (err == ESP_ERR_INVALID_ARG) {
|
||||
// command was empty
|
||||
} else if (err == ESP_OK && ret != ESP_OK) {
|
||||
ESP_LOGW(TAG,"Command returned non-zero error code: 0x%x (%s)\n", ret,
|
||||
ESP_LOGW(TAG,"Command returned non-zero error code: 0x%x (%s)", ret,
|
||||
esp_err_to_name(err));
|
||||
} else if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG,"Internal error: %s\n", esp_err_to_name(err));
|
||||
ESP_LOGE(TAG,"Internal error: %s", esp_err_to_name(err));
|
||||
}
|
||||
|
||||
}
|
||||
static void * console_thread() {
|
||||
if(!is_recovery_running){
|
||||
|
||||
@@ -7,7 +7,9 @@
|
||||
# please read the SDK documents if you need to do this.
|
||||
#
|
||||
|
||||
CFLAGS += -fstack-usage \
|
||||
-I$(COMPONENT_PATH)/../tools \
|
||||
-I$(COMPONENT_PATH)/../codecs/inc/alac \
|
||||
CFLAGS += -fstack-usage\
|
||||
-I$(PROJECT_PATH)/components/tools \
|
||||
-I$(PROJECT_PATH)/components/codecs/inc/alac \
|
||||
-I$(PROJECT_PATH)/main/
|
||||
COMPONENT_ADD_INCLUDEDIRS := .
|
||||
COMPONENT_SRCDIRS := .
|
||||
@@ -958,4 +958,3 @@ static void on_dmap_string(void *ctx, const char *code, const char *name, const
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
static void on_dmap_string(void *ctx, const char *code, const char *name, const char *buf, size_t len) {
|
||||
|
||||
@@ -511,14 +511,14 @@ static void buffer_push_packet(rtp_t *ctx) {
|
||||
int i;
|
||||
|
||||
// not ready to play yet
|
||||
if (!ctx->playing || ctx->synchro.status != (RTP_SYNC | NTP_SYNC)) return;
|
||||
|
||||
// maybe re-evaluate time in loop in case data callback blocks ...
|
||||
if (!ctx->playing || ctx->synchro.status != (RTP_SYNC | NTP_SYNC)) return;
|
||||
|
||||
// there is always at least one frame in the buffer
|
||||
do {
|
||||
// re-evaluate time in loop in case data callback blocks ...
|
||||
now = gettime_ms();
|
||||
|
||||
|
||||
// try to manage playtime so that we overflow as late as possible if we miss NTP (2^31 / 10 / 44100)
|
||||
curframe = ctx->audio_buffer + BUFIDX(ctx->ab_read);
|
||||
playtime = ctx->synchro.time + (((s32_t)(curframe->rtptime - ctx->synchro.rtp)) * 10) / (RAOP_SAMPLE_RATE / 100);
|
||||
|
||||
@@ -654,9 +654,14 @@ static void *rtp_thread_func(void *arg) {
|
||||
u32_t rtp_now_latency = ntohl(*(u32_t*)(pktp+4));
|
||||
u64_t remote = (((u64_t) ntohl(*(u32_t*)(pktp+8))) << 32) + ntohl(*(u32_t*)(pktp+12));
|
||||
u32_t rtp_now = ntohl(*(u32_t*)(pktp+16));
|
||||
u16_t flags = ntohs(*(u16_t*)(pktp+2));
|
||||
u16_t flags = ntohs(*(u16_t*)(pktp+2));
|
||||
u32_t remote_gap = NTP2MS(remote - ctx->timing.remote);
|
||||
|
||||
// try to get NTP every 3 sec or every time if we are not synced
|
||||
if (!count-- || !(ctx->synchro.status && NTP_SYNC)) {
|
||||
rtp_request_timing(ctx);
|
||||
count = 3;
|
||||
}
|
||||
|
||||
|
||||
// something is wrong, we should not have such gap
|
||||
if (remote_gap > 10000) {
|
||||
@@ -684,11 +689,6 @@ static void *rtp_thread_func(void *arg) {
|
||||
|
||||
pthread_mutex_unlock(&ctx->ab_mutex);
|
||||
|
||||
LOG_DEBUG("[%p]: sync packet latency:%d rtp_latency:%u rtp:%u remote ntp:%llx, local time:%u local rtp:%u (now:%u)",
|
||||
ctx, ctx->latency, rtp_now_latency, rtp_now, remote, ctx->synchro.time, ctx->synchro.rtp, gettime_ms());
|
||||
|
||||
if (!count--) {
|
||||
rtp_request_timing(ctx);
|
||||
LOG_DEBUG("[%p]: sync packet latency:%d rtp_latency:%u rtp:%u remote ntp:%llx, local time:%u local rtp:%u (now:%u)",
|
||||
ctx, ctx->latency, rtp_now_latency, rtp_now, remote, ctx->synchro.time, ctx->synchro.rtp, gettime_ms());
|
||||
|
||||
@@ -786,7 +786,7 @@ static bool rtp_request_resend(rtp_t *ctx, seq_t first, seq_t last) {
|
||||
static bool rtp_request_resend(rtp_t *ctx, seq_t first, seq_t last) {
|
||||
unsigned char req[8]; // *not* a standard RTCP NACK
|
||||
|
||||
// do not request silly ranges (happens in case of network large blackouts)
|
||||
// do not request silly ranges (happens in case of network large blackouts)
|
||||
if (seq_order(last, first) || last - first > BUFFER_FRAMES / 2) return false;
|
||||
|
||||
ctx->resent_req += (seq_t) (last - first) + 1;
|
||||
|
||||
@@ -588,7 +588,8 @@ void free_metadata(struct metadata_s *metadata)
|
||||
NFREE(metadata->remote_title);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
int _fprintf(FILE *file, ...)
|
||||
{
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
//#define LOG_LOCAL_LEVEL ESP_LOG_DEBUG
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
@@ -9,3 +9,4 @@
|
||||
|
||||
COMPONENT_SRCDIRS := .
|
||||
COMPONENT_ADD_INCLUDEDIRS := .
|
||||
CFLAGS += -D LOG_LOCAL_LEVEL=ESP_LOG_DEBUG
|
||||
230
components/services/messaging.c
Normal file
230
components/services/messaging.c
Normal file
@@ -0,0 +1,230 @@
|
||||
/**
|
||||
*
|
||||
*/
|
||||
#include <stdlib.h> // Required for libtelnet.h
|
||||
#include <esp_log.h>
|
||||
#include "stdbool.h"
|
||||
#include <lwip/def.h>
|
||||
#include <lwip/sockets.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include "esp_app_trace.h"
|
||||
#include "esp_attr.h"
|
||||
#include "config.h"
|
||||
#include "nvs_utilities.h"
|
||||
#include "platform_esp32.h"
|
||||
#include "messaging.h"
|
||||
#include "trace.h"
|
||||
/************************************
|
||||
* Globals
|
||||
*/
|
||||
|
||||
const static char tag[] = "messaging";
|
||||
typedef struct {
|
||||
struct messaging_list_t * next;
|
||||
char * subscriber_name;
|
||||
size_t max_count;
|
||||
RingbufHandle_t buf_handle;
|
||||
} messaging_list_t;
|
||||
static messaging_list_t top;
|
||||
#define MSG_LENGTH_AVG 1024
|
||||
|
||||
messaging_list_t * get_struct_ptr(messaging_handle_t handle){
|
||||
return (messaging_list_t *)handle;
|
||||
}
|
||||
messaging_handle_t get_handle_ptr(messaging_list_t * handle){
|
||||
return (messaging_handle_t )handle;
|
||||
}
|
||||
|
||||
RingbufHandle_t messaging_create_ring_buffer(uint8_t max_count){
|
||||
RingbufHandle_t buf_handle = NULL;
|
||||
StaticRingbuffer_t *buffer_struct = malloc(sizeof(StaticRingbuffer_t));
|
||||
if (buffer_struct != NULL) {
|
||||
size_t buf_size = (size_t )(sizeof(single_message_t)+8+MSG_LENGTH_AVG)*(size_t )(max_count>0?max_count:5); // no-split buffer requires an additional 8 bytes
|
||||
buf_size = buf_size - (buf_size % 4);
|
||||
uint8_t *buffer_storage = (uint8_t *)heap_caps_malloc(buf_size, MALLOC_CAP_SPIRAM | MALLOC_CAP_32BIT);
|
||||
if (buffer_storage== NULL) {
|
||||
ESP_LOGE(tag,"buff alloc failed");
|
||||
}
|
||||
else {
|
||||
buf_handle = xRingbufferCreateStatic(buf_size, RINGBUF_TYPE_NOSPLIT, buffer_storage, buffer_struct);
|
||||
}
|
||||
}
|
||||
else {
|
||||
ESP_LOGE(tag,"ringbuf alloc failed");
|
||||
}
|
||||
return buf_handle;
|
||||
}
|
||||
void messaging_fill_messages(messaging_list_t * target_subscriber){
|
||||
single_message_t * message=NULL;
|
||||
UBaseType_t uxItemsWaiting;
|
||||
|
||||
vRingbufferGetInfo(top.buf_handle, NULL, NULL, NULL, NULL, &uxItemsWaiting);
|
||||
for(size_t i=0;i<uxItemsWaiting;i++){
|
||||
message= messaging_retrieve_message(top.buf_handle);
|
||||
if(message){
|
||||
//re-post to original queue so it is available to future subscribers
|
||||
messaging_post_to_queue(get_handle_ptr(&top), message, message->msg_size);
|
||||
// post to new subscriber
|
||||
messaging_post_to_queue(get_handle_ptr(target_subscriber) , message, message->msg_size);
|
||||
FREE_AND_NULL(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
messaging_handle_t messaging_register_subscriber(uint8_t max_count, char * name){
|
||||
messaging_list_t * cur=⊤
|
||||
while(cur->next){
|
||||
cur = get_struct_ptr(cur->next);
|
||||
}
|
||||
cur->next=heap_caps_malloc(sizeof(messaging_list_t), MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
|
||||
if(!cur->next){
|
||||
ESP_LOGE(tag,"subscriber alloc failed");
|
||||
return NULL;
|
||||
}
|
||||
memset(cur->next,0x00,sizeof(messaging_list_t));
|
||||
cur = get_struct_ptr(cur->next);
|
||||
cur->max_count=max_count;
|
||||
cur->subscriber_name=strdup(name);
|
||||
cur->buf_handle = messaging_create_ring_buffer(max_count);
|
||||
if(cur->buf_handle){
|
||||
messaging_fill_messages(cur);
|
||||
}
|
||||
return cur->buf_handle;
|
||||
}
|
||||
void messaging_service_init(){
|
||||
size_t max_count=15;
|
||||
top.buf_handle = messaging_create_ring_buffer(max_count);
|
||||
if(!top.buf_handle){
|
||||
ESP_LOGE(tag, "messaging service init failed.");
|
||||
}
|
||||
else {
|
||||
top.max_count = max_count;
|
||||
top.subscriber_name = strdup("messaging");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const char * messaging_get_type_desc(messaging_types msg_type){
|
||||
switch (msg_type) {
|
||||
CASE_TO_STR(MESSAGING_INFO);
|
||||
CASE_TO_STR(MESSAGING_WARNING);
|
||||
CASE_TO_STR(MESSAGING_ERROR);
|
||||
default:
|
||||
return "Unknown";
|
||||
break;
|
||||
}
|
||||
}
|
||||
const char * messaging_get_class_desc(messaging_classes msg_class){
|
||||
switch (msg_class) {
|
||||
CASE_TO_STR(MESSAGING_CLASS_OTA);
|
||||
CASE_TO_STR(MESSAGING_CLASS_SYSTEM);
|
||||
CASE_TO_STR(MESSAGING_CLASS_STATS);
|
||||
default:
|
||||
return "Unknown";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
cJSON * messaging_retrieve_messages(RingbufHandle_t buf_handle){
|
||||
single_message_t * message=NULL;
|
||||
cJSON * json_messages=cJSON_CreateArray();
|
||||
cJSON * json_message=NULL;
|
||||
size_t item_size;
|
||||
UBaseType_t uxItemsWaiting;
|
||||
vRingbufferGetInfo(buf_handle, NULL, NULL, NULL, NULL, &uxItemsWaiting);
|
||||
for(int i = 0;i<uxItemsWaiting;i++){
|
||||
message = (single_message_t *)xRingbufferReceive(buf_handle, &item_size, pdMS_TO_TICKS(50));
|
||||
//Check received data
|
||||
if (message== NULL) {
|
||||
ESP_LOGE(tag,"received null ptr");
|
||||
}
|
||||
else {
|
||||
json_message = cJSON_CreateObject();
|
||||
cJSON_AddStringToObject(json_message, "message", message->message);
|
||||
vRingbufferReturnItem(buf_handle, (void *)message);
|
||||
cJSON_AddStringToObject(json_message, "type", messaging_get_type_desc(message->type));
|
||||
cJSON_AddStringToObject(json_message, "class", messaging_get_class_desc(message->msg_class));
|
||||
cJSON_AddNumberToObject(json_message,"sent_time",message->sent_time);
|
||||
cJSON_AddNumberToObject(json_message,"current_time",esp_timer_get_time() / 1000);
|
||||
cJSON_AddItemToArray(json_messages,json_message);
|
||||
}
|
||||
}
|
||||
return json_messages;
|
||||
}
|
||||
single_message_t * messaging_retrieve_message(RingbufHandle_t buf_handle){
|
||||
single_message_t * message=NULL;
|
||||
single_message_t * message_copy=NULL;
|
||||
size_t item_size;
|
||||
UBaseType_t uxItemsWaiting;
|
||||
vRingbufferGetInfo(buf_handle, NULL, NULL, NULL, NULL, &uxItemsWaiting);
|
||||
if(uxItemsWaiting>0){
|
||||
message = (single_message_t *)xRingbufferReceive(buf_handle, &item_size, pdMS_TO_TICKS(50));
|
||||
message_copy = heap_caps_malloc(item_size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
|
||||
if(message_copy){
|
||||
memcpy(message_copy,message,item_size);
|
||||
}
|
||||
vRingbufferReturnItem(buf_handle, (void *)message);
|
||||
}
|
||||
return message_copy;
|
||||
}
|
||||
|
||||
esp_err_t messaging_post_to_queue(messaging_handle_t subscriber_handle, single_message_t * message, size_t message_size){
|
||||
size_t item_size=0;
|
||||
messaging_list_t * subscriber=get_struct_ptr(subscriber_handle);
|
||||
if(!subscriber->buf_handle){
|
||||
ESP_LOGE(tag,"post failed: null buffer for %s", str_or_unknown(subscriber->subscriber_name));
|
||||
return ESP_FAIL;
|
||||
}
|
||||
void * pItem=NULL;
|
||||
UBaseType_t res=pdFALSE;
|
||||
while(1){
|
||||
ESP_LOGD(tag,"Attempting to reserve %d bytes for %s",message_size, str_or_unknown(subscriber->subscriber_name));
|
||||
res = xRingbufferSendAcquire(subscriber->buf_handle, &pItem, message_size, pdMS_TO_TICKS(50));
|
||||
if(res == pdTRUE && pItem){
|
||||
ESP_LOGD(tag,"Reserving complete for %s", str_or_unknown(subscriber->subscriber_name));
|
||||
memcpy(pItem,message,message_size);
|
||||
xRingbufferSendComplete(subscriber->buf_handle, pItem);
|
||||
break;
|
||||
}
|
||||
ESP_LOGD(tag,"Dropping for %s",str_or_unknown(subscriber->subscriber_name));
|
||||
single_message_t * dummy = (single_message_t *)xRingbufferReceive(subscriber->buf_handle, &item_size, pdMS_TO_TICKS(50));
|
||||
if (dummy== NULL) {
|
||||
ESP_LOGE(tag,"Dropping message failed");
|
||||
break;
|
||||
}
|
||||
else {
|
||||
ESP_LOGD(tag,"Dropping message of %d bytes for %s",item_size, str_or_unknown(subscriber->subscriber_name));
|
||||
vRingbufferReturnItem(subscriber->buf_handle, (void *)dummy);
|
||||
}
|
||||
}
|
||||
if (res != pdTRUE) {
|
||||
ESP_LOGE(tag,"post to %s failed",str_or_unknown(subscriber->subscriber_name));
|
||||
return ESP_FAIL;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
void messaging_post_message(messaging_types type,messaging_classes msg_class, char *fmt, ...){
|
||||
single_message_t * message=NULL;
|
||||
size_t msg_size=0;
|
||||
size_t ln =0;
|
||||
messaging_list_t * cur=⊤
|
||||
va_list va;
|
||||
va_start(va, fmt);
|
||||
ln = vsnprintf(NULL, 0, fmt, va)+1;
|
||||
msg_size = sizeof(single_message_t)+ln;
|
||||
message = (single_message_t *)heap_caps_malloc(msg_size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
|
||||
vsprintf(message->message, fmt, va);
|
||||
va_end(va);
|
||||
message->msg_size = msg_size;
|
||||
message->type = type;
|
||||
message->msg_class = msg_class;
|
||||
message->sent_time = esp_timer_get_time() / 1000;
|
||||
ESP_LOGD(tag,"Post: %s",message->message);
|
||||
while(cur){
|
||||
messaging_post_to_queue(get_handle_ptr(cur), message, msg_size);
|
||||
cur = get_struct_ptr(cur->next);
|
||||
}
|
||||
FREE_AND_NULL(message);
|
||||
return;
|
||||
|
||||
}
|
||||
32
components/services/messaging.h
Normal file
32
components/services/messaging.h
Normal file
@@ -0,0 +1,32 @@
|
||||
#include "sdkconfig.h"
|
||||
#include "freertos/ringbuf.h"
|
||||
#include "cJSON.h"
|
||||
#pragma once
|
||||
typedef enum {
|
||||
MESSAGING_INFO,
|
||||
MESSAGING_WARNING,
|
||||
MESSAGING_ERROR
|
||||
} messaging_types;
|
||||
typedef enum {
|
||||
MESSAGING_CLASS_OTA,
|
||||
MESSAGING_CLASS_SYSTEM,
|
||||
MESSAGING_CLASS_STATS
|
||||
} messaging_classes;
|
||||
|
||||
typedef struct messaging_list_t *messaging_handle_t;
|
||||
|
||||
typedef struct {
|
||||
time_t sent_time;
|
||||
messaging_types type;
|
||||
messaging_classes msg_class;
|
||||
size_t msg_size;
|
||||
char message[];
|
||||
} single_message_t;
|
||||
|
||||
cJSON * messaging_retrieve_messages(RingbufHandle_t buf_handle);
|
||||
messaging_handle_t messaging_register_subscriber(uint8_t max_count, char * name);
|
||||
esp_err_t messaging_post_to_queue(messaging_handle_t subscriber_handle, single_message_t * message, size_t message_size);
|
||||
void messaging_post_message(messaging_types type,messaging_classes msg_class, char * fmt, ...);
|
||||
cJSON * messaging_retrieve_messages(RingbufHandle_t buf_handle);
|
||||
single_message_t * messaging_retrieve_message(RingbufHandle_t buf_handle);
|
||||
void messaging_service_init();
|
||||
@@ -21,6 +21,9 @@
|
||||
#include "globdefs.h"
|
||||
#include "platform_config.h"
|
||||
#include "accessors.h"
|
||||
#include "messaging.h"
|
||||
#include "cJSON.h"
|
||||
#include "trace.h"
|
||||
|
||||
#define MONITOR_TIMER (10*1000)
|
||||
#define SCRATCH_SIZE 256
|
||||
@@ -44,16 +47,17 @@ bool spkfault_svc(void);
|
||||
/****************************************************************************************
|
||||
*
|
||||
*/
|
||||
static void task_stats( void ) {
|
||||
static void task_stats( cJSON* top ) {
|
||||
#ifdef CONFIG_FREERTOS_USE_TRACE_FACILITY
|
||||
static struct {
|
||||
TaskStatus_t *tasks;
|
||||
uint32_t total, n;
|
||||
} current, previous;
|
||||
|
||||
cJSON * tlist=cJSON_CreateArray();
|
||||
current.n = uxTaskGetNumberOfTasks();
|
||||
current.tasks = malloc( current.n * sizeof( TaskStatus_t ) );
|
||||
current.n = uxTaskGetSystemState( current.tasks, current.n, ¤t.total );
|
||||
cJSON_AddNumberToObject(top,"ntasks",current.n);
|
||||
|
||||
static EXT_RAM_ATTR char scratch[SCRATCH_SIZE];
|
||||
*scratch = '\0';
|
||||
@@ -68,6 +72,15 @@ static void task_stats( void ) {
|
||||
current.tasks[i].eCurrentState,
|
||||
100 * (current.tasks[i].ulRunTimeCounter - previous.tasks[j].ulRunTimeCounter) / elapsed,
|
||||
current.tasks[i].usStackHighWaterMark);
|
||||
cJSON * t=cJSON_CreateObject();
|
||||
cJSON_AddNumberToObject(t,"cpu",100 * (current.tasks[i].ulRunTimeCounter - previous.tasks[j].ulRunTimeCounter) / elapsed);
|
||||
cJSON_AddNumberToObject(t,"minstk",current.tasks[i].usStackHighWaterMark);
|
||||
cJSON_AddNumberToObject(t,"bprio",current.tasks[i].uxBasePriority);
|
||||
cJSON_AddNumberToObject(t,"cprio",current.tasks[i].uxCurrentPriority);
|
||||
cJSON_AddStringToObject(t,"nme",current.tasks[i].pcTaskName);
|
||||
cJSON_AddNumberToObject(t,"st",current.tasks[i].eCurrentState);
|
||||
cJSON_AddNumberToObject(t,"num",current.tasks[i].xTaskNumber);
|
||||
cJSON_AddItemToArray(tlist,t);
|
||||
if (i % 3 == 2 || i == current.n - 1) {
|
||||
ESP_LOGI(TAG, "%s", scratch);
|
||||
n = 0;
|
||||
@@ -79,13 +92,21 @@ static void task_stats( void ) {
|
||||
#else
|
||||
for (int i = 0, n = 0; i < current.n; i ++) {
|
||||
n += sprintf(scratch + n, "%16s s:%5u\t", current.tasks[i].pcTaskName, current.tasks[i].usStackHighWaterMark);
|
||||
cJSON * t=cJSON_CreateObject();
|
||||
cJSON_AddNumberToObject(t,"minstk",current.tasks[i].usStackHighWaterMark);
|
||||
cJSON_AddNumberToObject(t,"bprio",current.tasks[i].uxBasePriority);
|
||||
cJSON_AddNumberToObject(t,"cprio",current.tasks[i].uxCurrentPriority);
|
||||
cJSON_AddStringToObject(t,"nme",current.tasks[i].pcTaskName);
|
||||
cJSON_AddStringToObject(t,"st",current.tasks[i].eCurrentState);
|
||||
cJSON_AddNumberToObject(t,"num",current.tasks[i].xTaskNumber);
|
||||
cJSON_AddItemToArray(tlist,t);
|
||||
if (i % 3 == 2 || i == current.n - 1) {
|
||||
ESP_LOGI(TAG, "%s", scratch);
|
||||
n = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
cJSON_AddItemToObject(top,"tasks",tlist);
|
||||
if (previous.tasks) free(previous.tasks);
|
||||
previous = current;
|
||||
#endif
|
||||
@@ -95,13 +116,26 @@ static void task_stats( void ) {
|
||||
*
|
||||
*/
|
||||
static void monitor_callback(TimerHandle_t xTimer) {
|
||||
cJSON * top=cJSON_CreateObject();
|
||||
cJSON_AddNumberToObject(top,"free_iram",heap_caps_get_free_size(MALLOC_CAP_INTERNAL));
|
||||
cJSON_AddNumberToObject(top,"min_free_iram",heap_caps_get_minimum_free_size(MALLOC_CAP_INTERNAL));
|
||||
cJSON_AddNumberToObject(top,"free_spiram",heap_caps_get_free_size(MALLOC_CAP_SPIRAM));
|
||||
cJSON_AddNumberToObject(top,"min_free_spiram",heap_caps_get_minimum_free_size(MALLOC_CAP_SPIRAM));
|
||||
|
||||
ESP_LOGI(TAG, "Heap internal:%zu (min:%zu) external:%zu (min:%zu)",
|
||||
heap_caps_get_free_size(MALLOC_CAP_INTERNAL),
|
||||
heap_caps_get_minimum_free_size(MALLOC_CAP_INTERNAL),
|
||||
heap_caps_get_free_size(MALLOC_CAP_SPIRAM),
|
||||
heap_caps_get_minimum_free_size(MALLOC_CAP_SPIRAM));
|
||||
|
||||
task_stats();
|
||||
task_stats(top);
|
||||
char * top_a= cJSON_PrintUnformatted(top);
|
||||
if(top_a){
|
||||
messaging_post_message(MESSAGING_INFO, MESSAGING_CLASS_STATS,top_a);
|
||||
FREE_AND_NULL(top_a);
|
||||
}
|
||||
cJSON_free(top);
|
||||
|
||||
}
|
||||
|
||||
/****************************************************************************************
|
||||
@@ -109,6 +143,7 @@ static void monitor_callback(TimerHandle_t xTimer) {
|
||||
*/
|
||||
static void jack_handler_default(void *id, button_event_e event, button_press_e mode, bool long_press) {
|
||||
ESP_LOGD(TAG, "Jack %s", event == BUTTON_PRESSED ? "inserted" : "removed");
|
||||
messaging_post_message(MESSAGING_INFO, MESSAGING_CLASS_SYSTEM,"jack is %s",BUTTON_PRESSED ? "inserted" : "removed");
|
||||
if (jack_handler_svc) (*jack_handler_svc)(event == BUTTON_PRESSED);
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "monitor.h"
|
||||
#include "globdefs.h"
|
||||
#include "accessors.h"
|
||||
#include "messaging.h"
|
||||
|
||||
extern void battery_svc_init(void);
|
||||
extern void monitor_svc_init(void);
|
||||
@@ -52,6 +53,7 @@ void set_power_gpio(int gpio, char *value) {
|
||||
*
|
||||
*/
|
||||
void services_init(void) {
|
||||
messaging_service_init();
|
||||
gpio_install_isr_service(0);
|
||||
|
||||
#ifdef CONFIG_I2C_LOCKED
|
||||
|
||||
@@ -5,9 +5,6 @@
|
||||
|
||||
# todo: add support for https
|
||||
COMPONENT_ADD_INCLUDEDIRS := .
|
||||
COMPONENT_ADD_INCLUDEDIRS += include
|
||||
COMPONENT_EXTRA_INCLUDES += $(PROJECT_PATH)/main/
|
||||
COMPONENT_EXTRA_INCLUDES += $(PROJECT_PATH)/components/tools
|
||||
CFLAGS += -D LOG_LOCAL_LEVEL=ESP_LOG_INFO -DCONFIG_OTA_ALLOW_HTTP=1
|
||||
#CFLAGS += -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG -DCONFIG_OTA_ALLOW_HTTP=1
|
||||
|
||||
|
||||
|
||||
@@ -6,9 +6,6 @@
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
#ifndef LOG_LOCAL_LEVEL
|
||||
#define LOG_LOCAL_LEVEL ESP_LOG_INFO
|
||||
#endif
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_system.h"
|
||||
@@ -23,46 +20,69 @@
|
||||
#include "esp_err.h"
|
||||
#include "tcpip_adapter.h"
|
||||
#include "squeezelite-ota.h"
|
||||
#include "platform_config.h"
|
||||
#include "platform_esp32.h"
|
||||
#include "config.h"
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#include <stdarg.h>
|
||||
#include "esp_secure_boot.h"
|
||||
#include "esp_flash_encrypt.h"
|
||||
#include "esp_spi_flash.h"
|
||||
#include "platform_esp32.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#include "messaging.h"
|
||||
#include "trace.h"
|
||||
#include "esp_ota_ops.h"
|
||||
#include "display.h"
|
||||
#include "gds.h"
|
||||
#include "gds_text.h"
|
||||
#include "gds_draw.h"
|
||||
|
||||
extern const char * get_certificate();
|
||||
|
||||
#ifdef CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_1
|
||||
#define OTA_CORE 0
|
||||
#else
|
||||
#define OTA_CORE 1
|
||||
#endif
|
||||
|
||||
static const char *TAG = "squeezelite-ota";
|
||||
char * ota_write_data = NULL;
|
||||
esp_http_client_handle_t ota_http_client = NULL;
|
||||
#define IMAGE_HEADER_SIZE sizeof(esp_image_header_t) + sizeof(esp_image_segment_header_t) + sizeof(esp_app_desc_t) + 1
|
||||
#define BUFFSIZE 4096
|
||||
#define HASH_LEN 32 /* SHA-256 digest length */
|
||||
|
||||
typedef struct {
|
||||
char * url;
|
||||
char * bin;
|
||||
uint32_t length;
|
||||
} ota_thread_parms_t ;
|
||||
static ota_thread_parms_t ota_thread_parms;
|
||||
typedef enum {
|
||||
OTA_TYPE_HTTP,
|
||||
OTA_TYPE_BUFFER,
|
||||
OTA_TYPE_INVALID
|
||||
} ota_type_t;
|
||||
|
||||
static struct {
|
||||
char status_text[81];
|
||||
uint32_t ota_actual_len;
|
||||
uint32_t ota_total_len;
|
||||
char * redirected_url;
|
||||
char * current_url;
|
||||
uint32_t actual_image_len;
|
||||
uint32_t total_image_len;
|
||||
uint32_t remain_image_len;
|
||||
ota_type_t ota_type;
|
||||
char * ota_write_data;
|
||||
char * bin_data;
|
||||
bool bOTAStarted;
|
||||
bool bInitialized;
|
||||
size_t buffer_size;
|
||||
uint8_t lastpct;
|
||||
uint8_t newpct;
|
||||
struct timeval OTA_start;
|
||||
bool bOTAThreadStarted;
|
||||
|
||||
const esp_partition_t *configured;
|
||||
const esp_partition_t *running;
|
||||
const esp_partition_t * update_partition;
|
||||
const esp_partition_t* last_invalid_app ;
|
||||
const esp_partition_t * ota_partition;
|
||||
} ota_status;
|
||||
struct timeval tv;
|
||||
static esp_http_client_config_t ota_config;
|
||||
|
||||
extern void wifi_manager_refresh_ota_json();
|
||||
struct timeval tv;
|
||||
static esp_http_client_config_t http_client_config;
|
||||
|
||||
void _printMemStats(){
|
||||
ESP_LOGD(TAG,"Heap internal:%zu (min:%zu) external:%zu (min:%zu)",
|
||||
@@ -71,35 +91,121 @@ void _printMemStats(){
|
||||
heap_caps_get_free_size(MALLOC_CAP_SPIRAM),
|
||||
heap_caps_get_minimum_free_size(MALLOC_CAP_SPIRAM));
|
||||
}
|
||||
void triggerStatusJsonRefresh(bool bDelay,const char * status, ...){
|
||||
va_list args;
|
||||
va_start(args, status);
|
||||
vsnprintf(ota_status.status_text,sizeof(ota_status.status_text)-1,status, args);
|
||||
va_end(args);
|
||||
_printMemStats();
|
||||
wifi_manager_refresh_ota_json();
|
||||
if(bDelay){
|
||||
ESP_LOGD(TAG,"Holding task...");
|
||||
vTaskDelay(200 / portTICK_PERIOD_MS); // wait here for a short amount of time. This will help with refreshing the UI status
|
||||
ESP_LOGD(TAG,"Done holding task...");
|
||||
uint8_t ota_get_pct_complete(){
|
||||
return ota_status.total_image_len==0?0:
|
||||
(uint8_t)((float)ota_status.actual_image_len/(float)ota_status.total_image_len*100.0f);
|
||||
}
|
||||
typedef struct {
|
||||
int x1,y1,x2,y2,width,height;
|
||||
} rect_t;
|
||||
typedef struct _progress {
|
||||
int border_thickness;
|
||||
int sides_margin;
|
||||
int vertical_margin;
|
||||
int bar_tot_height;
|
||||
int bar_fill_height;
|
||||
rect_t border;
|
||||
rect_t filler;
|
||||
} progress_t;
|
||||
|
||||
static progress_t * loc_displayer_get_progress_dft(){
|
||||
int start_coord_offset=0;
|
||||
static progress_t def={
|
||||
.border_thickness = 2,
|
||||
.sides_margin = 2,
|
||||
.bar_tot_height = 7,
|
||||
};
|
||||
def.bar_fill_height= def.bar_tot_height-(def.border_thickness*2);
|
||||
def.border.x1=start_coord_offset+def.sides_margin;
|
||||
def.border.x2=GDS_GetWidth(display)-def.sides_margin;
|
||||
// progress bar will be drawn at the bottom of the display
|
||||
def.border.y2= GDS_GetHeight(display)-def.border_thickness;
|
||||
def.border.y1= def.border.y2-def.bar_tot_height;
|
||||
def.border.width=def.border.x2-def.border.x1;
|
||||
def.border.height=def.border.y2-def.border.y1;
|
||||
def.filler.x1= def.border.x1+def.border_thickness;
|
||||
def.filler.x2= def.border.x2-def.border_thickness;
|
||||
def.filler.y1= def.border.y1+def.border_thickness;
|
||||
def.filler.y2= def.border.y2-def.border_thickness;
|
||||
def.filler.width=def.filler.x2-def.filler.x1;
|
||||
def.filler.height=def.filler.y2-def.filler.y1;
|
||||
assert(def.filler.width>0);
|
||||
assert(def.filler.height>0);
|
||||
assert(def.border.width>0);
|
||||
assert(def.border.height>0);
|
||||
assert(def.border.width>def.filler.width);
|
||||
assert(def.border.height>def.filler.height);
|
||||
return &def;
|
||||
|
||||
}
|
||||
static void loc_displayer_progressbar(uint8_t pct){
|
||||
static progress_t * progress_coordinates;
|
||||
if(!progress_coordinates) progress_coordinates = loc_displayer_get_progress_dft();
|
||||
int filler_x=progress_coordinates->filler.x1+(int)((float)progress_coordinates->filler.width*(float)pct/(float)100);
|
||||
|
||||
ESP_LOGD(TAG,"Drawing %d,%d,%d,%d",progress_coordinates->border.x1,progress_coordinates->border.y1,progress_coordinates->border.x2,progress_coordinates->border.y2);
|
||||
GDS_DrawBox(display,progress_coordinates->border.x1,progress_coordinates->border.y1,progress_coordinates->border.x2,progress_coordinates->border.y2,GDS_COLOR_WHITE,false);
|
||||
ESP_LOGD(TAG,"Drawing %d,%d,%d,%d",progress_coordinates->filler.x1,progress_coordinates->filler.y1,filler_x,progress_coordinates->filler.y2);
|
||||
if(filler_x > progress_coordinates->filler.x1){
|
||||
GDS_DrawBox(display,progress_coordinates->filler.x1,progress_coordinates->filler.y1,filler_x,progress_coordinates->filler.y2,GDS_COLOR_WHITE,true);
|
||||
}
|
||||
else {
|
||||
ESP_LOGI(TAG,"%s",ota_status.status_text);
|
||||
taskYIELD();
|
||||
// Clear the inner box
|
||||
GDS_DrawBox(display,progress_coordinates->filler.x1,progress_coordinates->filler.y1,progress_coordinates->filler.x2,progress_coordinates->filler.y2,GDS_COLOR_BLACK,true);
|
||||
}
|
||||
ESP_LOGD(TAG,"Updating Display");
|
||||
GDS_Update(display);
|
||||
}
|
||||
const char * ota_get_status(){
|
||||
if(!ota_status.bInitialized)
|
||||
{
|
||||
memset(ota_status.status_text, 0x00,sizeof(ota_status.status_text));
|
||||
ota_status.bInitialized = true;
|
||||
void sendMessaging(messaging_types type,const char * fmt, ...){
|
||||
va_list args;
|
||||
cJSON * msg = cJSON_CreateObject();
|
||||
size_t str_len=0;
|
||||
char * msg_str=NULL;
|
||||
|
||||
va_start(args, fmt);
|
||||
str_len = vsnprintf(NULL,0,fmt,args)+1;
|
||||
if(str_len>0){
|
||||
msg_str = malloc(str_len);
|
||||
vsnprintf(msg_str,str_len,fmt,args);
|
||||
if(type == MESSAGING_WARNING){
|
||||
ESP_LOGW(TAG,"%s",msg_str);
|
||||
}
|
||||
return ota_status.status_text;
|
||||
}
|
||||
uint8_t ota_get_pct_complete(){
|
||||
return ota_status.ota_total_len==0?0:
|
||||
(uint8_t)((float)ota_status.ota_actual_len/(float)ota_status.ota_total_len*100.0f);
|
||||
else if (type == MESSAGING_ERROR){
|
||||
ESP_LOGE(TAG,"%s",msg_str);
|
||||
}
|
||||
else
|
||||
ESP_LOGI(TAG,"%s",msg_str);
|
||||
}
|
||||
else {
|
||||
ESP_LOGW(TAG, "Sending empty string message");
|
||||
}
|
||||
va_end(args);
|
||||
if(type!=MESSAGING_INFO){
|
||||
GDS_TextLine(display, 2, GDS_TEXT_LEFT, GDS_TEXT_CLEAR | GDS_TEXT_UPDATE, msg_str);
|
||||
}
|
||||
|
||||
cJSON_AddStringToObject(msg,"ota_dsc",str_or_unknown(msg_str));
|
||||
free(msg_str);
|
||||
cJSON_AddNumberToObject(msg,"ota_pct", ota_get_pct_complete() );
|
||||
char * json_msg = cJSON_PrintUnformatted(msg);
|
||||
messaging_post_message(type, MESSAGING_CLASS_OTA, json_msg);
|
||||
free(json_msg);
|
||||
cJSON_free(msg);
|
||||
_printMemStats();
|
||||
}
|
||||
//esp_err_t decode_alloc_ota_message(single_message_t * message, char * ota_dsc, uint8_t * ota_pct ){
|
||||
// if(!message || !message->message) return ESP_ERR_INVALID_ARG;
|
||||
// cJSON * json = cJSON_Parse(message->message);
|
||||
// if(!json) return ESP_FAIL;
|
||||
// if(ota_dsc) {
|
||||
// ota_dsc = strdup(cJSON_GetObjectItem(json, "ota_dsc")?cJSON_GetStringValue(cJSON_GetObjectItem(json, "ota_dsc")):"");
|
||||
// }
|
||||
// if(ota_pct){
|
||||
// *ota_pct = cJSON_GetObjectItem(json, "ota_pct")?cJSON_GetObjectItem(json, "ota_pct")->valueint:0;
|
||||
// }
|
||||
// cJSON_free(json);
|
||||
// return ESP_OK;
|
||||
//}
|
||||
|
||||
static void __attribute__((noreturn)) task_fatal_error(void)
|
||||
{
|
||||
@@ -110,7 +216,7 @@ static void __attribute__((noreturn)) task_fatal_error(void)
|
||||
;
|
||||
}
|
||||
}
|
||||
#define FREE_RESET(p) if(p!=NULL) { free(p); p=NULL; }
|
||||
|
||||
esp_err_t _http_event_handler(esp_http_client_event_t *evt)
|
||||
{
|
||||
// --------------
|
||||
@@ -138,10 +244,11 @@ esp_err_t _http_event_handler(esp_http_client_event_t *evt)
|
||||
case HTTP_EVENT_ON_CONNECTED:
|
||||
ESP_LOGD(TAG, "HTTP_EVENT_ON_CONNECTED");
|
||||
|
||||
if(ota_status.bOTAStarted) triggerStatusJsonRefresh(true,"Installing...");
|
||||
ota_status.ota_total_len=0;
|
||||
ota_status.ota_actual_len=0;
|
||||
if(ota_status.bOTAStarted) sendMessaging(MESSAGING_INFO,"Connecting to URL...");
|
||||
ota_status.total_image_len=0;
|
||||
ota_status.actual_image_len=0;
|
||||
ota_status.lastpct=0;
|
||||
ota_status.remain_image_len=0;
|
||||
ota_status.newpct=0;
|
||||
gettimeofday(&ota_status.OTA_start, NULL);
|
||||
|
||||
@@ -152,13 +259,11 @@ esp_err_t _http_event_handler(esp_http_client_event_t *evt)
|
||||
case HTTP_EVENT_ON_HEADER:
|
||||
ESP_LOGD(TAG, "HTTP_EVENT_ON_HEADER, key=%s, value=%s",evt->header_key, evt->header_value);
|
||||
if (strcasecmp(evt->header_key, "location") == 0) {
|
||||
FREE_RESET(ota_status.redirected_url);
|
||||
ota_status.redirected_url=strdup(evt->header_value);
|
||||
ESP_LOGW(TAG,"OTA will redirect to url: %s",ota_status.redirected_url);
|
||||
ESP_LOGW(TAG,"OTA will redirect to url: %s",evt->header_value);
|
||||
}
|
||||
if (strcasecmp(evt->header_key, "content-length") == 0) {
|
||||
ota_status.ota_total_len = atol(evt->header_value);
|
||||
ESP_LOGW(TAG, "Content length found: %s, parsed to %d", evt->header_value, ota_status.ota_total_len);
|
||||
ota_status.total_image_len = atol(evt->header_value);
|
||||
ESP_LOGW(TAG, "Content length found: %s, parsed to %d", evt->header_value, ota_status.total_image_len);
|
||||
}
|
||||
break;
|
||||
case HTTP_EVENT_ON_DATA:
|
||||
@@ -176,29 +281,49 @@ esp_err_t _http_event_handler(esp_http_client_event_t *evt)
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t init_config(char * url){
|
||||
memset(&ota_config, 0x00, sizeof(ota_config));
|
||||
ota_status.bInitialized = true;
|
||||
triggerStatusJsonRefresh(true,"Initializing...");
|
||||
if(url==NULL || strlen(url)==0){
|
||||
ESP_LOGE(TAG,"HTTP OTA called without a url");
|
||||
return ESP_FAIL;
|
||||
esp_err_t init_config(ota_thread_parms_t * p_ota_thread_parms){
|
||||
memset(&http_client_config, 0x00, sizeof(http_client_config));
|
||||
sendMessaging(MESSAGING_INFO,"Initializing...");
|
||||
loc_displayer_progressbar(0);
|
||||
ota_status.ota_type= OTA_TYPE_INVALID;
|
||||
if(p_ota_thread_parms->url !=NULL && strlen(p_ota_thread_parms->url)>0 ){
|
||||
ota_status.ota_type= OTA_TYPE_HTTP;
|
||||
}
|
||||
ota_status.current_url= url;
|
||||
ota_config.cert_pem =get_certificate();
|
||||
ota_config.event_handler = _http_event_handler;
|
||||
ota_config.buffer_size = BUFFSIZE;
|
||||
//ota_config.disable_auto_redirect=true;
|
||||
ota_config.disable_auto_redirect=false;
|
||||
ota_config.skip_cert_common_name_check = false;
|
||||
ota_config.url = strdup(url);
|
||||
ota_config.max_redirection_count = 3;
|
||||
ota_write_data = heap_caps_malloc(ota_config.buffer_size+1 , MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
|
||||
//ota_write_data = malloc(ota_config.buffer_size+1);
|
||||
if(ota_write_data== NULL){
|
||||
else if(p_ota_thread_parms->bin!=NULL && p_ota_thread_parms->length > 0) {
|
||||
ota_status.ota_type= OTA_TYPE_BUFFER;
|
||||
}
|
||||
|
||||
if( ota_status.ota_type== OTA_TYPE_INVALID ){
|
||||
ESP_LOGE(TAG,"HTTP OTA called without a url or a binary buffer");
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
ota_status.buffer_size = BUFFSIZE;
|
||||
ota_status.ota_write_data = heap_caps_malloc(ota_status.buffer_size+1 , (MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT));
|
||||
if(ota_status.ota_write_data== NULL){
|
||||
ESP_LOGE(TAG,"Error allocating the ota buffer");
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
switch (ota_status.ota_type) {
|
||||
case OTA_TYPE_HTTP:
|
||||
http_client_config.cert_pem =get_certificate();
|
||||
http_client_config.event_handler = _http_event_handler;
|
||||
http_client_config.disable_auto_redirect=true;
|
||||
http_client_config.skip_cert_common_name_check = false;
|
||||
http_client_config.url = strdup(p_ota_thread_parms->url);
|
||||
http_client_config.max_redirection_count = 3;
|
||||
// buffer size below is for http read chunks
|
||||
http_client_config.buffer_size = 1024 ;
|
||||
break;
|
||||
case OTA_TYPE_BUFFER:
|
||||
ota_status.bin_data = p_ota_thread_parms->bin;
|
||||
ota_status.total_image_len = p_ota_thread_parms->length;
|
||||
break;
|
||||
default:
|
||||
return ESP_FAIL;
|
||||
break;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
esp_partition_t * _get_ota_partition(esp_partition_subtype_t subtype){
|
||||
@@ -225,7 +350,7 @@ esp_partition_t * _get_ota_partition(esp_partition_subtype_t subtype){
|
||||
|
||||
|
||||
|
||||
esp_err_t _erase_last_boot_app_partition(esp_partition_t *ota_partition)
|
||||
esp_err_t _erase_last_boot_app_partition(const esp_partition_t *ota_partition)
|
||||
{
|
||||
uint16_t num_passes=0;
|
||||
uint16_t remain_size=0;
|
||||
@@ -257,18 +382,20 @@ esp_err_t _erase_last_boot_app_partition(esp_partition_t *ota_partition)
|
||||
ESP_LOGD(TAG,"Pass %d of %d, with chunks of %d bytes, from %d to %d", i+1, num_passes,single_pass_size,i*single_pass_size,i*single_pass_size+single_pass_size);
|
||||
err=esp_partition_erase_range(ota_partition, i*single_pass_size, single_pass_size);
|
||||
if(err!=ESP_OK) return err;
|
||||
// triggerStatusJsonRefresh(i%10==0?true:false,"Erasing flash (%u/%u)",i,num_passes);
|
||||
if(i%2) {
|
||||
triggerStatusJsonRefresh(false,"Erasing flash (%u/%u)",i,num_passes);
|
||||
loc_displayer_progressbar((int)(((float)i/(float)num_passes)*100.0f));
|
||||
sendMessaging(MESSAGING_INFO,"Erasing flash (%u/%u)",i,num_passes);
|
||||
}
|
||||
vTaskDelay(200/ portTICK_PERIOD_MS); // wait here for a short amount of time. This will help with reducing WDT errors
|
||||
vTaskDelay(100/ portTICK_PERIOD_MS); // wait here for a short amount of time. This will help with reducing WDT errors
|
||||
}
|
||||
if(remain_size>0){
|
||||
err=esp_partition_erase_range(ota_partition, ota_partition->size-remain_size, remain_size);
|
||||
|
||||
if(err!=ESP_OK) return err;
|
||||
}
|
||||
triggerStatusJsonRefresh(true,"Erasing flash complete.");
|
||||
taskYIELD();
|
||||
sendMessaging(MESSAGING_INFO,"Erasing flash complete.");
|
||||
loc_displayer_progressbar(100);
|
||||
vTaskDelay(200/ portTICK_PERIOD_MS);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@@ -287,28 +414,32 @@ static bool process_again(int status_code)
|
||||
static esp_err_t _http_handle_response_code(esp_http_client_handle_t http_client, int status_code)
|
||||
{
|
||||
esp_err_t err=ESP_OK;
|
||||
if (status_code == HttpStatus_MovedPermanently || status_code == HttpStatus_Found) {
|
||||
if (status_code == HttpStatus_MovedPermanently || status_code == HttpStatus_Found ) {
|
||||
ESP_LOGW(TAG, "Handling HTTP redirection. ");
|
||||
err = esp_http_client_set_redirection(http_client);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "URL redirection Failed. %s", esp_err_to_name(err));
|
||||
return err;
|
||||
}
|
||||
ESP_LOGW(TAG, "Done Handling HTTP redirection. ");
|
||||
|
||||
} else if (status_code == HttpStatus_Unauthorized) {
|
||||
ESP_LOGW(TAG, "Handling Unauthorized. ");
|
||||
esp_http_client_add_auth(http_client);
|
||||
}
|
||||
ESP_LOGD(TAG, "Redirection done, checking if we need to read the data. ");
|
||||
if (process_again(status_code)) {
|
||||
char * local_buff = heap_caps_malloc(ota_config.buffer_size+1, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
|
||||
//char * local_buff = malloc(ota_config.buffer_size+1);
|
||||
if(local_buff==NULL){
|
||||
ESP_LOGE(TAG,"Failed to allocate internal memory buffer for http processing");
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
//ESP_LOGD(TAG, "We have to read some more data. Allocating buffer size %u",ota_config.buffer_size+1);
|
||||
//char * local_buff = heap_caps_malloc(ota_status.buffer_size+1, (MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT));
|
||||
|
||||
// if(local_buff==NULL){
|
||||
// ESP_LOGE(TAG,"Failed to allocate internal memory buffer for http processing");
|
||||
// return ESP_ERR_NO_MEM;
|
||||
// }
|
||||
|
||||
while (1) {
|
||||
ESP_LOGD(TAG, "Reading data chunk. ");
|
||||
int data_read = esp_http_client_read(http_client, local_buff, ota_config.buffer_size);
|
||||
int data_read = esp_http_client_read(http_client, ota_status.ota_write_data, ota_status.buffer_size);
|
||||
if (data_read < 0) {
|
||||
ESP_LOGE(TAG, "Error: SSL data read error");
|
||||
err= ESP_FAIL;
|
||||
@@ -319,7 +450,7 @@ static esp_err_t _http_handle_response_code(esp_http_client_handle_t http_client
|
||||
break;
|
||||
}
|
||||
}
|
||||
FREE_RESET(local_buff);
|
||||
//FREE_RESET(local_buff);
|
||||
}
|
||||
|
||||
return err;
|
||||
@@ -329,44 +460,50 @@ static esp_err_t _http_connect(esp_http_client_handle_t http_client)
|
||||
esp_err_t err = ESP_FAIL;
|
||||
int status_code, header_ret;
|
||||
do {
|
||||
ESP_LOGD(TAG, "connecting the http client. ");
|
||||
ESP_LOGI(TAG, "connecting the http client. ");
|
||||
err = esp_http_client_open(http_client, 0);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to open HTTP connection: %s", esp_err_to_name(err));
|
||||
sendMessaging(MESSAGING_ERROR,"Failed to open HTTP connection: %s", esp_err_to_name(err));
|
||||
return err;
|
||||
}
|
||||
ESP_LOGD(TAG, "Fetching headers");
|
||||
ESP_LOGI(TAG, "Fetching headers");
|
||||
header_ret = esp_http_client_fetch_headers(http_client);
|
||||
if (header_ret < 0) {
|
||||
// Error found
|
||||
sendMessaging(MESSAGING_ERROR,"Header fetch failed");
|
||||
return header_ret;
|
||||
}
|
||||
ESP_LOGD(TAG, "HTTP Header fetch completed, found content length of %d",header_ret);
|
||||
ESP_LOGI(TAG, "HTTP Header fetch completed, found content length of %d",header_ret);
|
||||
status_code = esp_http_client_get_status_code(http_client);
|
||||
ESP_LOGD(TAG, "HTTP status code was %d",status_code);
|
||||
|
||||
|
||||
|
||||
err = _http_handle_response_code(http_client, status_code);
|
||||
if (err != ESP_OK) {
|
||||
sendMessaging(MESSAGING_ERROR,"HTTP connect error: %s", esp_err_to_name(err));
|
||||
return err;
|
||||
}
|
||||
|
||||
} while (process_again(status_code));
|
||||
|
||||
if(status_code >=400 && status_code <=900){
|
||||
sendMessaging(MESSAGING_ERROR,"Error: HTTP Status %d",status_code);
|
||||
err=ESP_FAIL;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
void ota_task_cleanup(const char * message, ...){
|
||||
ota_status.bOTAThreadStarted=false;
|
||||
loc_displayer_progressbar(0);
|
||||
if(message!=NULL){
|
||||
|
||||
va_list args;
|
||||
va_start(args, message);
|
||||
triggerStatusJsonRefresh(true,message, args);
|
||||
sendMessaging(MESSAGING_ERROR,message, args);
|
||||
va_end(args);
|
||||
ESP_LOGE(TAG, "%s",ota_status.status_text);
|
||||
}
|
||||
FREE_RESET(ota_status.redirected_url);
|
||||
FREE_RESET(ota_status.current_url);
|
||||
FREE_RESET(ota_write_data);
|
||||
FREE_RESET(ota_status.ota_write_data);
|
||||
FREE_RESET(ota_status.bin_data);
|
||||
if(ota_http_client!=NULL) {
|
||||
esp_http_client_cleanup(ota_http_client);
|
||||
ota_http_client=NULL;
|
||||
@@ -374,24 +511,120 @@ void ota_task_cleanup(const char * message, ...){
|
||||
ota_status.bOTAStarted = false;
|
||||
task_fatal_error();
|
||||
}
|
||||
esp_err_t ota_buffer_all(){
|
||||
int data_read=0;
|
||||
esp_err_t err=ESP_OK;
|
||||
if (ota_status.ota_type == OTA_TYPE_HTTP){
|
||||
GDS_TextLine(display, 2, GDS_TEXT_LEFT, GDS_TEXT_CLEAR | GDS_TEXT_UPDATE, "Downloading file");
|
||||
ota_http_client = esp_http_client_init(&http_client_config);
|
||||
if (ota_http_client == NULL) {
|
||||
sendMessaging(MESSAGING_ERROR,"Error: Failed to initialize HTTP connection.");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
_printMemStats();
|
||||
// Open the http connection and follow any redirection
|
||||
err = _http_connect(ota_http_client);
|
||||
if (err != ESP_OK) {
|
||||
return err;
|
||||
}
|
||||
if(ota_status.total_image_len<=0){
|
||||
sendMessaging(MESSAGING_ERROR,"Error: Invalid image length");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
ota_status.bin_data= malloc(ota_status.total_image_len);
|
||||
if(ota_status.bin_data==NULL){
|
||||
sendMessaging(MESSAGING_ERROR,"Error: buffer alloc error");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
data_read = esp_http_client_read(ota_http_client, ota_status.bin_data, ota_status.total_image_len);
|
||||
if(data_read != ota_status.total_image_len){
|
||||
sendMessaging(MESSAGING_ERROR,"Error: Binary incomplete");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
}
|
||||
else {
|
||||
gettimeofday(&ota_status.OTA_start, NULL);
|
||||
}
|
||||
ota_status.remain_image_len=ota_status.total_image_len;
|
||||
|
||||
return err;
|
||||
}
|
||||
int ota_buffer_read(){
|
||||
int data_read=0;
|
||||
if(ota_status.remain_image_len >ota_status.buffer_size){
|
||||
data_read = ota_status.buffer_size;
|
||||
} else {
|
||||
data_read = ota_status.remain_image_len;
|
||||
}
|
||||
memcpy(ota_status.ota_write_data, &ota_status.bin_data[ota_status.actual_image_len], data_read);
|
||||
|
||||
ota_status.actual_image_len += data_read;
|
||||
ota_status.remain_image_len -= data_read;
|
||||
return data_read;
|
||||
}
|
||||
esp_err_t ota_header_check(){
|
||||
esp_app_desc_t new_app_info;
|
||||
esp_app_desc_t running_app_info;
|
||||
|
||||
ota_status.configured = esp_ota_get_boot_partition();
|
||||
ota_status.running = esp_ota_get_running_partition();
|
||||
ota_status.last_invalid_app= esp_ota_get_last_invalid_partition();
|
||||
ota_status.ota_partition = _get_ota_partition(ESP_PARTITION_SUBTYPE_APP_OTA_0);
|
||||
|
||||
ESP_LOGI(TAG, "Running partition [%s] type %d subtype %d (offset 0x%08x)", ota_status.running->label, ota_status.running->type, ota_status.running->subtype, ota_status.running->address);
|
||||
if (ota_status.total_image_len > ota_status.ota_partition->size){
|
||||
ota_task_cleanup("Error: Image size too large to fit in partition.");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
if(ota_status.ota_partition == NULL){
|
||||
ESP_LOGE(TAG,"Unable to locate OTA application partition. ");
|
||||
ota_task_cleanup("Error: OTA partition not found");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
if (ota_status.configured != ota_status.running) {
|
||||
ESP_LOGW(TAG, "Configured OTA boot partition at offset 0x%08x, but running from offset 0x%08x", ota_status.configured->address, ota_status.running->address);
|
||||
ESP_LOGW(TAG, "(This can happen if either the OTA boot data or preferred boot image become corrupted somehow.)");
|
||||
}
|
||||
ESP_LOGI(TAG, "Next ota update partition is: [%s] subtype %d at offset 0x%x",
|
||||
ota_status.update_partition->label, ota_status.update_partition->subtype, ota_status.update_partition->address);
|
||||
|
||||
if (ota_status.total_image_len >= IMAGE_HEADER_SIZE) {
|
||||
// check current version with downloading
|
||||
memcpy(&new_app_info, &ota_status.bin_data[sizeof(esp_image_header_t) + sizeof(esp_image_segment_header_t)], sizeof(esp_app_desc_t));
|
||||
ESP_LOGI(TAG, "New firmware version: %s", new_app_info.version);
|
||||
if (esp_ota_get_partition_description(ota_status.running, &running_app_info) == ESP_OK) {
|
||||
ESP_LOGI(TAG, "Running recovery version: %s", running_app_info.version);
|
||||
}
|
||||
|
||||
esp_app_desc_t invalid_app_info;
|
||||
if (esp_ota_get_partition_description(ota_status.last_invalid_app, &invalid_app_info) == ESP_OK) {
|
||||
ESP_LOGI(TAG, "Last invalid firmware version: %s", invalid_app_info.version);
|
||||
}
|
||||
|
||||
if (memcmp(new_app_info.version, running_app_info.version, sizeof(new_app_info.version)) == 0) {
|
||||
ESP_LOGW(TAG, "Current running version is the same as a new.");
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
else{
|
||||
ota_task_cleanup("Error: Binary file too small");
|
||||
}
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
void ota_task(void *pvParameter)
|
||||
{
|
||||
esp_err_t err = ESP_OK;
|
||||
size_t buffer_size = BUFFSIZE;
|
||||
int data_read = 0;
|
||||
GDS_TextSetFont(display,2,GDS_GetHeight(display)>32?&Font_droid_sans_fallback_15x17:&Font_droid_sans_fallback_11x13,-2);
|
||||
GDS_ClearExt(display, true);
|
||||
GDS_TextLine(display, 1, GDS_TEXT_LEFT, GDS_TEXT_CLEAR | GDS_TEXT_UPDATE, "Firmware update");
|
||||
GDS_TextLine(display, 2, GDS_TEXT_LEFT, GDS_TEXT_CLEAR | GDS_TEXT_UPDATE, "Initializing");
|
||||
loc_displayer_progressbar(0);
|
||||
ESP_LOGD(TAG, "HTTP ota Thread started");
|
||||
const esp_partition_t *configured = esp_ota_get_boot_partition();
|
||||
const esp_partition_t *running = esp_ota_get_running_partition();
|
||||
const esp_partition_t * update_partition = esp_ota_get_next_update_partition(NULL);
|
||||
ESP_LOGI(TAG, "esp_ota_get_next_update_partition returned : partition [%s] subtype %d at offset 0x%x",
|
||||
update_partition->label, update_partition->subtype, update_partition->address);
|
||||
|
||||
if (configured != running) {
|
||||
ESP_LOGW(TAG, "Configured OTA boot partition at offset 0x%08x, but running from offset 0x%08x", configured->address, running->address);
|
||||
ESP_LOGW(TAG, "(This can happen if either the OTA boot data or preferred boot image become corrupted somehow.)");
|
||||
}
|
||||
ESP_LOGI(TAG, "Running partition [%s] type %d subtype %d (offset 0x%08x)", running->label, running->type, running->subtype, running->address);
|
||||
_printMemStats();
|
||||
|
||||
ota_status.update_partition = esp_ota_get_next_update_partition(NULL);
|
||||
|
||||
ESP_LOGI(TAG,"Initializing OTA configuration");
|
||||
err = init_config(pvParameter);
|
||||
@@ -400,139 +633,96 @@ void ota_task(void *pvParameter)
|
||||
return;
|
||||
}
|
||||
|
||||
/* Locate and erase ota application partition */
|
||||
ESP_LOGW(TAG,"**************** Expecting WATCHDOG errors below during flash erase. This is OK and not to worry about **************** ");
|
||||
triggerStatusJsonRefresh(true,"Erasing OTA partition");
|
||||
esp_partition_t *ota_partition = _get_ota_partition(ESP_PARTITION_SUBTYPE_APP_OTA_0);
|
||||
if(ota_partition == NULL){
|
||||
ESP_LOGE(TAG,"Unable to locate OTA application partition. ");
|
||||
ota_task_cleanup("Error: OTA application partition not found. (%s)",esp_err_to_name(err));
|
||||
_printMemStats();
|
||||
ota_status.bOTAStarted = true;
|
||||
sendMessaging(MESSAGING_INFO,"Starting OTA...");
|
||||
err=ota_buffer_all();
|
||||
if(err!=ESP_OK){
|
||||
ota_task_cleanup(NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if(ota_header_check()!=ESP_OK){
|
||||
ota_task_cleanup(NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Locate and erase ota application partition */
|
||||
ESP_LOGW(TAG,"**************** Expecting WATCHDOG errors below during flash erase. This is OK and not to worry about **************** ");
|
||||
GDS_TextLine(display, 2, GDS_TEXT_LEFT, GDS_TEXT_CLEAR | GDS_TEXT_UPDATE, "Formatting partition");
|
||||
sendMessaging(MESSAGING_INFO,"Formatting OTA partition");
|
||||
_printMemStats();
|
||||
err=_erase_last_boot_app_partition(ota_partition);
|
||||
err=_erase_last_boot_app_partition(ota_status.ota_partition);
|
||||
if(err!=ESP_OK){
|
||||
ota_task_cleanup("Error: Unable to erase last APP partition. (%s)",esp_err_to_name(err));
|
||||
return;
|
||||
}
|
||||
|
||||
_printMemStats();
|
||||
ota_status.bOTAStarted = true;
|
||||
triggerStatusJsonRefresh(true,"Starting OTA...");
|
||||
ota_http_client = esp_http_client_init(&ota_config);
|
||||
if (ota_http_client == NULL) {
|
||||
ota_task_cleanup("Error: Failed to initialize HTTP connection.");
|
||||
return;
|
||||
}
|
||||
_printMemStats();
|
||||
// Open the http connection and follow any redirection
|
||||
err = _http_connect(ota_http_client);
|
||||
if (err != ESP_OK) {
|
||||
ota_task_cleanup("Error: HTTP Start read failed. (%s)",esp_err_to_name(err));
|
||||
return;
|
||||
}
|
||||
|
||||
loc_displayer_progressbar(0);
|
||||
_printMemStats();
|
||||
|
||||
|
||||
// Call OTA Begin with a small partition size - this minimizes the time spent in erasing partition,
|
||||
// which was already done above
|
||||
esp_ota_handle_t update_handle = 0 ;
|
||||
int binary_file_length = 0;
|
||||
|
||||
/*deal with all receive packet*/
|
||||
bool image_header_was_checked = false;
|
||||
while (1) {
|
||||
int data_read = esp_http_client_read(ota_http_client, ota_write_data, buffer_size);
|
||||
if (data_read < 0) {
|
||||
ota_task_cleanup("Error: Data read error");
|
||||
return;
|
||||
} else if (data_read > 0) {
|
||||
if (image_header_was_checked == false) {
|
||||
esp_app_desc_t new_app_info;
|
||||
if (data_read > sizeof(esp_image_header_t) + sizeof(esp_image_segment_header_t) + sizeof(esp_app_desc_t)) {
|
||||
// check current version with downloading
|
||||
memcpy(&new_app_info, &ota_write_data[sizeof(esp_image_header_t) + sizeof(esp_image_segment_header_t)], sizeof(esp_app_desc_t));
|
||||
ESP_LOGI(TAG, "New firmware version: %s", new_app_info.version);
|
||||
|
||||
esp_app_desc_t running_app_info;
|
||||
if (esp_ota_get_partition_description(running, &running_app_info) == ESP_OK) {
|
||||
ESP_LOGI(TAG, "Running recovery version: %s", running_app_info.version);
|
||||
}
|
||||
|
||||
const esp_partition_t* last_invalid_app = esp_ota_get_last_invalid_partition();
|
||||
esp_app_desc_t invalid_app_info;
|
||||
if (esp_ota_get_partition_description(last_invalid_app, &invalid_app_info) == ESP_OK) {
|
||||
ESP_LOGI(TAG, "Last invalid firmware version: %s", invalid_app_info.version);
|
||||
}
|
||||
|
||||
// check current version with last invalid partition
|
||||
// if (last_invalid_app != NULL) {
|
||||
// if (memcmp(invalid_app_info.version, new_app_info.version, sizeof(new_app_info.version)) == 0) {
|
||||
// ESP_LOGW(TAG, "New version is the same as invalid version.");
|
||||
// ESP_LOGW(TAG, "Previously, there was an attempt to launch the firmware with %s version, but it failed.", invalid_app_info.version);
|
||||
// ESP_LOGW(TAG, "The firmware has been rolled back to the previous version.");
|
||||
// ota_task_cleanup("esp_ota_begin failed (%s)", esp_err_to_name(err));
|
||||
// }
|
||||
// }
|
||||
|
||||
if (memcmp(new_app_info.version, running_app_info.version, sizeof(new_app_info.version)) == 0) {
|
||||
ESP_LOGW(TAG, "Current running version is the same as a new.");
|
||||
}
|
||||
|
||||
image_header_was_checked = true;
|
||||
|
||||
// Call OTA Begin with a small partition size - this drives the erase operation which was already done;
|
||||
err = esp_ota_begin(ota_partition, 512, &update_handle);
|
||||
err = esp_ota_begin(ota_status.ota_partition, 512, &update_handle);
|
||||
if (err != ESP_OK) {
|
||||
ota_task_cleanup("esp_ota_begin failed (%s)", esp_err_to_name(err));
|
||||
return;
|
||||
}
|
||||
ESP_LOGD(TAG, "esp_ota_begin succeeded");
|
||||
} else {
|
||||
ota_task_cleanup("Error: Binary file too large for the current partition");
|
||||
GDS_TextLine(display, 2, GDS_TEXT_LEFT, GDS_TEXT_CLEAR | GDS_TEXT_UPDATE, "Writing image...");
|
||||
while (ota_status.remain_image_len>0) {
|
||||
|
||||
data_read = ota_buffer_read();
|
||||
if (data_read <= 0) {
|
||||
ota_task_cleanup("Error: Data read error");
|
||||
return;
|
||||
}
|
||||
}
|
||||
err = esp_ota_write( update_handle, (const void *)ota_write_data, data_read);
|
||||
} else if (data_read > 0) {
|
||||
err = esp_ota_write( update_handle, (const void *)ota_status.ota_write_data, data_read);
|
||||
if (err != ESP_OK) {
|
||||
ota_task_cleanup("Error: OTA Partition write failure. (%s)",esp_err_to_name(err));
|
||||
return;
|
||||
}
|
||||
binary_file_length += data_read;
|
||||
ESP_LOGD(TAG, "Written image length %d", binary_file_length);
|
||||
ota_status.ota_actual_len=binary_file_length;
|
||||
ESP_LOGD(TAG, "Written image length %d", ota_status.actual_image_len);
|
||||
|
||||
if(ota_get_pct_complete()%5 == 0) ota_status.newpct = ota_get_pct_complete();
|
||||
if(ota_status.lastpct!=ota_status.newpct ) {
|
||||
loc_displayer_progressbar(ota_status.newpct);
|
||||
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/%d (%d pct), %d KB/s", ota_status.ota_actual_len, ota_status.ota_total_len, ota_status.newpct, elapsed_ms>0?ota_status.ota_actual_len*1000/elapsed_ms/1024:0);
|
||||
triggerStatusJsonRefresh(true,"Downloading & writing update.");
|
||||
ESP_LOGI(TAG,"OTA progress : %d/%d (%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.");
|
||||
ota_status.lastpct=ota_status.newpct;
|
||||
}
|
||||
taskYIELD();
|
||||
|
||||
} else if (data_read == 0) {
|
||||
ESP_LOGI(TAG, "Connection closed");
|
||||
ESP_LOGI(TAG, "End of OTA data stream");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Total Write binary data length: %d", binary_file_length);
|
||||
if (ota_status.ota_total_len != binary_file_length) {
|
||||
ESP_LOGI(TAG, "Total Write binary data length: %d", ota_status.actual_image_len);
|
||||
if (ota_status.total_image_len != ota_status.actual_image_len) {
|
||||
ota_task_cleanup("Error: Error in receiving complete file");
|
||||
return;
|
||||
}
|
||||
_printMemStats();
|
||||
|
||||
loc_displayer_progressbar(100);
|
||||
err = esp_ota_end(update_handle);
|
||||
if (err != ESP_OK) {
|
||||
ota_task_cleanup("Error: %s",esp_err_to_name(err));
|
||||
return;
|
||||
}
|
||||
_printMemStats();
|
||||
err = esp_ota_set_boot_partition(ota_partition);
|
||||
err = esp_ota_set_boot_partition(ota_status.ota_partition);
|
||||
if (err == ESP_OK) {
|
||||
ESP_LOGI(TAG,"OTA Process completed successfully!");
|
||||
triggerStatusJsonRefresh(true,"Success!");
|
||||
sendMessaging(MESSAGING_INFO,"Success!");
|
||||
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
|
||||
GDS_Clear(display,GDS_COLOR_BLACK);
|
||||
esp_restart();
|
||||
} else {
|
||||
ota_task_cleanup("Error: Unable to update boot partition [%s]",esp_err_to_name(err));
|
||||
@@ -542,7 +732,7 @@ void ota_task(void *pvParameter)
|
||||
return;
|
||||
}
|
||||
|
||||
esp_err_t process_recovery_ota(const char * bin_url){
|
||||
esp_err_t process_recovery_ota(const char * bin_url, char * bin_buffer, uint32_t length){
|
||||
int ret = 0;
|
||||
uint16_t stack_size, task_priority;
|
||||
if(ota_status.bOTAThreadStarted){
|
||||
@@ -551,23 +741,21 @@ esp_err_t process_recovery_ota(const char * bin_url){
|
||||
}
|
||||
memset(&ota_status, 0x00, sizeof(ota_status));
|
||||
ota_status.bOTAThreadStarted=true;
|
||||
char * urlPtr=strdup(bin_url);
|
||||
// the first thing we need to do here is to erase the firmware url
|
||||
// to avoid a boot loop
|
||||
|
||||
#ifdef CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_1
|
||||
#define OTA_CORE 0
|
||||
#warning "OTA will run on core 0"
|
||||
#else
|
||||
#pragma message "OTA will run on core 1"
|
||||
#define OTA_CORE 1
|
||||
#endif
|
||||
ESP_LOGI(TAG, "Starting ota on core %u for : %s", OTA_CORE,urlPtr);
|
||||
if(bin_url){
|
||||
ota_thread_parms.url =strdup(bin_url);
|
||||
ESP_LOGI(TAG, "Starting ota on core %u for : %s", OTA_CORE,ota_thread_parms.url);
|
||||
}
|
||||
else {
|
||||
ota_thread_parms.bin = bin_buffer;
|
||||
ota_thread_parms.length = length;
|
||||
ESP_LOGI(TAG, "Starting ota on core %u for file upload", OTA_CORE);
|
||||
}
|
||||
|
||||
char * num_buffer=config_alloc_get(NVS_TYPE_STR, "ota_stack");
|
||||
if(num_buffer!=NULL) {
|
||||
stack_size= atol(num_buffer);
|
||||
free(num_buffer);
|
||||
num_buffer=NULL;
|
||||
FREE_AND_NULL(num_buffer);
|
||||
}
|
||||
else {
|
||||
ESP_LOGW(TAG,"OTA stack size config not found");
|
||||
@@ -576,16 +764,15 @@ esp_err_t process_recovery_ota(const char * bin_url){
|
||||
num_buffer=config_alloc_get(NVS_TYPE_STR, "ota_prio");
|
||||
if(num_buffer!=NULL) {
|
||||
task_priority= atol(num_buffer);
|
||||
free(num_buffer);
|
||||
num_buffer=NULL;
|
||||
FREE_AND_NULL(num_buffer);
|
||||
}
|
||||
else {
|
||||
ESP_LOGW(TAG,"OTA task priority not found");
|
||||
task_priority= OTA_TASK_PRIOTITY;
|
||||
}
|
||||
|
||||
ESP_LOGD(TAG,"OTA task stack size %d, priority %d (%d %s ESP_TASK_MAIN_PRIO)",stack_size , task_priority, abs(task_priority-ESP_TASK_MAIN_PRIO), task_priority-ESP_TASK_MAIN_PRIO>0?"above":"below");
|
||||
ret=xTaskCreatePinnedToCore(&ota_task, "ota_task", stack_size , (void *)urlPtr, task_priority, NULL, OTA_CORE);
|
||||
//ret=xTaskCreate(&ota_task, "ota_task", 1024*20, (void *)urlPtr, ESP_TASK_MAIN_PRIO+2, NULL);
|
||||
ret=xTaskCreatePinnedToCore(&ota_task, "ota_task", stack_size , (void *)&ota_thread_parms, task_priority, NULL, OTA_CORE);
|
||||
if (ret != pdPASS) {
|
||||
ESP_LOGI(TAG, "create thread %s failed", "ota_task");
|
||||
return ESP_FAIL;
|
||||
@@ -593,10 +780,14 @@ esp_err_t process_recovery_ota(const char * bin_url){
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t start_ota(const char * bin_url)
|
||||
esp_err_t start_ota(const char * bin_url, char * bin_buffer, uint32_t length)
|
||||
{
|
||||
if(is_recovery_running){
|
||||
return process_recovery_ota(bin_url);
|
||||
#if RECOVERY_APPLICATION
|
||||
return process_recovery_ota(bin_url,bin_buffer,length);
|
||||
#else
|
||||
if(!bin_url){
|
||||
ESP_LOGE(TAG,"missing URL parameter. Unable to start OTA");
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
ESP_LOGW(TAG, "Called to update the firmware from url: %s",bin_url);
|
||||
if(config_set_value(NVS_TYPE_STR, "fwurl", bin_url) != ESP_OK){
|
||||
@@ -610,4 +801,6 @@ esp_err_t start_ota(const char * bin_url)
|
||||
|
||||
ESP_LOGW(TAG, "Rebooting to recovery to complete the installation");
|
||||
return guided_factory();
|
||||
return ESP_OK;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -30,4 +30,5 @@ esp_err_t start_ota(const char * bin_url);
|
||||
const char * ota_get_status();
|
||||
uint8_t ota_get_pct_complete();
|
||||
|
||||
esp_err_t start_ota(const char * bin_url, char * bin_buffer, uint32_t length);
|
||||
|
||||
|
||||
@@ -10,6 +10,4 @@
|
||||
COMPONENT_SRCDIRS := .
|
||||
COMPONENT_SRCDIRS += ./libtelnet
|
||||
COMPONENT_ADD_INCLUDEDIRS := .
|
||||
COMPONENT_ADD_INCLUDEDIRS += ./libtelnet
|
||||
COMPONENT_EXTRA_INCLUDES += $(PROJECT_PATH)/main/
|
||||
|
||||
COMPONENT_PRIV_INCLUDEDIRS += ./libtelnet
|
||||
@@ -38,6 +38,8 @@
|
||||
#include "config.h"
|
||||
#include "nvs_utilities.h"
|
||||
#include "platform_esp32.h"
|
||||
#include "messaging.h"
|
||||
#include "trace.h"
|
||||
|
||||
|
||||
/************************************
|
||||
@@ -47,15 +49,16 @@
|
||||
#define TELNET_STACK_SIZE 8048
|
||||
#define TELNET_RX_BUF 1024
|
||||
|
||||
const static char tag[] = "telnet";
|
||||
const static char TAG[] = "telnet";
|
||||
static int uart_fd=0;
|
||||
RingbufHandle_t buf_handle;
|
||||
SemaphoreHandle_t xSemaphore = NULL;
|
||||
//static SemaphoreHandle_t xSemaphore = NULL;
|
||||
static size_t send_chunk=300;
|
||||
static size_t log_buf_size=2000; //32-bit aligned size
|
||||
static bool bIsEnabled=false;
|
||||
static int partnerSocket=0;
|
||||
static telnet_t *tnHandle;
|
||||
extern bool bypass_wifi_manager;
|
||||
|
||||
/************************************
|
||||
* Forward declarations
|
||||
@@ -68,22 +71,34 @@ static int stdout_fstat(int fd, struct stat * st);
|
||||
static ssize_t stdout_write(int fd, const void * data, size_t size);
|
||||
static char *eventToString(telnet_event_type_t type);
|
||||
static void handle_telnet_conn();
|
||||
static void process_logs( UBaseType_t bytes);
|
||||
|
||||
static void process_logs( UBaseType_t bytes, bool is_write_op);
|
||||
static bool bMirrorToUART=false;
|
||||
struct telnetUserData {
|
||||
int sockfd;
|
||||
telnet_t *tnHandle;
|
||||
char * rxbuf;
|
||||
};
|
||||
|
||||
|
||||
bool is_serial_suppressed(){
|
||||
return bIsEnabled?!bMirrorToUART:false ;
|
||||
}
|
||||
void init_telnet(){
|
||||
char *val= get_nvs_value_alloc(NVS_TYPE_STR, "telnet_enable");
|
||||
if (!val || strlen(val) == 0 || !strcasestr("YX",val) ) {
|
||||
ESP_LOGI(tag,"Telnet support disabled");
|
||||
if (!val || strlen(val) == 0 || !strcasestr("YXD",val) ) {
|
||||
ESP_LOGI(TAG,"Telnet support disabled");
|
||||
if(val) free(val);
|
||||
return;
|
||||
}
|
||||
// if wifi manager is bypassed, there will possibly be no wifi available
|
||||
//
|
||||
bMirrorToUART = (strcasestr("D",val)!=NULL);
|
||||
if(!bMirrorToUART && bypass_wifi_manager){
|
||||
// This isn't supposed to happen, as telnet won't start if wifi manager isn't
|
||||
// started. So this is a safeguard only.
|
||||
ESP_LOGW(TAG,"Wifi manager is not active. Forcing console on Serial output.");
|
||||
}
|
||||
|
||||
FREE_AND_NULL(val);
|
||||
val=get_nvs_value_alloc(NVS_TYPE_STR, "telnet_block");
|
||||
if(val){
|
||||
send_chunk=atol(val);
|
||||
@@ -97,18 +112,21 @@ void init_telnet(){
|
||||
log_buf_size=log_buf_size>0?log_buf_size:4000;
|
||||
}
|
||||
// Create the semaphore to guard a shared resource.
|
||||
vSemaphoreCreateBinary( xSemaphore );
|
||||
//vSemaphoreCreateBinary( xSemaphore );
|
||||
|
||||
// Redirect the output to our telnet handler as soon as possible
|
||||
StaticRingbuffer_t *buffer_struct = (StaticRingbuffer_t *)heap_caps_malloc(sizeof(StaticRingbuffer_t), MALLOC_CAP_SPIRAM);
|
||||
uint8_t *buffer_storage = (uint8_t *)heap_caps_malloc(sizeof(uint8_t)*log_buf_size, MALLOC_CAP_SPIRAM);
|
||||
StaticRingbuffer_t *buffer_struct = (StaticRingbuffer_t *)malloc(sizeof(StaticRingbuffer_t) );
|
||||
// All non-split ring buffer must have their memory alignment set to 32 bits.
|
||||
uint8_t *buffer_storage = (uint8_t *)heap_caps_malloc(sizeof(uint8_t)*log_buf_size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT );
|
||||
buf_handle = xRingbufferCreateStatic(log_buf_size, RINGBUF_TYPE_BYTEBUF, buffer_storage, buffer_struct);
|
||||
if (buf_handle == NULL) {
|
||||
ESP_LOGE(tag,"Failed to create ring buffer for telnet!");
|
||||
ESP_LOGE(TAG,"Failed to create ring buffer for telnet!");
|
||||
messaging_post_message(MESSAGING_ERROR,MESSAGING_CLASS_SYSTEM,"Failed to allocate memory for telnet buffer");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
ESP_LOGI(tag, "***Redirecting log output to telnet");
|
||||
ESP_LOGI(TAG, "***Redirecting log output to telnet");
|
||||
const esp_vfs_t vfs = {
|
||||
.flags = ESP_VFS_FLAG_DEFAULT,
|
||||
.write = &stdout_write,
|
||||
@@ -116,8 +134,12 @@ void init_telnet(){
|
||||
.fstat = &stdout_fstat,
|
||||
.close = &stdout_close,
|
||||
.read = &stdout_read,
|
||||
|
||||
};
|
||||
|
||||
if(bMirrorToUART){
|
||||
uart_fd=open("/dev/uart/0", O_RDWR);
|
||||
}
|
||||
ESP_ERROR_CHECK(esp_vfs_register("/dev/pkspstdout", &vfs, NULL));
|
||||
freopen("/dev/pkspstdout", "w", stdout);
|
||||
freopen("/dev/pkspstdout", "w", stderr);
|
||||
@@ -125,11 +147,11 @@ void init_telnet(){
|
||||
}
|
||||
void start_telnet(void * pvParameter){
|
||||
static bool isStarted=false;
|
||||
StaticTask_t *xTaskBuffer = (StaticTask_t*) heap_caps_malloc(sizeof(StaticTask_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
|
||||
StackType_t *xStack = malloc(TELNET_STACK_SIZE);
|
||||
StaticTask_t *xTaskBuffer = (StaticTask_t*) heap_caps_malloc(sizeof(StaticTask_t), (MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT));
|
||||
StackType_t *xStack = heap_caps_malloc(TELNET_STACK_SIZE,(MALLOC_CAP_SPIRAM|MALLOC_CAP_8BIT));
|
||||
|
||||
if(!isStarted && bIsEnabled) {
|
||||
xTaskCreateStatic( (TaskFunction_t) &telnet_task, "telnet", TELNET_STACK_SIZE, NULL, ESP_TASK_PRIO_MIN + 1, xStack, xTaskBuffer);
|
||||
xTaskCreateStatic( (TaskFunction_t) &telnet_task, "telnet", TELNET_STACK_SIZE, NULL, ESP_TASK_MAIN_PRIO , xStack, xTaskBuffer);
|
||||
isStarted=true;
|
||||
}
|
||||
}
|
||||
@@ -142,13 +164,15 @@ static void telnet_task(void *data) {
|
||||
|
||||
int rc = bind(serverSocket, (struct sockaddr *)&serverAddr, sizeof(serverAddr));
|
||||
if (rc < 0) {
|
||||
ESP_LOGE(tag, "bind: %d (%s)", errno, strerror(errno));
|
||||
ESP_LOGE(TAG, "bind: %d (%s)", errno, strerror(errno));
|
||||
close(serverSocket);
|
||||
return;
|
||||
}
|
||||
|
||||
rc = listen(serverSocket, 5);
|
||||
if (rc < 0) {
|
||||
ESP_LOGE(tag, "listen: %d (%s)", errno, strerror(errno));
|
||||
ESP_LOGE(TAG, "listen: %d (%s)", errno, strerror(errno));
|
||||
close(serverSocket);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -156,16 +180,17 @@ static void telnet_task(void *data) {
|
||||
socklen_t len = sizeof(serverAddr);
|
||||
rc = accept(serverSocket, (struct sockaddr *)&serverAddr, &len);
|
||||
if (rc < 0 ){
|
||||
ESP_LOGE(tag, "accept: %d (%s)", errno, strerror(errno));
|
||||
ESP_LOGE(TAG, "accept: %d (%s)", errno, strerror(errno));
|
||||
return;
|
||||
}
|
||||
else {
|
||||
partnerSocket = rc;
|
||||
ESP_LOGD(tag, "We have a new client connection!");
|
||||
ESP_LOGD(TAG, "We have a new client connection!");
|
||||
handle_telnet_conn();
|
||||
ESP_LOGD(tag, "Telnet connection terminated");
|
||||
ESP_LOGD(TAG, "Telnet connection terminated");
|
||||
}
|
||||
}
|
||||
close(serverSocket);
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
@@ -228,7 +253,9 @@ void process_received_data(const char * buffer, size_t size){
|
||||
command[size]='\0';
|
||||
if(command[0]!='\r' && command[0]!='\n'){
|
||||
// echo the command buffer out to uart and run
|
||||
if(bMirrorToUART){
|
||||
write(uart_fd, command, size);
|
||||
}
|
||||
run_command((char *)command);
|
||||
}
|
||||
free(command);
|
||||
@@ -265,23 +292,23 @@ static void handle_telnet_events(
|
||||
} // myhandle_telnet_events
|
||||
|
||||
|
||||
static void process_logs(UBaseType_t count){
|
||||
static void process_logs( UBaseType_t bytes, bool is_write_op){
|
||||
//Receive an item from no-split ring buffer
|
||||
size_t item_size;
|
||||
UBaseType_t uxItemsWaiting;
|
||||
UBaseType_t uxBytesToSend=count;
|
||||
UBaseType_t uxBytesToSend=bytes;
|
||||
|
||||
vRingbufferGetInfo(buf_handle, NULL, NULL, NULL, NULL, &uxItemsWaiting);
|
||||
if(count == 0){
|
||||
// this sends the entire buffer to the remote client
|
||||
uxBytesToSend = uxItemsWaiting;
|
||||
}
|
||||
if( partnerSocket ==0 && (uxItemsWaiting*100 / log_buf_size) <75){
|
||||
// We still have some room in the ringbuffer and there's no telnet
|
||||
// connection yet, so bail out for now.
|
||||
//printf("%s() Log buffer used %u of %u bytes used\n", __FUNCTION__, uxItemsWaiting, log_buf_size);
|
||||
bool is_space_available = ((log_buf_size-uxItemsWaiting)>=bytes && log_buf_size>uxItemsWaiting);
|
||||
if( is_space_available && (is_write_op || partnerSocket == 0) ){
|
||||
// there's still some room left in the buffer, and we're either
|
||||
// processing a write operation or telnet isn't connected yet.
|
||||
return;
|
||||
}
|
||||
if(is_write_op && !is_space_available && uxBytesToSend==0){
|
||||
// flush at least the size of a full chunk
|
||||
uxBytesToSend = send_chunk;
|
||||
}
|
||||
|
||||
while(uxBytesToSend>0){
|
||||
char *item = (char *)xRingbufferReceiveUpTo(buf_handle, &item_size, pdMS_TO_TICKS(50), uxBytesToSend);
|
||||
@@ -322,7 +349,7 @@ static void handle_telnet_conn() {
|
||||
pTelnetUserData->sockfd = partnerSocket;
|
||||
|
||||
// flush all the log buffer on connect
|
||||
process_logs(0);
|
||||
process_logs(log_buf_size, false);
|
||||
|
||||
while(1) {
|
||||
//ESP_LOGD(tag, "waiting for data");
|
||||
@@ -339,7 +366,7 @@ static void handle_telnet_conn() {
|
||||
partnerSocket = 0;
|
||||
return;
|
||||
}
|
||||
process_logs(send_chunk);
|
||||
process_logs(send_chunk, false);
|
||||
|
||||
taskYIELD();
|
||||
}
|
||||
@@ -348,37 +375,24 @@ static void handle_telnet_conn() {
|
||||
|
||||
// ******************* stdout/stderr Redirection to ringbuffer
|
||||
static ssize_t stdout_write(int fd, const void * data, size_t size) {
|
||||
if (xSemaphoreTake(xSemaphore, (TickType_t) 10) == pdTRUE) {
|
||||
// #1 Write to ringbuffer
|
||||
if (buf_handle == NULL) {
|
||||
printf("%s() ABORT. file handle _log_remote_fp is NULL\n",
|
||||
__FUNCTION__);
|
||||
} else {
|
||||
// flush the buffer if needed
|
||||
process_logs(size, true);
|
||||
//Send an item
|
||||
UBaseType_t res = xRingbufferSend(buf_handle, data, size,
|
||||
pdMS_TO_TICKS(100));
|
||||
if (res != pdTRUE) {
|
||||
// flush some entries
|
||||
process_logs(size);
|
||||
res = xRingbufferSend(buf_handle, data, size,
|
||||
pdMS_TO_TICKS(100));
|
||||
if (res != pdTRUE) {
|
||||
UBaseType_t res = xRingbufferSend(buf_handle, data, size, pdMS_TO_TICKS(10));
|
||||
assert(res == pdTRUE);
|
||||
|
||||
printf("%s() ABORT. Unable to store log entry in buffer\n",
|
||||
__FUNCTION__);
|
||||
}
|
||||
}
|
||||
}
|
||||
xSemaphoreGive(xSemaphore);
|
||||
} else {
|
||||
// We could not obtain the semaphore and can therefore not access
|
||||
// the shared resource safely.
|
||||
}
|
||||
return write(uart_fd, data, size);
|
||||
return bMirrorToUART?write(uart_fd, data, size):size;
|
||||
}
|
||||
|
||||
static ssize_t stdout_read(int fd, void* data, size_t size) {
|
||||
return read(fd, data, size);
|
||||
//return read(fd, data, size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int stdout_open(const char * path, int flags, int mode) {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
|
||||
void init_telnet();
|
||||
void start_telnet(void * pvParameter);
|
||||
extern bool is_serial_suppressed();
|
||||
|
||||
@@ -31,9 +31,4 @@ extern bool wait_for_wifi();
|
||||
extern void console_start();
|
||||
extern pthread_cond_t wifi_connect_suspend_cond;
|
||||
extern pthread_t wifi_connect_suspend_mutex;
|
||||
typedef enum {
|
||||
INFO,
|
||||
WARNING,
|
||||
ERROR
|
||||
} message_severity_t;
|
||||
extern void set_status_message(message_severity_t severity, const char * message);
|
||||
|
||||
|
||||
@@ -28,5 +28,20 @@
|
||||
#define STR(macro) QUOTE(macro)
|
||||
#endif
|
||||
#define ESP_LOG_DEBUG_EVENT(tag,e) ESP_LOGD(tag,"evt: " e)
|
||||
#ifndef STR_OR_ALT
|
||||
#define STR_OR_ALT(str,alt) (str?str:alt)
|
||||
#endif
|
||||
|
||||
extern const char unknown_string_placeholder[];
|
||||
extern const char * str_or_unknown(const char * str);
|
||||
|
||||
#ifndef FREE_AND_NULL
|
||||
#define FREE_AND_NULL(x) if(x) { free(x); x=NULL; }
|
||||
#endif
|
||||
|
||||
#ifndef CASE_TO_STR
|
||||
#define CASE_TO_STR(x) case x: return STR(x); break;
|
||||
#endif
|
||||
#define START_FREE_MEM_CHECK(a) size_t a=heap_caps_get_free_size(MALLOC_CAP_INTERNAL);
|
||||
#define CHECK_RESET_FREE_MEM_CHECK(a,b) ESP_LOGV(__FUNCTION__ ,b "Mem used: %i",a-heap_caps_get_free_size(MALLOC_CAP_INTERNAL)); a=heap_caps_get_free_size(MALLOC_CAP_INTERNAL)
|
||||
|
||||
|
||||
93
components/wifi-manager/_esp_http_server.h
Normal file
93
components/wifi-manager/_esp_http_server.h
Normal file
@@ -0,0 +1,93 @@
|
||||
// Copyright 2018 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef __ESP_HTTP_SERVER_H_
|
||||
#define __ESP_HTTP_SERVER_H_
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <freertos/task.h>
|
||||
#include <http_parser.h>
|
||||
#include <sdkconfig.h>
|
||||
#include <esp_err.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Starts the web server
|
||||
*
|
||||
* Create an instance of HTTP server and allocate memory/resources for it
|
||||
* depending upon the specified configuration.
|
||||
*
|
||||
* Example usage:
|
||||
* @code{c}
|
||||
*
|
||||
* //Function for starting the webserver
|
||||
* httpd_handle_t start_webserver(void)
|
||||
* {
|
||||
* // Generate default configuration
|
||||
* httpd_config_t config = HTTPD_DEFAULT_CONFIG();
|
||||
*
|
||||
* // Empty handle to http_server
|
||||
* httpd_handle_t server = NULL;
|
||||
*
|
||||
* // Start the httpd server
|
||||
* if (httpd_start(&server, &config) == ESP_OK) {
|
||||
* // Register URI handlers
|
||||
* httpd_register_uri_handler(server, &uri_get);
|
||||
* httpd_register_uri_handler(server, &uri_post);
|
||||
* }
|
||||
* // If server failed to start, handle will be NULL
|
||||
* return server;
|
||||
* }
|
||||
*
|
||||
* @endcode
|
||||
*
|
||||
* @param[in] config Configuration for new instance of the server
|
||||
* @param[out] handle Handle to newly created instance of the server. NULL on error
|
||||
* @return
|
||||
* - ESP_OK : Instance created successfully
|
||||
* - ESP_ERR_INVALID_ARG : Null argument(s)
|
||||
* - ESP_ERR_HTTPD_ALLOC_MEM : Failed to allocate memory for instance
|
||||
* - ESP_ERR_HTTPD_TASK : Failed to launch server task
|
||||
*/
|
||||
esp_err_t __httpd_start(httpd_handle_t *handle, const httpd_config_t *config);
|
||||
static inline int __httpd_os_thread_create_static(TaskHandle_t *thread,
|
||||
const char *name, uint16_t stacksize, int prio,
|
||||
void (*thread_routine)(void *arg), void *arg,
|
||||
BaseType_t core_id)
|
||||
{
|
||||
|
||||
|
||||
StaticTask_t *xTaskBuffer = (StaticTask_t*) heap_caps_malloc(sizeof(StaticTask_t), (MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT));
|
||||
StackType_t *xStack = heap_caps_malloc(stacksize,(MALLOC_CAP_SPIRAM|MALLOC_CAP_8BIT));
|
||||
|
||||
|
||||
//
|
||||
*thread = xTaskCreateStaticPinnedToCore(thread_routine, name, stacksize, arg, prio, xStack,xTaskBuffer,core_id);
|
||||
if (*thread) {
|
||||
return ESP_OK;
|
||||
}
|
||||
return ESP_FAIL;
|
||||
}
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ! _ESP_HTTP_SERVER_H_ */
|
||||
373
components/wifi-manager/_esp_httpd_main.c
Normal file
373
components/wifi-manager/_esp_httpd_main.c
Normal file
@@ -0,0 +1,373 @@
|
||||
// Copyright 2018 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/param.h>
|
||||
#include <errno.h>
|
||||
#include <esp_log.h>
|
||||
#include <esp_err.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <esp_http_server.h>
|
||||
#include <_esp_http_server.h>
|
||||
#include "esp_httpd_priv.h"
|
||||
#include "ctrl_sock.h"
|
||||
|
||||
static const char *TAG = "_httpd";
|
||||
|
||||
|
||||
struct httpd_ctrl_data {
|
||||
enum httpd_ctrl_msg {
|
||||
HTTPD_CTRL_SHUTDOWN,
|
||||
HTTPD_CTRL_WORK,
|
||||
} hc_msg;
|
||||
httpd_work_fn_t hc_work;
|
||||
void *hc_work_arg;
|
||||
};
|
||||
|
||||
|
||||
static esp_err_t _httpd_server_init(struct httpd_data *hd)
|
||||
{
|
||||
int fd = socket(PF_INET6, SOCK_STREAM, 0);
|
||||
if (fd < 0) {
|
||||
ESP_LOGE(TAG, LOG_FMT("error in socket (%d)"), errno);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
struct in6_addr inaddr_any = IN6ADDR_ANY_INIT;
|
||||
struct sockaddr_in6 serv_addr = {
|
||||
.sin6_family = PF_INET6,
|
||||
.sin6_addr = inaddr_any,
|
||||
.sin6_port = htons(hd->config.server_port)
|
||||
};
|
||||
|
||||
/* Enable SO_REUSEADDR to allow binding to the same
|
||||
* address and port when restarting the server */
|
||||
int enable = 1;
|
||||
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable)) < 0) {
|
||||
/* This will fail if CONFIG_LWIP_SO_REUSE is not enabled. But
|
||||
* it does not affect the normal working of the HTTP Server */
|
||||
ESP_LOGW(TAG, LOG_FMT("error enabling SO_REUSEADDR (%d)"), errno);
|
||||
}
|
||||
|
||||
int ret = bind(fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));
|
||||
if (ret < 0) {
|
||||
ESP_LOGE(TAG, LOG_FMT("error in bind (%d)"), errno);
|
||||
close(fd);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
ret = listen(fd, hd->config.backlog_conn);
|
||||
if (ret < 0) {
|
||||
ESP_LOGE(TAG, LOG_FMT("error in listen (%d)"), errno);
|
||||
close(fd);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
int ctrl_fd = cs_create_ctrl_sock(hd->config.ctrl_port);
|
||||
if (ctrl_fd < 0) {
|
||||
ESP_LOGE(TAG, LOG_FMT("error in creating ctrl socket (%d)"), errno);
|
||||
close(fd);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
int msg_fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||
if (msg_fd < 0) {
|
||||
ESP_LOGE(TAG, LOG_FMT("error in creating msg socket (%d)"), errno);
|
||||
close(fd);
|
||||
close(ctrl_fd);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
hd->listen_fd = fd;
|
||||
hd->ctrl_fd = ctrl_fd;
|
||||
hd->msg_fd = msg_fd;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static void _httpd_process_ctrl_msg(struct httpd_data *hd)
|
||||
{
|
||||
struct httpd_ctrl_data msg;
|
||||
int ret = recv(hd->ctrl_fd, &msg, sizeof(msg), 0);
|
||||
if (ret <= 0) {
|
||||
ESP_LOGW(TAG, LOG_FMT("error in recv (%d)"), errno);
|
||||
return;
|
||||
}
|
||||
if (ret != sizeof(msg)) {
|
||||
ESP_LOGW(TAG, LOG_FMT("incomplete msg"));
|
||||
return;
|
||||
}
|
||||
|
||||
switch (msg.hc_msg) {
|
||||
case HTTPD_CTRL_WORK:
|
||||
if (msg.hc_work) {
|
||||
ESP_LOGD(TAG, LOG_FMT("work"));
|
||||
(*msg.hc_work)(msg.hc_work_arg);
|
||||
}
|
||||
break;
|
||||
case HTTPD_CTRL_SHUTDOWN:
|
||||
ESP_LOGD(TAG, LOG_FMT("shutdown"));
|
||||
hd->hd_td.status = THREAD_STOPPING;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static esp_err_t _httpd_accept_conn(struct httpd_data *hd, int listen_fd)
|
||||
{
|
||||
/* If no space is available for new session, close the least recently used one */
|
||||
if (hd->config.lru_purge_enable == true) {
|
||||
if (!httpd_is_sess_available(hd)) {
|
||||
/* Queue asynchronous closure of the least recently used session */
|
||||
return httpd_sess_close_lru(hd);
|
||||
/* Returning from this allowes the main server thread to process
|
||||
* the queued asynchronous control message for closing LRU session.
|
||||
* Since connection request hasn't been addressed yet using accept()
|
||||
* therefore _httpd_accept_conn() will be called again, but this time
|
||||
* with space available for one session
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
struct sockaddr_in addr_from;
|
||||
socklen_t addr_from_len = sizeof(addr_from);
|
||||
int new_fd = accept(listen_fd, (struct sockaddr *)&addr_from, &addr_from_len);
|
||||
if (new_fd < 0) {
|
||||
ESP_LOGW(TAG, LOG_FMT("error in accept (%d)"), errno);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
ESP_LOGD(TAG, LOG_FMT("newfd = %d"), new_fd);
|
||||
|
||||
struct timeval tv;
|
||||
/* Set recv timeout of this fd as per config */
|
||||
tv.tv_sec = hd->config.recv_wait_timeout;
|
||||
tv.tv_usec = 0;
|
||||
setsockopt(new_fd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof(tv));
|
||||
|
||||
/* Set send timeout of this fd as per config */
|
||||
tv.tv_sec = hd->config.send_wait_timeout;
|
||||
tv.tv_usec = 0;
|
||||
setsockopt(new_fd, SOL_SOCKET, SO_SNDTIMEO, (const char*)&tv, sizeof(tv));
|
||||
|
||||
if (ESP_OK != httpd_sess_new(hd, new_fd)) {
|
||||
ESP_LOGW(TAG, LOG_FMT("session creation failed"));
|
||||
close(new_fd);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
ESP_LOGD(TAG, LOG_FMT("complete"));
|
||||
return ESP_OK;
|
||||
}
|
||||
/* Manage in-coming connection or data requests */
|
||||
static esp_err_t _httpd_server(struct httpd_data *hd)
|
||||
{
|
||||
fd_set read_set;
|
||||
FD_ZERO(&read_set);
|
||||
if (hd->config.lru_purge_enable || httpd_is_sess_available(hd)) {
|
||||
/* Only listen for new connections if server has capacity to
|
||||
* handle more (or when LRU purge is enabled, in which case
|
||||
* older connections will be closed) */
|
||||
FD_SET(hd->listen_fd, &read_set);
|
||||
}
|
||||
FD_SET(hd->ctrl_fd, &read_set);
|
||||
|
||||
int tmp_max_fd;
|
||||
httpd_sess_set_descriptors(hd, &read_set, &tmp_max_fd);
|
||||
int maxfd = MAX(hd->listen_fd, tmp_max_fd);
|
||||
tmp_max_fd = maxfd;
|
||||
maxfd = MAX(hd->ctrl_fd, tmp_max_fd);
|
||||
|
||||
ESP_LOGD(TAG, LOG_FMT("doing select maxfd+1 = %d"), maxfd + 1);
|
||||
int active_cnt = select(maxfd + 1, &read_set, NULL, NULL, NULL);
|
||||
if (active_cnt < 0) {
|
||||
ESP_LOGE(TAG, LOG_FMT("error in select (%d)"), errno);
|
||||
httpd_sess_delete_invalid(hd);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/* Case0: Do we have a control message? */
|
||||
if (FD_ISSET(hd->ctrl_fd, &read_set)) {
|
||||
ESP_LOGD(TAG, LOG_FMT("processing ctrl message"));
|
||||
_httpd_process_ctrl_msg(hd);
|
||||
if (hd->hd_td.status == THREAD_STOPPING) {
|
||||
ESP_LOGD(TAG, LOG_FMT("stopping thread"));
|
||||
return ESP_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Case1: Do we have any activity on the current data
|
||||
* sessions? */
|
||||
int fd = -1;
|
||||
while ((fd = httpd_sess_iterate(hd, fd)) != -1) {
|
||||
if (FD_ISSET(fd, &read_set) || (httpd_sess_pending(hd, fd))) {
|
||||
ESP_LOGD(TAG, LOG_FMT("processing socket %d"), fd);
|
||||
if (httpd_sess_process(hd, fd) != ESP_OK) {
|
||||
ESP_LOGD(TAG, LOG_FMT("closing socket %d"), fd);
|
||||
close(fd);
|
||||
/* Delete session and update fd to that
|
||||
* preceding the one being deleted */
|
||||
fd = httpd_sess_delete(hd, fd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Case2: Do we have any incoming connection requests to
|
||||
* process? */
|
||||
if (FD_ISSET(hd->listen_fd, &read_set)) {
|
||||
ESP_LOGD(TAG, LOG_FMT("processing listen socket %d"), hd->listen_fd);
|
||||
if (_httpd_accept_conn(hd, hd->listen_fd) != ESP_OK) {
|
||||
ESP_LOGW(TAG, LOG_FMT("error accepting new connection"));
|
||||
}
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static void _httpd_close_all_sessions(struct httpd_data *hd)
|
||||
{
|
||||
int fd = -1;
|
||||
while ((fd = httpd_sess_iterate(hd, fd)) != -1) {
|
||||
ESP_LOGD(TAG, LOG_FMT("cleaning up socket %d"), fd);
|
||||
httpd_sess_delete(hd, fd);
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
/* The main HTTPD thread */
|
||||
static void _httpd_thread(void *arg)
|
||||
{
|
||||
int ret;
|
||||
struct httpd_data *hd = (struct httpd_data *) arg;
|
||||
hd->hd_td.status = THREAD_RUNNING;
|
||||
|
||||
ESP_LOGD(TAG, LOG_FMT("web server started"));
|
||||
while (1) {
|
||||
ret = _httpd_server(hd);
|
||||
if (ret != ESP_OK) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ESP_LOGD(TAG, LOG_FMT("web server exiting"));
|
||||
close(hd->msg_fd);
|
||||
cs_free_ctrl_sock(hd->ctrl_fd);
|
||||
_httpd_close_all_sessions(hd);
|
||||
close(hd->listen_fd);
|
||||
hd->hd_td.status = THREAD_STOPPED;
|
||||
httpd_os_thread_delete();
|
||||
}
|
||||
static struct httpd_data *__httpd_create(const httpd_config_t *config)
|
||||
{
|
||||
/* Allocate memory for httpd instance data */
|
||||
struct httpd_data *hd = calloc(1, sizeof(struct httpd_data));
|
||||
if (!hd) {
|
||||
ESP_LOGE(TAG, LOG_FMT("Failed to allocate memory for HTTP server instance"));
|
||||
return NULL;
|
||||
}
|
||||
hd->hd_calls = calloc(config->max_uri_handlers, sizeof(httpd_uri_t *));
|
||||
if (!hd->hd_calls) {
|
||||
ESP_LOGE(TAG, LOG_FMT("Failed to allocate memory for HTTP URI handlers"));
|
||||
free(hd);
|
||||
return NULL;
|
||||
}
|
||||
hd->hd_sd = calloc(config->max_open_sockets, sizeof(struct sock_db));
|
||||
if (!hd->hd_sd) {
|
||||
ESP_LOGE(TAG, LOG_FMT("Failed to allocate memory for HTTP session data"));
|
||||
free(hd->hd_calls);
|
||||
free(hd);
|
||||
return NULL;
|
||||
}
|
||||
struct httpd_req_aux *ra = &hd->hd_req_aux;
|
||||
ra->resp_hdrs = calloc(config->max_resp_headers, sizeof(struct resp_hdr));
|
||||
if (!ra->resp_hdrs) {
|
||||
ESP_LOGE(TAG, LOG_FMT("Failed to allocate memory for HTTP response headers"));
|
||||
free(hd->hd_sd);
|
||||
free(hd->hd_calls);
|
||||
free(hd);
|
||||
return NULL;
|
||||
}
|
||||
hd->err_handler_fns = calloc(HTTPD_ERR_CODE_MAX, sizeof(httpd_err_handler_func_t));
|
||||
if (!hd->err_handler_fns) {
|
||||
ESP_LOGE(TAG, LOG_FMT("Failed to allocate memory for HTTP error handlers"));
|
||||
free(ra->resp_hdrs);
|
||||
free(hd->hd_sd);
|
||||
free(hd->hd_calls);
|
||||
free(hd);
|
||||
return NULL;
|
||||
}
|
||||
/* Save the configuration for this instance */
|
||||
hd->config = *config;
|
||||
return hd;
|
||||
}
|
||||
static void _httpd_delete(struct httpd_data *hd)
|
||||
{
|
||||
struct httpd_req_aux *ra = &hd->hd_req_aux;
|
||||
/* Free memory of httpd instance data */
|
||||
free(hd->err_handler_fns);
|
||||
free(ra->resp_hdrs);
|
||||
free(hd->hd_sd);
|
||||
|
||||
/* Free registered URI handlers */
|
||||
httpd_unregister_all_uri_handlers(hd);
|
||||
free(hd->hd_calls);
|
||||
free(hd);
|
||||
}
|
||||
esp_err_t __httpd_start(httpd_handle_t *handle, const httpd_config_t *config)
|
||||
{
|
||||
if (handle == NULL || config == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
/* Sanity check about whether LWIP is configured for providing the
|
||||
* maximum number of open sockets sufficient for the server. Though,
|
||||
* this check doesn't guarantee that many sockets will actually be
|
||||
* available at runtime as other processes may use up some sockets.
|
||||
* Note that server also uses 3 sockets for its internal use :
|
||||
* 1) listening for new TCP connections
|
||||
* 2) for sending control messages over UDP
|
||||
* 3) for receiving control messages over UDP
|
||||
* So the total number of required sockets is max_open_sockets + 3
|
||||
*/
|
||||
if (CONFIG_LWIP_MAX_SOCKETS < config->max_open_sockets + 3) {
|
||||
ESP_LOGE(TAG, "Configuration option max_open_sockets is too large (max allowed %d)\n\t"
|
||||
"Either decrease this or configure LWIP_MAX_SOCKETS to a larger value",
|
||||
CONFIG_LWIP_MAX_SOCKETS - 3);
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
struct httpd_data *hd = __httpd_create(config);
|
||||
if (hd == NULL) {
|
||||
/* Failed to allocate memory */
|
||||
return ESP_ERR_HTTPD_ALLOC_MEM;
|
||||
}
|
||||
|
||||
if (_httpd_server_init(hd) != ESP_OK) {
|
||||
_httpd_delete(hd);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
httpd_sess_init(hd);
|
||||
if (__httpd_os_thread_create_static(&hd->hd_td.handle, "httpd",
|
||||
hd->config.stack_size,
|
||||
hd->config.task_priority,
|
||||
_httpd_thread, hd,
|
||||
hd->config.core_id) != ESP_OK) {
|
||||
/* Failed to launch task */
|
||||
_httpd_delete(hd);
|
||||
return ESP_ERR_HTTPD_TASK;
|
||||
}
|
||||
|
||||
*handle = (httpd_handle_t *)hd;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@@ -10,7 +10,28 @@ if (!String.prototype.format) {
|
||||
});
|
||||
};
|
||||
}
|
||||
var nvs_type_t = {
|
||||
NVS_TYPE_U8 : 0x01, /*!< Type uint8_t */
|
||||
NVS_TYPE_I8 : 0x11, /*!< Type int8_t */
|
||||
NVS_TYPE_U16 : 0x02, /*!< Type uint16_t */
|
||||
NVS_TYPE_I16 : 0x12, /*!< Type int16_t */
|
||||
NVS_TYPE_U32 : 0x04, /*!< Type uint32_t */
|
||||
NVS_TYPE_I32 : 0x14, /*!< Type int32_t */
|
||||
NVS_TYPE_U64 : 0x08, /*!< Type uint64_t */
|
||||
NVS_TYPE_I64 : 0x18, /*!< Type int64_t */
|
||||
NVS_TYPE_STR : 0x21, /*!< Type string */
|
||||
NVS_TYPE_BLOB : 0x42, /*!< Type blob */
|
||||
NVS_TYPE_ANY : 0xff /*!< Must be last */
|
||||
} ;
|
||||
|
||||
var task_state_t = {
|
||||
0 : "eRunning", /*!< A task is querying the state of itself, so must be running. */
|
||||
1 : "eReady", /*!< The task being queried is in a read or pending ready list. */
|
||||
2 : "eBlocked", /*!< The task being queried is in the Blocked state. */
|
||||
3 : "eSuspended", /*!< The task being queried is in the Suspended state, or is in the Blocked state with an infinite time out. */
|
||||
4 : "eDeleted"
|
||||
|
||||
}
|
||||
var releaseURL = 'https://api.github.com/repos/sle118/squeezelite-esp32/releases';
|
||||
var recovery = false;
|
||||
var enableAPTimer = true;
|
||||
@@ -19,7 +40,6 @@ var commandHeader = 'squeezelite -b 500:2000 -d all=info ';
|
||||
var pname, ver, otapct, otadsc;
|
||||
var blockAjax = false;
|
||||
var blockFlashButton = false;
|
||||
var lastMsg = '';
|
||||
|
||||
var apList = null;
|
||||
var selectedSSID = "";
|
||||
@@ -189,20 +209,29 @@ $(document).ready(function(){
|
||||
$("input#autoexec-cb").on("click", function() {
|
||||
var data = { 'timestamp': Date.now() };
|
||||
autoexec = (this.checked)?1:0;
|
||||
data['autoexec'] = autoexec;
|
||||
showMessage('please wait for the ESP32 to reboot', 'WARNING');
|
||||
data['config'] = {};
|
||||
data['config'] = {
|
||||
autoexec : {
|
||||
value : autoexec,
|
||||
type : 33
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
showMessage('please wait for the ESP32 to reboot', 'MESSAGING_WARNING');
|
||||
$.ajax({
|
||||
url: '/config.json',
|
||||
dataType: 'text',
|
||||
method: 'POST',
|
||||
cache: false,
|
||||
headers: { "X-Custom-autoexec": autoexec },
|
||||
// headers: { "X-Custom-autoexec": autoexec },
|
||||
contentType: 'application/json; charset=utf-8',
|
||||
data: JSON.stringify(data),
|
||||
|
||||
error: function (xhr, ajaxOptions, thrownError) {
|
||||
console.log(xhr.status);
|
||||
console.log(thrownError);
|
||||
if (thrownError != '') showMessage(thrownError, 'ERROR');
|
||||
if (thrownError != '') showMessage(thrownError, 'MESSAGING_ERROR');
|
||||
},
|
||||
complete: function(response) {
|
||||
//var returnedResponse = JSON.parse(response.responseText);
|
||||
@@ -219,7 +248,7 @@ $(document).ready(function(){
|
||||
error: function (xhr, ajaxOptions, thrownError) {
|
||||
console.log(xhr.status);
|
||||
console.log(thrownError);
|
||||
if (thrownError != '') showMessage(thrownError, 'ERROR');
|
||||
if (thrownError != '') showMessage(thrownError, 'MESSAGING_ERROR');
|
||||
},
|
||||
complete: function(response) {
|
||||
console.log('reboot call completed');
|
||||
@@ -232,20 +261,26 @@ $(document).ready(function(){
|
||||
$("input#save-autoexec1").on("click", function() {
|
||||
var data = { 'timestamp': Date.now() };
|
||||
autoexec1 = $("#autoexec1").val();
|
||||
data['autoexec1'] = autoexec1;
|
||||
data['config'] = {};
|
||||
data['config'] = {
|
||||
autoexec1 : {
|
||||
value : autoexec1,
|
||||
type : 33
|
||||
}
|
||||
}
|
||||
|
||||
$.ajax({
|
||||
url: '/config.json',
|
||||
dataType: 'text',
|
||||
method: 'POST',
|
||||
cache: false,
|
||||
headers: { "X-Custom-autoexec1": autoexec1 },
|
||||
// headers: { "X-Custom-autoexec1": autoexec1 },
|
||||
contentType: 'application/json; charset=utf-8',
|
||||
data: JSON.stringify(data),
|
||||
error: function (xhr, ajaxOptions, thrownError) {
|
||||
console.log(xhr.status);
|
||||
console.log(thrownError);
|
||||
if (thrownError != '') showMessage(thrownError, 'ERROR');
|
||||
if (thrownError != '') showMessage(thrownError, 'MESSAGING_ERROR');
|
||||
}
|
||||
});
|
||||
console.log('sent config JSON with headers:', autoexec1);
|
||||
@@ -254,15 +289,19 @@ $(document).ready(function(){
|
||||
|
||||
$("input#save-gpio").on("click", function() {
|
||||
var data = { 'timestamp': Date.now() };
|
||||
var config = {};
|
||||
|
||||
var headers = {};
|
||||
$("input.gpio").each(function() {
|
||||
var id = $(this)[0].id;
|
||||
var pin = $(this).val();
|
||||
if (pin != '') {
|
||||
headers["X-Custom-"+id] = pin;
|
||||
data[id] = pin;
|
||||
config[id] = {};
|
||||
config[id].value = pin;
|
||||
config[id].type = nvs_type_t.NVS_TYPE_STR;
|
||||
}
|
||||
});
|
||||
data['config'] = config;
|
||||
$.ajax({
|
||||
url: '/config.json',
|
||||
dataType: 'text',
|
||||
@@ -274,7 +313,7 @@ $(document).ready(function(){
|
||||
error: function (xhr, ajaxOptions, thrownError) {
|
||||
console.log(xhr.status);
|
||||
console.log(thrownError);
|
||||
if (thrownError != '') showMessage(thrownError, 'ERROR');
|
||||
if (thrownError != '') showMessage(thrownError, 'MESSAGING_ERROR');
|
||||
}
|
||||
});
|
||||
console.log('sent config JSON with headers:', JSON.stringify(headers));
|
||||
@@ -284,23 +323,40 @@ $(document).ready(function(){
|
||||
$("#save-nvs").on("click", function() {
|
||||
var headers = {};
|
||||
var data = { 'timestamp': Date.now() };
|
||||
var config = {};
|
||||
$("input.nvs").each(function() {
|
||||
var key = $(this)[0].id;
|
||||
var val = $(this).val();
|
||||
var nvs_type = parseInt($(this)[0].attributes.nvs_type.nodeValue,10);
|
||||
if (key != '') {
|
||||
headers["X-Custom-"+key] = val;
|
||||
data[key] = {};
|
||||
data[key].value = val;
|
||||
data[key].type = 33;
|
||||
config[key] = {};
|
||||
if(nvs_type == nvs_type_t.NVS_TYPE_U8
|
||||
|| nvs_type == nvs_type_t.NVS_TYPE_I8
|
||||
|| nvs_type == nvs_type_t.NVS_TYPE_U16
|
||||
|| nvs_type == nvs_type_t.NVS_TYPE_I16
|
||||
|| nvs_type == nvs_type_t.NVS_TYPE_U32
|
||||
|| nvs_type == nvs_type_t.NVS_TYPE_I32
|
||||
|| nvs_type == nvs_type_t.NVS_TYPE_U64
|
||||
|| nvs_type == nvs_type_t.NVS_TYPE_I64) {
|
||||
config[key].value = parseInt(val);
|
||||
}
|
||||
else {
|
||||
config[key].value = val;
|
||||
}
|
||||
|
||||
|
||||
config[key].type = nvs_type;
|
||||
}
|
||||
});
|
||||
var key = $("#nvs-new-key").val();
|
||||
var val = $("#nvs-new-value").val();
|
||||
if (key != '') {
|
||||
headers["X-Custom-"+key] = val;
|
||||
data[key] = {};
|
||||
data[key].value = val;
|
||||
// headers["X-Custom-" +key] = val;
|
||||
config[key] = {};
|
||||
config[key].value = val;
|
||||
config[key].type = 33;
|
||||
}
|
||||
data['config'] = config;
|
||||
$.ajax({
|
||||
url: '/config.json',
|
||||
dataType: 'text',
|
||||
@@ -308,35 +364,64 @@ $(document).ready(function(){
|
||||
cache: false,
|
||||
headers: headers,
|
||||
contentType: 'application/json; charset=utf-8',
|
||||
data: JSON.stringify(data),
|
||||
data : JSON.stringify(data),
|
||||
error: function (xhr, ajaxOptions, thrownError) {
|
||||
console.log(xhr.status);
|
||||
console.log(thrownError);
|
||||
if (thrownError != '') showMessage(thrownError, 'ERROR');
|
||||
if (thrownError != '') showMessage(thrownError, 'MESSAGING_ERROR');
|
||||
}
|
||||
});
|
||||
console.log('sent config JSON with headers:', JSON.stringify(headers));
|
||||
console.log('sent config JSON with data:', JSON.stringify(data));
|
||||
});
|
||||
|
||||
$("#fwUpload").on("click", function() {
|
||||
var upload_path = "/flash.json";
|
||||
var fileInput = document.getElementById("flashfilename").files;
|
||||
if (fileInput.length == 0) {
|
||||
alert("No file selected!");
|
||||
} else {
|
||||
var file = fileInput[0];
|
||||
var xhttp = new XMLHttpRequest();
|
||||
xhttp.onreadystatechange = function() {
|
||||
if (xhttp.readyState == 4) {
|
||||
if (xhttp.status == 200) {
|
||||
showMessage(xhttp.responseText, 'MESSAGING_INFO')
|
||||
} else if (xhttp.status == 0) {
|
||||
showMessage("Upload connection was closed abruptly!", 'MESSAGING_ERROR');
|
||||
} else {
|
||||
showMessage(xhttp.status + " Error!\n" + xhttp.responseText, 'MESSAGING_ERROR');
|
||||
}
|
||||
}
|
||||
};
|
||||
xhttp.open("POST", upload_path, true);
|
||||
xhttp.send(file);
|
||||
}
|
||||
enableStatusTimer = true;
|
||||
});
|
||||
$("#flash").on("click", function() {
|
||||
var data = { 'timestamp': Date.now() };
|
||||
if (blockFlashButton) return;
|
||||
blockFlashButton = true;
|
||||
var url = $("#fwurl").val();
|
||||
data['fwurl'] = url;
|
||||
data['config'] = {
|
||||
fwurl : {
|
||||
value : url,
|
||||
type : 33
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
$.ajax({
|
||||
url: '/config.json',
|
||||
dataType: 'text',
|
||||
method: 'POST',
|
||||
cache: false,
|
||||
headers: { "X-Custom-fwurl": url },
|
||||
contentType: 'application/json; charset=utf-8',
|
||||
data: JSON.stringify(data),
|
||||
error: function (xhr, ajaxOptions, thrownError) {
|
||||
console.log(xhr.status);
|
||||
console.log(thrownError);
|
||||
if (thrownError != '') showMessage(thrownError, 'ERROR');
|
||||
if (thrownError != '') showMessage(thrownError, 'MESSAGING_ERROR');
|
||||
}
|
||||
});
|
||||
enableStatusTimer = true;
|
||||
@@ -509,13 +594,17 @@ function performConnect(conntype){
|
||||
dataType: 'text',
|
||||
method: 'POST',
|
||||
cache: false,
|
||||
headers: { 'X-Custom-ssid': selectedSSID, 'X-Custom-pwd': pwd, 'X-Custom-host_name': dhcpname },
|
||||
// headers: { 'X-Custom-ssid': selectedSSID, 'X-Custom-pwd': pwd, 'X-Custom-host_name': dhcpname },
|
||||
contentType: 'application/json; charset=utf-8',
|
||||
data: { 'timestamp': Date.now()},
|
||||
data: JSON.stringify({ 'timestamp': Date.now(),
|
||||
'ssid' : selectedSSID,
|
||||
'pwd' : pwd,
|
||||
'host_name' : dhcpname
|
||||
}),
|
||||
error: function (xhr, ajaxOptions, thrownError) {
|
||||
console.log(xhr.status);
|
||||
console.log(thrownError);
|
||||
if (thrownError != '') showMessage(thrownError, 'ERROR');
|
||||
if (thrownError != '') showMessage(thrownError, 'MESSAGING_ERROR');
|
||||
}
|
||||
});
|
||||
|
||||
@@ -564,11 +653,76 @@ function refreshAPHTML(data){
|
||||
$( "#wifi-list" ).html(h)
|
||||
}
|
||||
|
||||
function getMessages() {
|
||||
$.getJSON("/messages.json?1", function(data) {
|
||||
data.forEach(function(msg) {
|
||||
var msg_age = msg["current_time"] - msg["sent_time"];
|
||||
var msg_time = new Date();
|
||||
msg_time.setTime( msg_time.getTime() - msg_age );
|
||||
switch (msg["class"]) {
|
||||
case "MESSAGING_CLASS_OTA":
|
||||
//message: "{"ota_dsc":"Erasing flash complete","ota_pct":0}"
|
||||
var ota_data = JSON.parse(msg["message"]);
|
||||
if (ota_data.hasOwnProperty('ota_pct') && ota_data['ota_pct'] != 0){
|
||||
otapct = ota_data['ota_pct'];
|
||||
$('.progress-bar').css('width', otapct+'%').attr('aria-valuenow', otapct);
|
||||
$('.progress-bar').html(otapct+'%');
|
||||
}
|
||||
if (ota_data.hasOwnProperty('ota_dsc') && ota_data['ota_dsc'] != ''){
|
||||
otadsc = ota_data['ota_dsc'];
|
||||
$("span#flash-status").html(otadsc);
|
||||
if (otadsc.match(/Error:/) || otapct > 95) {
|
||||
blockFlashButton = false;
|
||||
enableStatusTimer = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "MESSAGING_CLASS_STATS":
|
||||
// for task states, check structure : task_state_t
|
||||
var stats_data = JSON.parse(msg["message"]);
|
||||
console.log(msg_time.toLocaleString() + " - Number of tasks on the ESP32: " + stats_data["ntasks"]);
|
||||
var stats_tasks = stats_data["tasks"];
|
||||
console.log(msg_time.toLocaleString() + '\tname' + '\tcpu' + '\tstate'+ '\tminstk'+ '\tbprio'+ '\tcprio'+ '\tnum' );
|
||||
stats_tasks.forEach(function(task) {
|
||||
console.log(msg_time.toLocaleString() + '\t' + task["nme"] + '\t'+ task["cpu"] + '\t'+ task_state_t[task["st"]]+ '\t'+ task["minstk"]+ '\t'+ task["bprio"]+ '\t'+ task["cprio"]+ '\t'+ task["num"]);
|
||||
});
|
||||
break;
|
||||
case "MESSAGING_CLASS_SYSTEM":
|
||||
showMessage(msg["message"], msg["type"],msg_age);
|
||||
|
||||
$("#syslogTable").append(
|
||||
"<tr class='"+msg["type"]+"'>"+
|
||||
"<td>"+msg_time.toLocaleString()+"</td>"+
|
||||
"<td>"+msg["message"]+"</td>"+
|
||||
"</tr>"
|
||||
);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
})
|
||||
.fail(function(xhr, ajaxOptions, thrownError) {
|
||||
console.log(xhr.status);
|
||||
console.log(thrownError);
|
||||
if (thrownError != '') showMessage(thrownError, 'MESSAGING_ERROR');
|
||||
});
|
||||
/*
|
||||
Minstk is minimum stack space left
|
||||
Bprio is base priority
|
||||
cprio is current priority
|
||||
nme is name
|
||||
st is task state. I provided a "typedef" that you can use to convert to text
|
||||
cpu is cpu percent used
|
||||
*/
|
||||
}
|
||||
function checkStatus(){
|
||||
RepeatCheckStatusInterval();
|
||||
if (!enableStatusTimer) return;
|
||||
if (blockAjax) return;
|
||||
blockAjax = true;
|
||||
getMessages();
|
||||
$.getJSON( "/status.json", function( data ) {
|
||||
if (data.hasOwnProperty('ssid') && data['ssid'] != ""){
|
||||
if (data["ssid"] === selectedSSID){
|
||||
@@ -659,20 +813,24 @@ function checkStatus(){
|
||||
$("#otadiv").show();
|
||||
$('a[href^="#tab-audio"]').hide();
|
||||
$('a[href^="#tab-gpio"]').show();
|
||||
$('#uploaddiv').show();
|
||||
$("footer.footer").removeClass('sl');
|
||||
$("footer.footer").addClass('recovery');
|
||||
$("#boot-button").html('Reboot');
|
||||
$("#boot-form").attr('action', '/reboot_ota.json');
|
||||
|
||||
enableStatusTimer = true;
|
||||
} else {
|
||||
recovery = false;
|
||||
$("#otadiv").hide();
|
||||
$('a[href^="#tab-audio"]').show();
|
||||
$('a[href^="#tab-gpio"]').hide();
|
||||
$('#uploaddiv').hide();
|
||||
$("footer.footer").removeClass('recovery');
|
||||
$("footer.footer").addClass('sl');
|
||||
$("#boot-button").html('Recovery');
|
||||
$("#boot-form").attr('action', '/recovery.json');
|
||||
|
||||
enableStatusTimer = false;
|
||||
}
|
||||
}
|
||||
@@ -683,29 +841,10 @@ function checkStatus(){
|
||||
ver = data['version'];
|
||||
$("span#foot-fw").html("fw: <strong>"+ver+"</strong>, mode: <strong>"+pname+"</strong>");
|
||||
}
|
||||
if (data.hasOwnProperty('ota_pct') && data['ota_pct'] != 0){
|
||||
otapct = data['ota_pct'];
|
||||
$('.progress-bar').css('width', otapct+'%').attr('aria-valuenow', otapct);
|
||||
$('.progress-bar').html(otapct+'%');
|
||||
}
|
||||
if (data.hasOwnProperty('ota_dsc') && data['ota_dsc'] != ''){
|
||||
otadsc = data['ota_dsc'];
|
||||
$("span#flash-status").html(otadsc);
|
||||
if (otadsc.match(/Error:/) || otapct > 95) {
|
||||
blockFlashButton = false;
|
||||
enableStatusTimer = true;
|
||||
}
|
||||
} else {
|
||||
else {
|
||||
$("span#flash-status").html('');
|
||||
}
|
||||
if (data.hasOwnProperty('message') && data['message'] != ''){
|
||||
var msg = data['message'].text;
|
||||
var severity = data['message'].severity;
|
||||
if (msg != lastMsg) {
|
||||
showMessage(msg, severity);
|
||||
lastMsg = msg;
|
||||
}
|
||||
}
|
||||
|
||||
if (data.hasOwnProperty('Voltage')) {
|
||||
var voltage = data['Voltage'];
|
||||
var layer;
|
||||
@@ -735,7 +874,7 @@ function checkStatus(){
|
||||
.fail(function(xhr, ajaxOptions, thrownError) {
|
||||
console.log(xhr.status);
|
||||
console.log(thrownError);
|
||||
if (thrownError != '') showMessage(thrownError, 'ERROR');
|
||||
if (thrownError != '') showMessage(thrownError, 'MESSAGING_ERROR');
|
||||
blockAjax = false;
|
||||
});
|
||||
}
|
||||
@@ -770,7 +909,7 @@ function getConfig() {
|
||||
"<tr>"+
|
||||
"<td>"+key+"</td>"+
|
||||
"<td class='value'>"+
|
||||
"<input type='text' class='form-control nvs' id='"+key+"'>"+
|
||||
"<input type='text' class='form-control nvs' id='"+key+"' nvs_type="+data[key].type+" >"+
|
||||
"</td>"+
|
||||
"</tr>"
|
||||
);
|
||||
@@ -783,7 +922,7 @@ function getConfig() {
|
||||
"<input type='text' class='form-control' id='nvs-new-key' placeholder='new key'>"+
|
||||
"</td>"+
|
||||
"<td>"+
|
||||
"<input type='text' class='form-control' id='nvs-new-value' placeholder='new value'>"+
|
||||
"<input type='text' class='form-control' id='nvs-new-value' placeholder='new value' nvs_type=33 >"+ // todo: provide a way to choose field type
|
||||
"</td>"+
|
||||
"</tr>"
|
||||
);
|
||||
@@ -791,19 +930,23 @@ function getConfig() {
|
||||
.fail(function(xhr, ajaxOptions, thrownError) {
|
||||
console.log(xhr.status);
|
||||
console.log(thrownError);
|
||||
if (thrownError != '') showMessage(thrownError, 'ERROR');
|
||||
if (thrownError != '') showMessage(thrownError, 'MESSAGING_ERROR');
|
||||
blockAjax = false;
|
||||
});
|
||||
}
|
||||
|
||||
function showMessage(message, severity) {
|
||||
if (severity == 'INFO') {
|
||||
|
||||
function showMessage(message, severity, age=0) {
|
||||
if (severity == 'MESSAGING_INFO') {
|
||||
$('#message').css('background', '#6af');
|
||||
} else if (severity == 'WARNING') {
|
||||
} else if (severity == 'MESSAGING_WARNING') {
|
||||
$('#message').css('background', '#ff0');
|
||||
} else if (severity == 'MESSAGING_ERROR' ) {
|
||||
$('#message').css('background', '#f00');
|
||||
} else {
|
||||
$('#message').css('background', '#f00');
|
||||
}
|
||||
|
||||
$('#message').html(message);
|
||||
$("#content").fadeTo("slow", 0.3, function() {
|
||||
$("#message").show(500).delay(5000).hide(500, function() {
|
||||
@@ -815,3 +958,6 @@ function showMessage(message, severity) {
|
||||
function inRange(x, min, max) {
|
||||
return ((x-min)*(x-max) <= 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -7,14 +7,8 @@
|
||||
# please read the SDK documents if you need to do this.
|
||||
#
|
||||
COMPONENT_EMBED_FILES := style.css code.js index.html bootstrap.min.css.gz jquery.min.js.gz popper.min.js.gz bootstrap.min.js.gz
|
||||
|
||||
#CFLAGS += -D LOG_LOCAL_LEVEL=ESP_LOG_DEBUG
|
||||
CFLAGS += -D LOG_LOCAL_LEVEL=ESP_LOG_INFO \
|
||||
-I$(COMPONENT_PATH)/../tools
|
||||
COMPONENT_ADD_INCLUDEDIRS := .
|
||||
COMPONENT_ADD_INCLUDEDIRS += $(COMPONENT_PATH)/../tools
|
||||
COMPONENT_ADD_INCLUDEDIRS += $(COMPONENT_PATH)/../squeezelite-ota
|
||||
COMPONENT_EXTRA_INCLUDES += $(PROJECT_PATH)/main/
|
||||
|
||||
COMPONENT_EXTRA_INCLUDES += $(IDF_PATH)/components/esp_http_server/src $(IDF_PATH)/components/esp_http_server/src/port/esp32 $(IDF_PATH)/components/esp_http_server/src/util $(IDF_PATH)/components/esp_http_server/src/
|
||||
CFLAGS += -D LOG_LOCAL_LEVEL=ESP_LOG_INFO
|
||||
|
||||
|
||||
|
||||
@@ -73,11 +73,7 @@ void dns_server_stop(){
|
||||
}
|
||||
|
||||
|
||||
|
||||
void dns_server(void *pvParameters) {
|
||||
|
||||
|
||||
|
||||
struct sockaddr_in sa, ra;
|
||||
|
||||
/* Set redirection DNS hijack to the access point IP */
|
||||
|
||||
1127
components/wifi-manager/http_server_handlers.c
Normal file
1127
components/wifi-manager/http_server_handlers.c
Normal file
File diff suppressed because it is too large
Load Diff
148
components/wifi-manager/http_server_handlers.h
Normal file
148
components/wifi-manager/http_server_handlers.h
Normal file
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
Copyright (c) 2017-2019 Tony Pottier
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
@file http_server.h
|
||||
@author Tony Pottier
|
||||
@brief Defines all functions necessary for the HTTP server to run.
|
||||
|
||||
Contains the freeRTOS task for the HTTP listener and all necessary support
|
||||
function to process requests, decode URLs, serve files, etc. etc.
|
||||
|
||||
@note http_server task cannot run without the wifi_manager task!
|
||||
@see https://idyl.io
|
||||
@see https://github.com/tonyp7/esp32-wifi-manager
|
||||
*/
|
||||
|
||||
#ifndef HTTP_SERVER_H_INCLUDED
|
||||
#define HTTP_SERVER_H_INCLUDED
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include "esp_http_server.h"
|
||||
#include "wifi_manager.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/event_groups.h"
|
||||
#include "esp_wifi.h"
|
||||
#include "esp_event_loop.h"
|
||||
#include "nvs_flash.h"
|
||||
#include "esp_log.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "mdns.h"
|
||||
#include "lwip/api.h"
|
||||
#include "lwip/err.h"
|
||||
#include "lwip/netdb.h"
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/memp.h"
|
||||
#include "lwip/ip.h"
|
||||
#include "lwip/raw.h"
|
||||
#include "lwip/udp.h"
|
||||
#include "lwip/priv/api_msg.h"
|
||||
#include "lwip/priv/tcp_priv.h"
|
||||
#include "lwip/priv/tcpip_priv.h"
|
||||
#include "esp_vfs.h"
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define ESP_LOGE_LOC(t,str, ...) ESP_LOGE(t, "%s(%d): " str, __FUNCTION__, __LINE__, ##__VA_ARGS__)
|
||||
#define ESP_LOGI_LOC(t,str, ...) ESP_LOGI(t, "%s(%d): " str, __FUNCTION__, __LINE__, ##__VA_ARGS__)
|
||||
#define ESP_LOGD_LOC(t,str, ...) ESP_LOGD(t, "%s(%d): " str, __FUNCTION__, __LINE__, ##__VA_ARGS__)
|
||||
#define ESP_LOGW_LOC(t,str, ...) ESP_LOGW(t, "%s(%d): " str, __FUNCTION__, __LINE__, ##__VA_ARGS__)
|
||||
#define ESP_LOGV_LOC(t,str, ...) ESP_LOGV(t, "%s(%d): " str, __FUNCTION__, __LINE__, ##__VA_ARGS__)
|
||||
|
||||
|
||||
esp_err_t root_get_handler(httpd_req_t *req);
|
||||
esp_err_t resource_filehandler(httpd_req_t *req);
|
||||
esp_err_t resource_filehandler(httpd_req_t *req);
|
||||
esp_err_t resource_filehandler(httpd_req_t *req);
|
||||
esp_err_t resource_filehandler(httpd_req_t *req);
|
||||
esp_err_t resource_filehandler(httpd_req_t *req);
|
||||
esp_err_t resource_filehandler(httpd_req_t *req);
|
||||
esp_err_t ap_get_handler(httpd_req_t *req);
|
||||
esp_err_t config_get_handler(httpd_req_t *req);
|
||||
esp_err_t config_post_handler(httpd_req_t *req);
|
||||
esp_err_t connect_post_handler(httpd_req_t *req);
|
||||
esp_err_t connect_delete_handler(httpd_req_t *req);
|
||||
esp_err_t reboot_ota_post_handler(httpd_req_t *req);
|
||||
esp_err_t reboot_post_handler(httpd_req_t *req);
|
||||
esp_err_t recovery_post_handler(httpd_req_t *req);
|
||||
#if RECOVERY_APPLICATION
|
||||
esp_err_t flash_post_handler(httpd_req_t *req);
|
||||
#endif
|
||||
esp_err_t status_get_handler(httpd_req_t *req);
|
||||
esp_err_t messages_get_handler(httpd_req_t *req);
|
||||
|
||||
esp_err_t ap_scan_handler(httpd_req_t *req);
|
||||
esp_err_t redirect_ev_handler(httpd_req_t *req);
|
||||
esp_err_t redirect_200_ev_handler(httpd_req_t *req);
|
||||
|
||||
|
||||
esp_err_t err_handler(httpd_req_t *req, httpd_err_code_t error);
|
||||
#define SCRATCH_BUFSIZE (10240)
|
||||
#define FILE_PATH_MAX (ESP_VFS_PATH_MAX + 128)
|
||||
|
||||
typedef struct rest_server_context {
|
||||
char base_path[ESP_VFS_PATH_MAX + 1];
|
||||
char scratch[SCRATCH_BUFSIZE];
|
||||
} rest_server_context_t;
|
||||
/**
|
||||
* @brief RTOS task for the HTTP server. Do not start manually.
|
||||
* @see void http_server_start()
|
||||
*/
|
||||
void CODE_RAM_LOCATION http_server(void *pvParameters);
|
||||
|
||||
/* @brief helper function that processes one HTTP request at a time */
|
||||
void CODE_RAM_LOCATION http_server_netconn_serve(struct netconn *conn);
|
||||
|
||||
/* @brief create the task for the http server */
|
||||
esp_err_t CODE_RAM_LOCATION http_server_start();
|
||||
|
||||
/**
|
||||
* @brief gets a char* pointer to the first occurence of header_name withing the complete http request request.
|
||||
*
|
||||
* For optimization purposes, no local copy is made. memcpy can then be used in coordination with len to extract the
|
||||
* data.
|
||||
*
|
||||
* @param request the full HTTP raw request.
|
||||
* @param header_name the header that is being searched.
|
||||
* @param len the size of the header value if found.
|
||||
* @return pointer to the beginning of the header value.
|
||||
*/
|
||||
char* CODE_RAM_LOCATION http_server_get_header(char *request, char *header_name, int *len);
|
||||
|
||||
void CODE_RAM_LOCATION strreplace(char *src, char *str, char *rep);
|
||||
/* @brief lock the json config object */
|
||||
bool http_server_lock_json_object(TickType_t xTicksToWait);
|
||||
/* @brief unlock the json config object */
|
||||
void http_server_unlock_json_object();
|
||||
#define PROTECTED_JSON_CALL(a) if(http_server_lock_json_object( portMAX_DELAY )){ \ a; http_server_unlocklock_json_object(); } else{ ESP_LOGE(TAG, "could not get access to json mutex in wifi_scan"); }
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -4,19 +4,12 @@
|
||||
<meta charset="utf-8"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||
<link rel="stylesheet" href="/bootstrap.css">
|
||||
<link rel="stylesheet" href="res/test/bootstrap.min.css"> <!-- TODO delete -->
|
||||
<link rel="stylesheet" href="/style.css">
|
||||
<script src="/jquery.js"></script>
|
||||
<script src="/popper.js"></script>
|
||||
<script src="/bootstrap.js"></script>
|
||||
|
||||
<script src="res/test/jquery.min.js"></script> <!-- TODO delete -->
|
||||
<script src="res/test/popper.min.js"></script> <!-- TODO delete -->
|
||||
<script src="res/test/bootstrap.min.js"></script> <!-- TODO delete -->
|
||||
|
||||
<script src="/code.js"></script>
|
||||
|
||||
<link rel="stylesheet" href="/res/bootstrap.css">
|
||||
<link rel="stylesheet" href="/res/style.css">
|
||||
<script src="/res/jquery.js"></script>
|
||||
<script src="/res/popper.js"></script>
|
||||
<script src="/res/bootstrap.js"></script>
|
||||
<script src="/res/code.js"></script>
|
||||
|
||||
<title>esp32-wifi-manager</title>
|
||||
</head>
|
||||
@@ -74,7 +67,7 @@
|
||||
<a class="nav-link" data-toggle="tab" href="#tab-firmware">Firmware</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" data-toggle="tab" href="#tab-gpio">GPIO</a>
|
||||
<a class="nav-link" data-toggle="tab" href="#tab-syslog">Syslog</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" data-toggle="tab" href="#tab-nvs">NVS editor</a>
|
||||
@@ -197,7 +190,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- wifi -->
|
||||
|
||||
<div class="tab-pane fade" id="tab-audio">
|
||||
<div id="audioout">
|
||||
@@ -247,72 +240,7 @@
|
||||
<label class="custom-control-label" for="autoexec-cb"></label>
|
||||
</div>
|
||||
<br />
|
||||
</div>
|
||||
|
||||
<div class="tab-pane fade" id="tab-gpio">
|
||||
<table class="table table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">Signal</th>
|
||||
<th scope="col">I2S pin</th>
|
||||
<th scope="col">SPDIF pin</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="gpioTable">
|
||||
<tr>
|
||||
<td>Bit clock</td>
|
||||
<td>
|
||||
<input type="text" class="form-control gpio" id="gpio-i2s-bc" maxlength="2" size="2">
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" class="form-control gpio" id="gpio-spdif-bc" maxlength="2" size="2">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Word select</td>
|
||||
<td>
|
||||
<input type="text" class="form-control gpio" id="gpio-i2s-ws" maxlength="2" size="2">
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" class="form-control gpio" id="gpio-spdif-ws" maxlength="2" size="2">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Data</td>
|
||||
<td>
|
||||
<input type="text" class="form-control gpio" id="gpio-i2s-data" maxlength="2" size="2">
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" class="form-control gpio" id="gpio-spdif-data" maxlength="2" size="2">
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="buttons">
|
||||
<input id="save-gpio" type="button" class="btn btn-success" value="Save" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="tab-pane fade" id="tab-nvs">
|
||||
<table class="table table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">Key</th>
|
||||
<th scope="col">Value</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="nvsTable">
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="buttons">
|
||||
<div id="boot-div">
|
||||
<form id="reboot-form" action="/reboot.json" method="post" target="dummyframe">
|
||||
<button id="reboot-button" type="submit" class="btn btn-primary">Reboot</button>
|
||||
</form>
|
||||
</div>
|
||||
<input id="save-nvs" type="button" class="btn btn-success" value="Save" />
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- audio -->
|
||||
|
||||
<div class="tab-pane fade" id="tab-firmware">
|
||||
<div id="boot-div">
|
||||
@@ -343,21 +271,17 @@
|
||||
</table>
|
||||
<h2>Firmware URL:</h2>
|
||||
<textarea id="fwurl" maxlength="350"></textarea>
|
||||
<!--
|
||||
<br />OR<br />
|
||||
<div class="input-group mb-3" id="upload">
|
||||
<div class="custom-file">
|
||||
<input type="file" class="custom-file-input" id="inputGroupFile01">
|
||||
<label class="custom-file-label" for="inputGroupFile01"></label>
|
||||
</div>
|
||||
<div class="input-group-append">
|
||||
<span class="input-group-text" id="fwUpload">Upload</span>
|
||||
</div>
|
||||
</div>
|
||||
-->
|
||||
<div class="buttons">
|
||||
<input type="button" id="flash" class="btn btn-danger" value="Flash!" /><span id="flash-status"></span>
|
||||
</div>
|
||||
<p>OR</p>
|
||||
<div class="form-group">
|
||||
<input type="file" class="form-control-file" id="flashfilename" aria-describedby="fileHelp">
|
||||
<div class="buttons">
|
||||
<button type="button" class="btn btn-danger" id="fwUpload">Upload!</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="otadiv">
|
||||
<div class="progress" id="progress">
|
||||
<div class="progress-bar" role="progressbar" aria-valuemin="0" aria-valuemax="100" style="width:0%">
|
||||
@@ -365,11 +289,48 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- firmware -->
|
||||
|
||||
<div class="tab-pane fade" id="tab-syslog">
|
||||
<table class="table table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">Timestamp</th>
|
||||
<th scope="col">Message</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="syslogTable">
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="buttons">
|
||||
<input id="clear-syslog" type="button" class="btn btn-danger btn-sm" value="Clear" />
|
||||
</div>
|
||||
</div> <!-- syslog -->
|
||||
|
||||
<div class="tab-pane fade" id="tab-nvs">
|
||||
<table class="table table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">Key</th>
|
||||
<th scope="col">Value</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="nvsTable">
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="buttons">
|
||||
<div id="boot-div">
|
||||
<form id="reboot-form" action="/reboot.json" method="post" target="dummyframe">
|
||||
<button id="reboot-button" type="submit" class="btn btn-primary">Reboot</button>
|
||||
</form>
|
||||
</div>
|
||||
<input id="save-nvs" type="button" class="btn btn-success" value="Save" />
|
||||
</div>
|
||||
</div> <!-- nvs -->
|
||||
|
||||
<div class="tab-pane fade" id="tab-credits">
|
||||
<div class="jumbotron">
|
||||
<p><strong><a href="https://github.com/sle118/squeezelite-esp32">squeezelite-esp32</a></strong>, © 2019, philippe44, sle118, daduke<br />Licensed under the GPL</p>
|
||||
<p><strong><a href="https://github.com/sle118/squeezelite-esp32">squeezelite-esp32</a></strong>, © 2020, philippe44, sle118, daduke<br />Licensed under the GPL</p>
|
||||
<p>
|
||||
This app would not be possible without the following libraries:
|
||||
</p>
|
||||
@@ -388,7 +349,7 @@
|
||||
<input type="checkbox" class="custom-control-input" id="show-nvs" checked="checked">
|
||||
<label class="custom-control-label" for="show-nvs"></label>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- credits -->
|
||||
</div>
|
||||
<footer class="footer"><span id="foot-fw"></span><span id="foot-wifi"></span></footer>
|
||||
<iframe width="0" height="0" border="0" name="dummyframe" id="dummyframe"></iframe>
|
||||
|
||||
@@ -212,12 +212,6 @@ input[type='text'], input[type='password'], textarea {
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
input.gpio {
|
||||
width: 2em;
|
||||
color: #000;
|
||||
height: 1.8em;
|
||||
}
|
||||
|
||||
.custom-switch {
|
||||
margin-left: 8px;
|
||||
}
|
||||
@@ -273,6 +267,18 @@ textarea#autoexec1, textarea#fwurl, div#upload {
|
||||
width: 80%;
|
||||
}
|
||||
|
||||
table tr.MESSAGING_INFO {
|
||||
background: #123;
|
||||
}
|
||||
|
||||
table tr.MESSAGING_WARNING {
|
||||
background: #330;
|
||||
}
|
||||
|
||||
table tr.MESSAGING_ERROR {
|
||||
background: #300;
|
||||
}
|
||||
|
||||
input, textarea {
|
||||
border-radius: 3px;
|
||||
border: 1px solid transparent;
|
||||
|
||||
@@ -37,7 +37,6 @@ Contains the freeRTOS task and all necessary support
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "dns_server.h"
|
||||
#include "http_server.h"
|
||||
#include "esp_system.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
@@ -61,6 +60,9 @@ Contains the freeRTOS task and all necessary support
|
||||
#include "platform_config.h"
|
||||
#include "trace.h"
|
||||
#include "cmd_system.h"
|
||||
#include "messaging.h"
|
||||
|
||||
#include "http_server_handlers.h"
|
||||
#include "monitor.h"
|
||||
#include "globdefs.h"
|
||||
|
||||
@@ -69,7 +71,7 @@ Contains the freeRTOS task and all necessary support
|
||||
#endif
|
||||
|
||||
#define STR_OR_BLANK(p) p==NULL?"":p
|
||||
#define FREE_AND_NULL(p) if(p!=NULL){ free(p); p=NULL;}
|
||||
|
||||
/* objects used to manipulate the main queue of events */
|
||||
QueueHandle_t wifi_manager_queue;
|
||||
SemaphoreHandle_t wifi_manager_json_mutex = NULL;
|
||||
@@ -83,7 +85,7 @@ char *ip_info_json = NULL;
|
||||
char * release_url=NULL;
|
||||
cJSON * ip_info_cjson=NULL;
|
||||
wifi_config_t* wifi_manager_config_sta = NULL;
|
||||
static update_reason_code_t last_update_reason_code=0;
|
||||
|
||||
|
||||
static int32_t total_connected_time=0;
|
||||
static int64_t last_connected=0;
|
||||
@@ -202,9 +204,6 @@ bool isGroupBitSet(uint8_t bit){
|
||||
EventBits_t uxBits= xEventGroupGetBits(wifi_manager_event_group);
|
||||
return (uxBits & bit);
|
||||
}
|
||||
void wifi_manager_refresh_ota_json(){
|
||||
wifi_manager_send_message(EVENT_REFRESH_OTA, NULL);
|
||||
}
|
||||
|
||||
void wifi_manager_scan_async(){
|
||||
wifi_manager_send_message(ORDER_START_WIFI_SCAN, NULL);
|
||||
@@ -357,6 +356,7 @@ esp_err_t wifi_manager_save_sta_config(){
|
||||
esp_err = nvs_commit(handle);
|
||||
if (esp_err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Unable to commit changes. Error %s", esp_err_to_name(esp_err));
|
||||
messaging_post_message(MESSAGING_ERROR,MESSAGING_CLASS_SYSTEM,"Unable to save wifi credentials. %s",esp_err_to_name(esp_err));
|
||||
return esp_err;
|
||||
}
|
||||
nvs_close(handle);
|
||||
@@ -449,8 +449,6 @@ cJSON * wifi_manager_get_basic_info(cJSON **old){
|
||||
cJSON_AddItemToObject(root, "version", cJSON_CreateString(desc->version));
|
||||
if(release_url !=NULL) cJSON_AddItemToObject(root, "release_url", cJSON_CreateString(release_url));
|
||||
cJSON_AddNumberToObject(root,"recovery", is_recovery_running?1:0);
|
||||
cJSON_AddItemToObject(root, "ota_dsc", cJSON_CreateString(ota_get_status()));
|
||||
cJSON_AddNumberToObject(root,"ota_pct", ota_get_pct_complete() );
|
||||
cJSON_AddItemToObject(root, "Jack", cJSON_CreateString(jack_inserted_svc() ? "1" : "0"));
|
||||
cJSON_AddNumberToObject(root,"Voltage", battery_value_svc());
|
||||
cJSON_AddNumberToObject(root,"disconnect_count", num_disconnect );
|
||||
@@ -479,12 +477,6 @@ void wifi_manager_generate_ip_info_json(update_reason_code_t update_reason_code)
|
||||
wifi_config_t *config = wifi_manager_get_wifi_sta_config();
|
||||
ip_info_cjson = wifi_manager_get_basic_info(&ip_info_cjson);
|
||||
|
||||
if(update_reason_code == UPDATE_OTA) {
|
||||
update_reason_code = last_update_reason_code;
|
||||
}
|
||||
else {
|
||||
last_update_reason_code = update_reason_code;
|
||||
}
|
||||
cJSON_AddNumberToObject(ip_info_cjson, "urc", update_reason_code);
|
||||
if(config){
|
||||
cJSON_AddItemToObject(ip_info_cjson, "ssid", cJSON_CreateString((char *)config->sta.ssid));
|
||||
@@ -505,7 +497,7 @@ char * get_mac_string(uint8_t mac[6]){
|
||||
|
||||
char * macStr=malloc(LOCAL_MAC_SIZE);
|
||||
memset(macStr, 0x00, LOCAL_MAC_SIZE);
|
||||
snprintf(macStr, LOCAL_MAC_SIZE-1,MACSTR, MAC2STR(mac));
|
||||
snprintf(macStr, LOCAL_MAC_SIZE,MACSTR, MAC2STR(mac));
|
||||
return macStr;
|
||||
|
||||
}
|
||||
@@ -855,20 +847,6 @@ void wifi_manager_connect_async(){
|
||||
wifi_manager_send_message(ORDER_CONNECT_STA, (void*)CONNECTION_REQUEST_USER);
|
||||
}
|
||||
|
||||
void set_status_message(message_severity_t severity, const char * message){
|
||||
if(ip_info_cjson==NULL){
|
||||
ip_info_cjson = wifi_manager_get_new_json(&ip_info_cjson);
|
||||
}
|
||||
if(ip_info_cjson==NULL){
|
||||
ESP_LOGE(TAG, "Error setting status message. Unable to allocate cJSON.");
|
||||
return;
|
||||
}
|
||||
cJSON * item=cJSON_GetObjectItem(ip_info_cjson, "message");
|
||||
item = wifi_manager_get_new_json(&item);
|
||||
cJSON_AddItemToObject(item, "severity", cJSON_CreateString(severity==INFO?"INFO":severity==WARNING?"WARNING":severity==ERROR?"ERROR":"" ));
|
||||
cJSON_AddItemToObject(item, "text", cJSON_CreateString(message));
|
||||
}
|
||||
|
||||
|
||||
char* wifi_manager_alloc_get_ip_info_json(){
|
||||
return cJSON_PrintUnformatted(ip_info_cjson);
|
||||
@@ -1138,12 +1116,6 @@ void wifi_manager( void * pvParameters ){
|
||||
ESP_LOGD(TAG, "Done Invoking SCAN DONE callback");
|
||||
}
|
||||
break;
|
||||
case EVENT_REFRESH_OTA:
|
||||
if(wifi_manager_lock_json_buffer( portMAX_DELAY )){
|
||||
wifi_manager_generate_ip_info_json( UPDATE_OTA );
|
||||
wifi_manager_unlock_json_buffer();
|
||||
}
|
||||
break;
|
||||
|
||||
case ORDER_START_WIFI_SCAN:
|
||||
ESP_LOGD(TAG, "MESSAGE: ORDER_START_WIFI_SCAN");
|
||||
@@ -1153,6 +1125,7 @@ void wifi_manager( void * pvParameters ){
|
||||
if(esp_wifi_scan_start(&scan_config, false)!=ESP_OK){
|
||||
ESP_LOGW(TAG, "Unable to start scan; wifi is trying to connect");
|
||||
// set_status_message(WARNING, "Wifi Connecting. Cannot start scan.");
|
||||
messaging_post_message(MESSAGING_WARNING,MESSAGING_CLASS_SYSTEM,"Wifi connecting. Cannot start scan.");
|
||||
}
|
||||
else {
|
||||
xEventGroupSetBits(wifi_manager_event_group, WIFI_MANAGER_SCAN_BIT);
|
||||
@@ -1358,6 +1331,8 @@ void wifi_manager( void * pvParameters ){
|
||||
else{
|
||||
/* lost connection ? */
|
||||
ESP_LOGE(TAG, "WiFi Connection lost.");
|
||||
messaging_post_message(MESSAGING_WARNING,MESSAGING_CLASS_SYSTEM,"WiFi Connection lost");
|
||||
|
||||
if(wifi_manager_lock_json_buffer( portMAX_DELAY )){
|
||||
wifi_manager_generate_ip_info_json( UPDATE_LOST_CONNECTION );
|
||||
wifi_manager_unlock_json_buffer();
|
||||
@@ -1439,7 +1414,7 @@ void wifi_manager( void * pvParameters ){
|
||||
if(cb_ptr_arr[msg.code]) (*cb_ptr_arr[msg.code])(NULL);
|
||||
break;
|
||||
case UPDATE_CONNECTION_OK:
|
||||
/* refresh JSON with the new ota data */
|
||||
/* refresh JSON */
|
||||
if(wifi_manager_lock_json_buffer( portMAX_DELAY )){
|
||||
/* generate the connection info with success */
|
||||
wifi_manager_generate_ip_info_json( UPDATE_CONNECTION_OK );
|
||||
|
||||
@@ -42,6 +42,17 @@ extern "C" {
|
||||
#include "squeezelite-ota.h"
|
||||
#include "cJSON.h"
|
||||
|
||||
#ifndef RECOVERY_APPLICATION
|
||||
#error "RECOVERY_APPLICATION not defined. Defaulting to squeezelite"
|
||||
#endif
|
||||
|
||||
#if RECOVERY_APPLICATION==1
|
||||
#elif RECOVERY_APPLICATION==0
|
||||
#else
|
||||
#error "unknown configuration"
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Defines the maximum size of a SSID name. 32 is IEEE standard.
|
||||
@@ -187,12 +198,11 @@ typedef enum message_code_t {
|
||||
EVENT_STA_DISCONNECTED = 12,
|
||||
EVENT_SCAN_DONE = 13,
|
||||
EVENT_STA_GOT_IP = 14,
|
||||
EVENT_REFRESH_OTA = 15,
|
||||
ORDER_RESTART_OTA = 16,
|
||||
ORDER_RESTART_RECOVERY = 17,
|
||||
ORDER_RESTART_OTA_URL = 18,
|
||||
ORDER_RESTART = 19,
|
||||
MESSAGE_CODE_COUNT = 20 /* important for the callback array */
|
||||
ORDER_RESTART_OTA = 15,
|
||||
ORDER_RESTART_RECOVERY = 16,
|
||||
ORDER_RESTART_OTA_URL = 17,
|
||||
ORDER_RESTART = 18,
|
||||
MESSAGE_CODE_COUNT = 19 /* important for the callback array */
|
||||
|
||||
}message_code_t;
|
||||
|
||||
@@ -215,8 +225,7 @@ typedef enum update_reason_code_t {
|
||||
UPDATE_CONNECTION_OK = 0,
|
||||
UPDATE_FAILED_ATTEMPT = 1,
|
||||
UPDATE_USER_DISCONNECT = 2,
|
||||
UPDATE_LOST_CONNECTION = 3,
|
||||
UPDATE_OTA=4
|
||||
UPDATE_LOST_CONNECTION = 3
|
||||
}update_reason_code_t;
|
||||
|
||||
typedef enum connection_request_made_by_code_t{
|
||||
|
||||
165
components/wifi-manager/wifi_manager_http_server.c
Normal file
165
components/wifi-manager/wifi_manager_http_server.c
Normal file
@@ -0,0 +1,165 @@
|
||||
/*
|
||||
* Squeezelite for esp32
|
||||
*
|
||||
* (c) Sebastien 2019
|
||||
* Philippe G. 2019, philippe_44@outlook.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "http_server_handlers.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_http_server.h"
|
||||
#include "_esp_http_server.h"
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "esp_system.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "config.h"
|
||||
#include "messaging.h"
|
||||
static const char TAG[] = "http_server";
|
||||
|
||||
static httpd_handle_t _server = NULL;
|
||||
rest_server_context_t *rest_context = NULL;
|
||||
RingbufHandle_t messaging=NULL;
|
||||
|
||||
void register_common_handlers(httpd_handle_t server){
|
||||
httpd_uri_t res_get = { .uri = "/res/*", .method = HTTP_GET, .handler = resource_filehandler, .user_ctx = rest_context };
|
||||
httpd_register_uri_handler(server, &res_get);
|
||||
|
||||
}
|
||||
void register_regular_handlers(httpd_handle_t server){
|
||||
httpd_uri_t root_get = { .uri = "/", .method = HTTP_GET, .handler = root_get_handler, .user_ctx = rest_context };
|
||||
httpd_register_uri_handler(server, &root_get);
|
||||
|
||||
httpd_uri_t ap_get = { .uri = "/ap.json", .method = HTTP_GET, .handler = ap_get_handler, .user_ctx = rest_context };
|
||||
httpd_register_uri_handler(server, &ap_get);
|
||||
httpd_uri_t scan_get = { .uri = "/scan.json", .method = HTTP_GET, .handler = ap_scan_handler, .user_ctx = rest_context };
|
||||
httpd_register_uri_handler(server, &scan_get);
|
||||
httpd_uri_t config_get = { .uri = "/config.json", .method = HTTP_GET, .handler = config_get_handler, .user_ctx = rest_context };
|
||||
httpd_register_uri_handler(server, &config_get);
|
||||
httpd_uri_t status_get = { .uri = "/status.json", .method = HTTP_GET, .handler = status_get_handler, .user_ctx = rest_context };
|
||||
httpd_register_uri_handler(server, &status_get);
|
||||
httpd_uri_t messages_get = { .uri = "/messages.json", .method = HTTP_GET, .handler = messages_get_handler, .user_ctx = rest_context };
|
||||
httpd_register_uri_handler(server, &messages_get);
|
||||
|
||||
httpd_uri_t config_post = { .uri = "/config.json", .method = HTTP_POST, .handler = config_post_handler, .user_ctx = rest_context };
|
||||
httpd_register_uri_handler(server, &config_post);
|
||||
httpd_uri_t connect_post = { .uri = "/connect.json", .method = HTTP_POST, .handler = connect_post_handler, .user_ctx = rest_context };
|
||||
httpd_register_uri_handler(server, &connect_post);
|
||||
|
||||
httpd_uri_t reboot_ota_post = { .uri = "/reboot_ota.json", .method = HTTP_POST, .handler = reboot_ota_post_handler, .user_ctx = rest_context };
|
||||
httpd_register_uri_handler(server, &reboot_ota_post);
|
||||
|
||||
httpd_uri_t reboot_post = { .uri = "/reboot.json", .method = HTTP_POST, .handler = reboot_post_handler, .user_ctx = rest_context };
|
||||
httpd_register_uri_handler(server, &reboot_post);
|
||||
|
||||
httpd_uri_t recovery_post = { .uri = "/recovery.json", .method = HTTP_POST, .handler = recovery_post_handler, .user_ctx = rest_context };
|
||||
httpd_register_uri_handler(server, &recovery_post);
|
||||
|
||||
httpd_uri_t connect_delete = { .uri = "/connect.json", .method = HTTP_DELETE, .handler = connect_delete_handler, .user_ctx = rest_context };
|
||||
httpd_register_uri_handler(server, &connect_delete);
|
||||
|
||||
#if RECOVERY_APPLICATION
|
||||
|
||||
httpd_uri_t flash_post = { .uri = "/flash.json", .method = HTTP_POST, .handler = flash_post_handler, .user_ctx = rest_context };
|
||||
httpd_register_uri_handler(server, &flash_post);
|
||||
#endif
|
||||
|
||||
|
||||
// from https://github.com/tripflex/wifi-captive-portal/blob/master/src/mgos_wifi_captive_portal.c
|
||||
// https://unix.stackexchange.com/questions/432190/why-isnt-androids-captive-portal-detection-triggering-a-browser-window
|
||||
// Known HTTP GET requests to check for Captive Portal
|
||||
|
||||
///kindle-wifi/wifiredirect.html Kindle when requested with com.android.captiveportallogin
|
||||
///kindle-wifi/wifistub.html Kindle before requesting with captive portal login window (maybe for detection?)
|
||||
|
||||
|
||||
httpd_uri_t connect_redirect_1 = { .uri = "/mobile/status.php", .method = HTTP_GET, .handler = redirect_200_ev_handler, .user_ctx = rest_context };// Android 8.0 (Samsung s9+)
|
||||
httpd_register_uri_handler(server, &connect_redirect_1);
|
||||
httpd_uri_t connect_redirect_2 = { .uri = "/generate_204", .method = HTTP_GET, .handler = redirect_200_ev_handler, .user_ctx = rest_context };// Android
|
||||
httpd_register_uri_handler(server, &connect_redirect_2);
|
||||
httpd_uri_t connect_redirect_3 = { .uri = "/gen_204", .method = HTTP_GET, .handler = redirect_ev_handler, .user_ctx = rest_context };// Android 9.0
|
||||
httpd_register_uri_handler(server, &connect_redirect_3);
|
||||
// httpd_uri_t connect_redirect_4 = { .uri = "/ncsi.txt", .method = HTTP_GET, .handler = redirect_ev_handler, .user_ctx = rest_context };// Windows
|
||||
// httpd_register_uri_handler(server, &connect_redirect_4);
|
||||
httpd_uri_t connect_redirect_5 = { .uri = "/hotspot-detect.html", .method = HTTP_GET, .handler = redirect_ev_handler, .user_ctx = rest_context }; // iOS 8/9
|
||||
httpd_register_uri_handler(server, &connect_redirect_5);
|
||||
httpd_uri_t connect_redirect_6 = { .uri = "/library/test/success.html", .method = HTTP_GET, .handler = redirect_ev_handler, .user_ctx = rest_context };// iOS 8/9
|
||||
httpd_register_uri_handler(server, &connect_redirect_6);
|
||||
httpd_uri_t connect_redirect_7 = { .uri = "/hotspotdetect.html", .method = HTTP_GET, .handler = redirect_ev_handler, .user_ctx = rest_context }; // iOS
|
||||
httpd_register_uri_handler(server, &connect_redirect_7);
|
||||
httpd_uri_t connect_redirect_8 = { .uri = "/success.txt", .method = HTTP_GET, .handler = redirect_ev_handler, .user_ctx = rest_context }; // OSX
|
||||
httpd_register_uri_handler(server, &connect_redirect_8);
|
||||
|
||||
|
||||
|
||||
ESP_LOGD(TAG,"Registering default error handler for 404");
|
||||
httpd_register_err_handler(server, HTTPD_404_NOT_FOUND,&err_handler);
|
||||
|
||||
}
|
||||
|
||||
|
||||
esp_err_t http_server_start()
|
||||
{
|
||||
ESP_LOGI(TAG, "Initializing HTTP Server");
|
||||
messaging = messaging_register_subscriber(10, "http_server");
|
||||
rest_context = calloc(1, sizeof(rest_server_context_t));
|
||||
if(rest_context==NULL){
|
||||
ESP_LOGE(TAG,"No memory for http context");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
strlcpy(rest_context->base_path, "/res/", sizeof(rest_context->base_path));
|
||||
|
||||
httpd_config_t config = HTTPD_DEFAULT_CONFIG();
|
||||
config.max_uri_handlers = 25;
|
||||
config.max_open_sockets = 5;
|
||||
config.uri_match_fn = httpd_uri_match_wildcard;
|
||||
//todo: use the endpoint below to configure session token?
|
||||
// config.open_fn
|
||||
|
||||
ESP_LOGI(TAG, "Starting HTTP Server");
|
||||
esp_err_t err= __httpd_start(&_server, &config);
|
||||
if(err != ESP_OK){
|
||||
ESP_LOGE_LOC(TAG,"Start server failed");
|
||||
}
|
||||
else {
|
||||
|
||||
register_common_handlers(_server);
|
||||
register_regular_handlers(_server);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
/* Function to free context */
|
||||
void adder_free_func(void *ctx)
|
||||
{
|
||||
ESP_LOGI(TAG, "/adder Free Context function called");
|
||||
free(ctx);
|
||||
}
|
||||
|
||||
|
||||
void stop_webserver(httpd_handle_t server)
|
||||
{
|
||||
// Stop the httpd server
|
||||
httpd_stop(server);
|
||||
}
|
||||
|
||||
|
||||
|
||||
113
eclipse_make_wrapper.py
Normal file
113
eclipse_make_wrapper.py
Normal file
@@ -0,0 +1,113 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Wrapper to run make and preprocess any paths in the output from MSYS Unix-style paths
|
||||
# to Windows paths, for Eclipse
|
||||
from __future__ import print_function, division
|
||||
import sys
|
||||
import subprocess
|
||||
import os.path
|
||||
import os
|
||||
import re
|
||||
import glob
|
||||
from test import test_cmd_line
|
||||
|
||||
#UNIX_PATH_RE = re.compile(r'(([a-zA-Z]{1}[:]{1}){0,1}[/\\][^\s\'\"\t\[\(]+)+')
|
||||
UNIX_PATH_RE = re.compile(r'(([a-zA-Z]{1}[:]{1}){0,1}[/\\][^\s\'\"\t\[\(]+(?![^\\/\n]*$)[/\\]?)')
|
||||
INCLUDE_PATH_RE = re.compile(r'-I[\s"]{0,}(.+?)["]{0,}(?=\s-\S)')
|
||||
INCLUDE_PATH_ADJ_RE = re.compile(r'^([/]opt[/]esp-idf[/]){1}(.*)')
|
||||
INCLUDE_PATH_ADJ2_RE = re.compile(r'^([/]c[/]){1}(.*)')
|
||||
|
||||
paths = {}
|
||||
names = []
|
||||
idf_path= os.environ.get('IDF_PATH').replace("/", "\\")
|
||||
cwd_path= os.environ.get('CWD')
|
||||
pwd_path= os.environ.get('PWD')
|
||||
|
||||
def check_path(path):
|
||||
try:
|
||||
return paths[path]
|
||||
except KeyError:
|
||||
pass
|
||||
paths[path] = path
|
||||
winpath =path
|
||||
|
||||
if not os.path.exists(winpath):
|
||||
# cache as failed, replace with success if it works
|
||||
if re.match(INCLUDE_PATH_ADJ2_RE, path) is not None:
|
||||
winpath = INCLUDE_PATH_ADJ2_RE.sub(r'c:/\2',path) #replace /c/
|
||||
try:
|
||||
winpath = subprocess.check_output(["cygpath", "-w", winpath]).strip()
|
||||
except subprocess.CalledProcessError:
|
||||
return path # something went wrong running cygpath, assume this is not a path!
|
||||
if not os.path.exists(winpath):
|
||||
if not os.path.exists(winpath):
|
||||
winpath=idf_path + '\\' + re.sub(r'^[/\\]opt[/\\](esp-idf[/\\]){0,}', '', path, 1)
|
||||
try:
|
||||
winpath = subprocess.check_output(["cygpath", "-w", winpath]).strip()
|
||||
except subprocess.CalledProcessError:
|
||||
return path # something went wrong running cygpath, assume this is not a path!
|
||||
if not os.path.exists(winpath):
|
||||
return path # not actually a valid path
|
||||
|
||||
winpath = winpath.replace("/", "\\") # make consistent with forward-slashes used elsewhere
|
||||
paths[path] = winpath
|
||||
|
||||
|
||||
#print("In path: {0}, out path: {1}".format(path,winpath) )
|
||||
return winpath
|
||||
def fix_paths(filename):
|
||||
if re.match(r'.*[\\](.*$)',filename) is not None:
|
||||
filename = re.findall(r'.*[\\](.*$)',filename)[0].replace("\\", "/")
|
||||
|
||||
return filename.rstrip()
|
||||
|
||||
def print_paths(path_list, file_name, source_file):
|
||||
|
||||
new_path_list = list(set(path_list))
|
||||
new_path_list.sort()
|
||||
last_n = ''
|
||||
cmd_line='xtensa-esp32-elf-gcc '
|
||||
for n in new_path_list:
|
||||
if re.match(INCLUDE_PATH_ADJ_RE, n) is not None:
|
||||
n = INCLUDE_PATH_ADJ_RE.sub(idf_path+r"\2",n )
|
||||
if re.match(INCLUDE_PATH_ADJ2_RE, n) is not None:
|
||||
n = INCLUDE_PATH_ADJ2_RE.sub(r'c:/\2',n)
|
||||
if last_n != n:
|
||||
cmd_line = cmd_line + ' -I ' + n.rstrip()
|
||||
last_n = n
|
||||
if source_file:
|
||||
cmd_line = cmd_line + ' -c ' + fix_paths(source_file)
|
||||
cmd_line = cmd_line + ' -o ' + fix_paths(file_name)
|
||||
print(cmd_line)
|
||||
def extract_includes():
|
||||
|
||||
for filename in [y for x in os.walk('build') for y in glob.glob(os.path.join(x[0], '*.d'))]:
|
||||
lines = []
|
||||
source=''
|
||||
with open(filename) as file_in:
|
||||
for line in file_in:
|
||||
if re.match(r'\S*(?=/[^/]*\.[h][p]?)',line) is not None:
|
||||
lines.extend(re.findall(r'\S*(?=/[^/]*\.[h][p]?)/',line))
|
||||
if re.match(r'\S*(?=\.[cC][pP]{0,})[^\\\s]*',line) is not None:
|
||||
source = re.findall(r'\S*(?=\.[cC][pP]{0,})[^\\\s]*',line)[0]
|
||||
|
||||
print_paths(lines,filename,source )
|
||||
|
||||
def main():
|
||||
cwd_path=check_path(os.getcwd())
|
||||
os.environ['CWD']= cwd_path
|
||||
os.environ['PWD']= cwd_path
|
||||
idf_path= os.environ.get('IDF_PATH').replace("/", "\\")
|
||||
cwd_path= os.environ.get('CWD')
|
||||
pwd_path= os.environ.get('PWD')
|
||||
print('Running custom script make in {}, IDF_PATH={}, CWD={}, PWD={}'.format(cwd_path,idf_path,cwd_path,pwd_path))
|
||||
|
||||
make = subprocess.Popen(["make"] + sys.argv[1:] + ["BATCH_BUILD=1"], stdout=subprocess.PIPE)
|
||||
for line in iter(make.stdout.readline, ''):
|
||||
line = re.sub(UNIX_PATH_RE, lambda m: check_path(m.group(0)), line)
|
||||
names.extend(INCLUDE_PATH_RE.findall(line))
|
||||
print(line.rstrip())
|
||||
sys.exit(make.wait())
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -3,4 +3,3 @@ idf_component_register(SRC_DIRS .
|
||||
INCLUDE_DIRS .
|
||||
EMBED_FILES ../server_certs/github.pem
|
||||
)
|
||||
|
||||
@@ -6,10 +6,7 @@
|
||||
# lib(subdirectory_name).a in the build directory. This behaviour is entirely configurable,
|
||||
# please read the SDK documents if you need to do this.
|
||||
#
|
||||
#CFLAGS += -D LOG_LOCAL_LEVEL=ESP_LOG_DEBUG
|
||||
CFLAGS += -D LOG_LOCAL_LEVEL=ESP_LOG_INFO -DMODEL_NAME=SqueezeESP32
|
||||
COMPONENT_ADD_INCLUDEDIRS += $(COMPONENT_PATH)/../tools \
|
||||
$(COMPONENT_PATH)/../config
|
||||
COMPONENT_EXTRA_INCLUDES += $(PROJECT_PATH)/components/tools/
|
||||
LDFLAGS += -s
|
||||
COMPONENT_EMBED_TXTFILES := ${PROJECT_PATH}/server_certs/github.pem
|
||||
COMPONENT_ADD_INCLUDEDIRS := .
|
||||
@@ -18,7 +18,7 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#define LOG_LOCAL_LEVEL ESP_LOG_DEBUG
|
||||
|
||||
#include "platform_esp32.h"
|
||||
#include "led.h"
|
||||
#include <stdio.h>
|
||||
@@ -40,7 +40,6 @@
|
||||
#include "lwip/err.h"
|
||||
#include "lwip/netdb.h"
|
||||
#include "nvs_utilities.h"
|
||||
#include "http_server.h"
|
||||
#include "trace.h"
|
||||
#include "wifi_manager.h"
|
||||
#include "squeezelite-ota.h"
|
||||
@@ -48,11 +47,12 @@
|
||||
#include "platform_config.h"
|
||||
#include "audio_controls.h"
|
||||
#include "telnet.h"
|
||||
#include "messaging.h"
|
||||
|
||||
static const char certs_namespace[] = "certificates";
|
||||
static const char certs_key[] = "blob";
|
||||
static const char certs_version[] = "version";
|
||||
|
||||
const char unknown_string_placeholder[] = "unknown";
|
||||
EventGroupHandle_t wifi_event_group;
|
||||
|
||||
bool bypass_wifi_manager=false;
|
||||
@@ -70,7 +70,9 @@ extern const uint8_t server_cert_pem_end[] asm("_binary_github_pem_end");
|
||||
// as an exception _init function don't need include
|
||||
extern void services_init(void);
|
||||
extern void display_init(char *welcome);
|
||||
|
||||
bool is_recovery_running;
|
||||
const char * str_or_unknown(const char * str) { return (str?str:unknown_string_placeholder); }
|
||||
|
||||
/* brief this is an exemple of a callback that you can setup in your own app to get notified of wifi manager event */
|
||||
void cb_connection_got_ip(void *pvParameter){
|
||||
@@ -87,12 +89,14 @@ void cb_connection_got_ip(void *pvParameter){
|
||||
}
|
||||
ip.addr = ipInfo.ip.addr;
|
||||
ESP_LOGI(TAG, "I have a connection!");
|
||||
messaging_post_message(MESSAGING_INFO,MESSAGING_CLASS_SYSTEM,"Wifi connected");
|
||||
xEventGroupSetBits(wifi_event_group, CONNECTED_BIT);
|
||||
bWifiConnected=true;
|
||||
led_unpush(LED_GREEN);
|
||||
}
|
||||
void cb_connection_sta_disconnected(void *pvParameter){
|
||||
led_blink_pushed(LED_GREEN, 250, 250);
|
||||
messaging_post_message(MESSAGING_WARNING,MESSAGING_CLASS_SYSTEM,"Wifi disconnected");
|
||||
bWifiConnected=false;
|
||||
xEventGroupClearBits(wifi_event_group, CONNECTED_BIT);
|
||||
}
|
||||
@@ -168,7 +172,7 @@ esp_err_t update_certificates(){
|
||||
if ( (esp_err= nvs_get_str(handle, certs_version, NULL, &len)) == ESP_OK) {
|
||||
str=(char *)malloc(len);
|
||||
if ( (esp_err = nvs_get_str(handle, certs_version, str, &len)) == ESP_OK) {
|
||||
printf("String associated with key '%s' is %s \n", certs_version, str);
|
||||
ESP_LOGI(TAG,"String associated with key '%s' is %s", certs_version, str);
|
||||
}
|
||||
}
|
||||
if(str!=NULL){
|
||||
@@ -375,16 +379,14 @@ void app_main()
|
||||
ESP_LOGD(TAG,"Clearing CONNECTED_BIT from wifi group");
|
||||
xEventGroupClearBits(wifi_event_group, CONNECTED_BIT);
|
||||
|
||||
|
||||
ESP_LOGI(TAG,"Registering default values");
|
||||
register_default_nvs();
|
||||
|
||||
ESP_LOGD(TAG,"Configuring services");
|
||||
ESP_LOGI(TAG,"Configuring services");
|
||||
services_init();
|
||||
|
||||
ESP_LOGD(TAG,"Initializing display");
|
||||
ESP_LOGI(TAG,"Initializing display");
|
||||
display_init("SqueezeESP32");
|
||||
|
||||
if(!is_recovery_running){
|
||||
ESP_LOGI(TAG,"Checking if certificates need to be updated");
|
||||
update_certificates();
|
||||
@@ -418,10 +420,12 @@ void app_main()
|
||||
led_blink(LED_GREEN, 250, 250);
|
||||
|
||||
if(bypass_wifi_manager){
|
||||
ESP_LOGW(TAG,"\n\nwifi manager is disabled. Please use wifi commands to connect to your wifi access point.\n\n");
|
||||
ESP_LOGW(TAG,"*******************************************************************************************");
|
||||
ESP_LOGW(TAG,"* wifi manager is disabled. Please use wifi commands to connect to your wifi access point.");
|
||||
ESP_LOGW(TAG,"*******************************************************************************************");
|
||||
}
|
||||
else {
|
||||
ESP_LOGW(TAG,"\n\nwifi manager is ENABLED. Starting...\n\n");
|
||||
ESP_LOGI(TAG,"Starting Wifi Manager");
|
||||
wifi_manager_start();
|
||||
wifi_manager_set_callback(EVENT_STA_GOT_IP, &cb_connection_got_ip);
|
||||
wifi_manager_set_callback(EVENT_STA_DISCONNECTED, &cb_connection_sta_disconnected);
|
||||
@@ -445,4 +449,5 @@ void app_main()
|
||||
}
|
||||
free(fwurl);
|
||||
}
|
||||
messaging_post_message(MESSAGING_INFO,MESSAGING_CLASS_SYSTEM,"System started");
|
||||
}
|
||||
|
||||
@@ -480,7 +480,7 @@ CONFIG_ESP_EVENT_POST_FROM_ISR=y
|
||||
CONFIG_ESP_EVENT_POST_FROM_IRAM_ISR=y
|
||||
CONFIG_ESP_HTTP_CLIENT_ENABLE_HTTPS=y
|
||||
|
||||
CONFIG_HTTPD_MAX_REQ_HDR_LEN=512
|
||||
CONFIG_HTTPD_MAX_REQ_HDR_LEN=1024
|
||||
CONFIG_HTTPD_MAX_URI_LEN=512
|
||||
CONFIG_HTTPD_ERR_RESP_NO_DELAY=y
|
||||
CONFIG_HTTPD_PURGE_BUF_LEN=32
|
||||
|
||||
Reference in New Issue
Block a user