├── .cproject ├── .gitignore ├── .project ├── .settings ├── language.settings.xml ├── org.eclipse.cdt.codan.core.prefs ├── org.eclipse.cdt.core.prefs └── org.eclipse.ltk.core.refactoring.prefs ├── Documents ├── SIM800 Series_AT Command Manual_V1.09.pdf ├── SIM800_Hardware Design_V1.08.pdf └── neoway-m590-hardware-design-manual-v1.pdf ├── Makefile ├── README.md ├── components └── pppos │ ├── component.mk │ ├── libGSM.c │ └── libGSM.h ├── main ├── Kconfig ├── component.mk ├── pppos_client_main.c └── server_root_cert.pem ├── pppapi.c.patch ├── pppapi.c.patched └── sdkconfig.defaults /.cproject: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | make 106 | -j8 all 107 | true 108 | true 109 | true 110 | 111 | 112 | make 113 | 114 | flash 115 | true 116 | true 117 | true 118 | 119 | 120 | make 121 | clean 122 | true 123 | true 124 | true 125 | 126 | 127 | 128 | 129 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .config 2 | *.o 3 | *.pyc 4 | *.a 5 | *.d 6 | 7 | # gtags 8 | GTAGS 9 | GRTAGS 10 | GPATH 11 | 12 | # emacs 13 | .dir-locals.el 14 | 15 | # emacs temp file suffixes 16 | *~ 17 | .#* 18 | \#*# 19 | 20 | sdkconfig 21 | sdkconfig.old 22 | sdkconfig.lobo 23 | BUILD 24 | 25 | build/ 26 | temp/ 27 | *.dis 28 | *.elf 29 | *.map 30 | **/.DS_Store 31 | -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | ESP32-PPPOS-EXAMPLE 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.cdt.managedbuilder.core.genmakebuilder 10 | clean,full,incremental, 11 | 12 | 13 | 14 | 15 | org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder 16 | full,incremental, 17 | 18 | 19 | 20 | 21 | 22 | org.eclipse.cdt.core.cnature 23 | org.eclipse.cdt.core.ccnature 24 | org.eclipse.cdt.managedbuilder.core.managedBuildNature 25 | org.eclipse.cdt.managedbuilder.core.ScannerConfigNature 26 | 27 | 28 | -------------------------------------------------------------------------------- /.settings/language.settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /.settings/org.eclipse.cdt.codan.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.cdt.codan.checkers.errnoreturn=Warning 3 | 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} 4 | org.eclipse.cdt.codan.checkers.errreturnvalue=Error 5 | 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\\")"} 6 | org.eclipse.cdt.codan.checkers.nocommentinside=-Error 7 | 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\\")"} 8 | org.eclipse.cdt.codan.checkers.nolinecomment=-Error 9 | 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\\")"} 10 | org.eclipse.cdt.codan.checkers.noreturn=Error 11 | 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} 12 | org.eclipse.cdt.codan.internal.checkers.AbstractClassCreation=Error 13 | 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\\")"} 14 | org.eclipse.cdt.codan.internal.checkers.AmbiguousProblem=Error 15 | 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\\")"} 16 | org.eclipse.cdt.codan.internal.checkers.AssignmentInConditionProblem=Warning 17 | 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\\")"} 18 | org.eclipse.cdt.codan.internal.checkers.AssignmentToItselfProblem=Error 19 | 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\\")"} 20 | org.eclipse.cdt.codan.internal.checkers.CaseBreakProblem=Warning 21 | 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} 22 | org.eclipse.cdt.codan.internal.checkers.CatchByReference=Warning 23 | 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\=>()} 24 | org.eclipse.cdt.codan.internal.checkers.CircularReferenceProblem=Error 25 | 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\\")"} 26 | org.eclipse.cdt.codan.internal.checkers.ClassMembersInitialization=Warning 27 | 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} 28 | org.eclipse.cdt.codan.internal.checkers.FieldResolutionProblem=Error 29 | 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\\")"} 30 | org.eclipse.cdt.codan.internal.checkers.FunctionResolutionProblem=Error 31 | 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\\")"} 32 | org.eclipse.cdt.codan.internal.checkers.InvalidArguments=Error 33 | 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\\")"} 34 | org.eclipse.cdt.codan.internal.checkers.InvalidTemplateArgumentsProblem=Error 35 | 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\\")"} 36 | org.eclipse.cdt.codan.internal.checkers.LabelStatementNotFoundProblem=Error 37 | 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\\")"} 38 | org.eclipse.cdt.codan.internal.checkers.MemberDeclarationNotFoundProblem=Error 39 | 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\\")"} 40 | org.eclipse.cdt.codan.internal.checkers.MethodResolutionProblem=Error 41 | 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\\")"} 42 | org.eclipse.cdt.codan.internal.checkers.NamingConventionFunctionChecker=-Info 43 | 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\=>()} 44 | org.eclipse.cdt.codan.internal.checkers.NonVirtualDestructorProblem=Warning 45 | 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\\")"} 46 | org.eclipse.cdt.codan.internal.checkers.OverloadProblem=Error 47 | 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\\")"} 48 | org.eclipse.cdt.codan.internal.checkers.RedeclarationProblem=Error 49 | 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\\")"} 50 | org.eclipse.cdt.codan.internal.checkers.RedefinitionProblem=Error 51 | 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\\")"} 52 | org.eclipse.cdt.codan.internal.checkers.ReturnStyleProblem=-Warning 53 | 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\\")"} 54 | org.eclipse.cdt.codan.internal.checkers.ScanfFormatStringSecurityProblem=-Warning 55 | 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\\")"} 56 | org.eclipse.cdt.codan.internal.checkers.StatementHasNoEffectProblem=Warning 57 | 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\=>()} 58 | org.eclipse.cdt.codan.internal.checkers.SuggestedParenthesisProblem=Warning 59 | 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} 60 | org.eclipse.cdt.codan.internal.checkers.SuspiciousSemicolonProblem=Warning 61 | 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} 62 | org.eclipse.cdt.codan.internal.checkers.TypeResolutionProblem=Error 63 | 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\\")"} 64 | org.eclipse.cdt.codan.internal.checkers.UnusedFunctionDeclarationProblem=Warning 65 | 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} 66 | org.eclipse.cdt.codan.internal.checkers.UnusedStaticFunctionProblem=Warning 67 | 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} 68 | org.eclipse.cdt.codan.internal.checkers.UnusedVariableDeclarationProblem=Warning 69 | 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")} 70 | org.eclipse.cdt.codan.internal.checkers.VariableResolutionProblem=Error 71 | 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\\")"} 72 | useParentScope=false 73 | -------------------------------------------------------------------------------- /.settings/org.eclipse.cdt.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | environment/project/cdt.managedbuild.toolchain.gnu.cross.base.2062137617.1047447828/ESP_IDF/delimiter=\: 3 | environment/project/cdt.managedbuild.toolchain.gnu.cross.base.2062137617.1047447828/ESP_IDF/operation=replace 4 | environment/project/cdt.managedbuild.toolchain.gnu.cross.base.2062137617.1047447828/ESP_IDF/value=/home/LoBo2_Razno/ESP32/esp-idf 5 | environment/project/cdt.managedbuild.toolchain.gnu.cross.base.2062137617.1047447828/IDF_PATH/delimiter=\: 6 | environment/project/cdt.managedbuild.toolchain.gnu.cross.base.2062137617.1047447828/IDF_PATH/operation=append 7 | environment/project/cdt.managedbuild.toolchain.gnu.cross.base.2062137617.1047447828/IDF_PATH/value=/home/LoBo2_Razno/ESP32/esp-idf 8 | environment/project/cdt.managedbuild.toolchain.gnu.cross.base.2062137617.1047447828/PATH/delimiter=\: 9 | environment/project/cdt.managedbuild.toolchain.gnu.cross.base.2062137617.1047447828/PATH/operation=replace 10 | environment/project/cdt.managedbuild.toolchain.gnu.cross.base.2062137617.1047447828/PATH/value=/bin\:/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/usr/games\:/usr/local/games\:/snap/bin\:/usr/lib/jvm/java-8-oracle/bin\:/usr/lib/jvm/java-8-oracle/db/bin\:/usr/lib/jvm/java-8-oracle/jre/bin\:/home/LoBo2_Razno/ESP32/xtensa-esp32-elf/bin 11 | environment/project/cdt.managedbuild.toolchain.gnu.cross.base.2062137617.1047447828/append=true 12 | environment/project/cdt.managedbuild.toolchain.gnu.cross.base.2062137617.1047447828/appendContributed=true 13 | environment/project/cdt.managedbuild.toolchain.gnu.cross.base.2062137617/IDF_PATH/delimiter=\: 14 | environment/project/cdt.managedbuild.toolchain.gnu.cross.base.2062137617/IDF_PATH/operation=replace 15 | environment/project/cdt.managedbuild.toolchain.gnu.cross.base.2062137617/IDF_PATH/value=/home/LoBo2_Razno/ESP32/esp-idf 16 | environment/project/cdt.managedbuild.toolchain.gnu.cross.base.2062137617/PATH/delimiter=\: 17 | environment/project/cdt.managedbuild.toolchain.gnu.cross.base.2062137617/PATH/operation=replace 18 | environment/project/cdt.managedbuild.toolchain.gnu.cross.base.2062137617/PATH/value=/home/LoBo2_Razno/ESP32/xtensa-esp32-elf/bin\:/bin\:/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/usr/lib/jvm/java-8-oracle/bin\:/usr/lib/jvm/java-8-oracle/db/bin\:/usr/lib/jvm/java-8-oracle/jre/bin 19 | environment/project/cdt.managedbuild.toolchain.gnu.cross.base.2062137617/append=true 20 | environment/project/cdt.managedbuild.toolchain.gnu.cross.base.2062137617/appendContributed=true 21 | environment/project/cdt.managedbuild.toolchain.gnu.cross.base.458462299/IDF_PATH/delimiter=\: 22 | environment/project/cdt.managedbuild.toolchain.gnu.cross.base.458462299/IDF_PATH/operation=replace 23 | environment/project/cdt.managedbuild.toolchain.gnu.cross.base.458462299/IDF_PATH/value=/Users/jaumeolivepetrus/esp-idf 24 | environment/project/cdt.managedbuild.toolchain.gnu.cross.base.458462299/PATH/delimiter=\: 25 | environment/project/cdt.managedbuild.toolchain.gnu.cross.base.458462299/PATH/operation=replace 26 | environment/project/cdt.managedbuild.toolchain.gnu.cross.base.458462299/PATH/value=/usr/local/xtensa-esp32-elf/bin\:/bin\:/usr/bin\:/usr/sbin\:/sbin 27 | environment/project/cdt.managedbuild.toolchain.gnu.cross.base.458462299/append=true 28 | environment/project/cdt.managedbuild.toolchain.gnu.cross.base.458462299/appendContributed=true 29 | environment/project/cdt.managedbuild.toolchain.gnu.cross.base.458462299/v/delimiter=\: 30 | environment/project/cdt.managedbuild.toolchain.gnu.cross.base.458462299/v/operation=append 31 | environment/project/cdt.managedbuild.toolchain.gnu.cross.base.458462299/v/value=1 32 | -------------------------------------------------------------------------------- /.settings/org.eclipse.ltk.core.refactoring.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.ltk.core.refactoring.enable.project.refactoring.history=false 3 | -------------------------------------------------------------------------------- /Documents/SIM800 Series_AT Command Manual_V1.09.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/loboris/ESP32-PPPOS-EXAMPLE/6a3664130abe6ce8ea41d748dff5e5db9788d210/Documents/SIM800 Series_AT Command Manual_V1.09.pdf -------------------------------------------------------------------------------- /Documents/SIM800_Hardware Design_V1.08.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/loboris/ESP32-PPPOS-EXAMPLE/6a3664130abe6ce8ea41d748dff5e5db9788d210/Documents/SIM800_Hardware Design_V1.08.pdf -------------------------------------------------------------------------------- /Documents/neoway-m590-hardware-design-manual-v1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/loboris/ESP32-PPPOS-EXAMPLE/6a3664130abe6ce8ea41d748dff5e5db9788d210/Documents/neoway-m590-hardware-design-manual-v1.pdf -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # This is a project Makefile. It is assumed the directory this Makefile resides in is a 3 | # project subdirectory. 4 | # 5 | 6 | PROJECT_NAME := pppos_client 7 | 8 | include $(IDF_PATH)/make/project.mk 9 | 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### PPP over Serial (PPPoS) client example 2 | 3 | Tested with **esp-idf v2.1** and latest esp-idf master branch 4 | 5 | --- 6 | 7 | If using with latest esp-idf (e6afe28bafe5db5ab79fae213f2e8e1ccd9f937c or later) a patch for **components/lwip/api/pppapi.c** is need. 8 | 9 | Use included **pppapi.c.patch** to patch the file or copy **pppapi.c.patched** to **components/lwip/api/** as **pppapi.c** 10 | 11 | ** This patch was merged into esp-idf on 14. Nov 2017** 12 | 13 | --- 14 | 15 | **Includes GSM library** *libGSM* **which handles all GSM and PPPoS operations*** 16 | 17 | See *libGSM.h* for functions usage detailes. 18 | 19 | --- 20 | 21 | #### How to build 22 | 23 | Configure your esp32 build environment as for other **esp-idf examples** 24 | 25 | Clone the repository 26 | 27 | `git clone https://github.com/loboris/ESP32-PPPOS-EXAMPLE.git` 28 | 29 | Execute menuconfig and configure your Serial flash config and other settings. Included *sdkconfig.defaults* sets some defaults to be used. 30 | 31 | Navigate to **GSM PPPoS configuration** and set GSM and example parameters: 32 | 33 | * **Enable GSM debugging** if set GSM AT commands and responses are printed 34 | * **UART Output to GSM Module** UART Tx pin, connected to GSM Module Rx pin. 35 | * **UART Input from GSM Module** UART Rx pin, connected to GSM Module Tx pin. 36 | * **UART Baud rate** UART baudrate to comunicate with GSM module 37 | * **Internet User** Network provider internet user. 38 | * **Internet password** Network provider internet password 39 | * **Internet APN** Network provider's APN for internet access 40 | * **Start WiFi and AP** Enable WiFi, configure AP, start WebServer to test local WiFi and Internet over GSM/PPPoS connection 41 | * **Send SMS message** if set SMS messages will be sent during example run 42 | * **SMS number** SMS number for sending messages, enter the number in international format (+123999876543) 43 | * **SMS message interval** Set SMS message interval in miliseconds 44 | 45 | `make menuconfig` 46 | 47 | Make and flash the example. 48 | 49 | `make all && make flash` 50 | 51 | --- 52 | 53 | Power your GSM module with good power supply, using LiPo battery is recommended. 54 | 55 | In this example **hw flow controll** is not used. With 2G (GPRS) module it is not needed. 56 | If using higher speed 3G module, using hw flow controll is recomended. You can configure it in *libGSM.c* 57 | 58 | --- 59 | 60 | #### The example runs as follows: 61 | 62 | 1. Creates the **pppos client task** which initializes modem on UART port and handles lwip interaction 63 | 2. If configured, starts WiFi, Access Point and WebServer 64 | 3. When connection to the Internet is established, gets the current time using SNTP protocol 65 | 4. Creates **http**, **https** and **sms** tasks synchronized with mutex 66 | 5. **HTTP task** gets text file from server and displays the header and data 67 | 6. **HTTPS task** gets ssl info from server and displays the header and received JSON data with info about used SSL 68 | 7. **SMS task** sends SMS messages after defined interval has passed, checks and displays received messages. If received messages starts with **Esp32 info** sends the response message to senders number. 69 | 8. The tasks repeats operation after interval defined in *pppos_client_main.c* 70 | 9. If WiFi is configured, simple web page can be accessed on *http://192.168.4.1*. Generated page includes includes the text received from internet via PPPoS. 71 | 72 | 73 | #### Tested with GSM SIM800L, should also work with other SIMCOM & Telit GSM modules. 74 | 75 | 76 | **Example output:** 77 | 78 | ``` 79 | I (0) cpu_start: App cpu up. 80 | I (1121) heap_alloc_caps: Initializing. RAM available for dynamic allocation: 81 | I (1143) heap_alloc_caps: At 3FFAE2A0 len 00001D60 (7 KiB): DRAM 82 | I (1164) heap_alloc_caps: At 3FFB6F28 len 000290D8 (164 KiB): DRAM 83 | I (1185) heap_alloc_caps: At 3FFE0440 len 00003BC0 (14 KiB): D/IRAM 84 | I (1206) heap_alloc_caps: At 3FFE4350 len 0001BCB0 (111 KiB): D/IRAM 85 | I (1228) heap_alloc_caps: At 40092D0C len 0000D2F4 (52 KiB): IRAM 86 | I (1249) cpu_start: Pro cpu start user code 87 | I (1304) cpu_start: Starting scheduler on PRO CPU. 88 | I (197) cpu_start: Starting scheduler on APP CPU. 89 | I (297) [PPPOS CLIENT]: AT COMMAND: [AT..] 90 | I (317) [PPPOS CLIENT]: AT RESPONSE: [..OK..] 91 | I (417) [PPPOS CLIENT]: AT COMMAND: [AT+CFUN=4..] 92 | I (437) [PPPOS CLIENT]: AT RESPONSE: [..OK..] 93 | I (437) [PPPOS CLIENT]: GSM initialization start 94 | I (1037) [PPPOS CLIENT]: AT COMMAND: [AT..] 95 | I (1057) [PPPOS CLIENT]: AT RESPONSE: [..OK..] 96 | I (1157) [PPPOS CLIENT]: AT COMMAND: [ATZ..] 97 | I (1177) [PPPOS CLIENT]: AT RESPONSE: [..OK..] 98 | I (1277) [PPPOS CLIENT]: AT COMMAND: [ATE0..] 99 | I (1297) [PPPOS CLIENT]: AT RESPONSE: [ATE0...OK..] 100 | I (1397) [PPPOS CLIENT]: AT COMMAND: [AT+CFUN=1..] 101 | I (1417) [PPPOS CLIENT]: AT RESPONSE: [..OK..] 102 | I (2517) [PPPOS CLIENT]: AT COMMAND: [AT+CNMI=0,0,0,0,0..] 103 | I (2537) [PPPOS CLIENT]: AT RESPONSE: [..OK..] 104 | I (2637) [PPPOS CLIENT]: AT COMMAND: [AT+CPIN?..] 105 | I (2657) [PPPOS CLIENT]: AT RESPONSE: [..+CPIN: READY....OK..] 106 | I (2757) [PPPOS CLIENT]: AT COMMAND: [AT+CREG?..] 107 | I (2777) [PPPOS CLIENT]: AT BAD RESPONSE: [..+CREG: 0,2....OK..] 108 | W (2777) [PPPOS CLIENT]: Wrong response, restarting... 109 | I (5777) [PPPOS CLIENT]: Skip command: [AT..] 110 | I (5777) [PPPOS CLIENT]: Skip command: [ATZ..] 111 | I (5777) [PPPOS CLIENT]: Skip command: [ATE0..] 112 | I (5777) [PPPOS CLIENT]: Skip command: [AT+CFUN=1..] 113 | I (5777) [PPPOS CLIENT]: Skip command: [AT+CNMI=0,0,0,0,0..] 114 | I (5787) [PPPOS CLIENT]: Skip command: [AT+CPIN?..] 115 | I (5897) [PPPOS CLIENT]: AT COMMAND: [AT+CREG?..] 116 | I (5917) [PPPOS CLIENT]: AT BAD RESPONSE: [..+CREG: 0,2....OK..] 117 | W (5917) [PPPOS CLIENT]: Wrong response, restarting... 118 | I (8917) [PPPOS CLIENT]: Skip command: [AT..] 119 | I (8917) [PPPOS CLIENT]: Skip command: [ATZ..] 120 | I (8917) [PPPOS CLIENT]: Skip command: [ATE0..] 121 | I (8917) [PPPOS CLIENT]: Skip command: [AT+CFUN=1..] 122 | I (8917) [PPPOS CLIENT]: Skip command: [AT+CNMI=0,0,0,0,0..] 123 | I (8927) [PPPOS CLIENT]: Skip command: [AT+CPIN?..] 124 | I (9037) [PPPOS CLIENT]: AT COMMAND: [AT+CREG?..] 125 | I (9057) [PPPOS CLIENT]: AT RESPONSE: [..+CREG: 0,1....OK..] 126 | I (19157) [PPPOS CLIENT]: AT COMMAND: [AT+CGDCONT=1,"IP","internet.ht.hr"..] 127 | I (19177) [PPPOS CLIENT]: AT RESPONSE: [..OK..] 128 | I (19277) [PPPOS CLIENT]: AT COMMAND: [AT+CGDATA="PPP",1..] 129 | I (19297) [PPPOS CLIENT]: AT RESPONSE: [..CONNECT..] 130 | I (20297) [PPPOS CLIENT]: GSM initialized. 131 | I (21077) [PPPOS CLIENT]: status_cb: Connected 132 | I (21077) [PPPOS CLIENT]: ipaddr = 10.229.68.97 133 | I (21077) [PPPOS CLIENT]: gateway = 10.64.64.64 134 | I (21077) [PPPOS CLIENT]: netmask = 255.255.255.255 135 | I (21087) [PPPOS CLIENT]: ip6addr = :: 136 | 137 | I (21087) [SNTP]: OBTAINING TIME 138 | I (21097) [SNTP]: Initializing SNTP 139 | I (21107) [SNTP]: SNTP INITIALIZED 140 | I (21107) [SNTP]: Waiting for system time to be set... (1/10) 141 | I (23107) [SNTP]: TIME SET TO Mon Jun 19 09:30:55 2017 142 | 143 | I (23117) [HTTP]: ===== HTTP GET REQUEST ========================================= 144 | 145 | I (23497) [HTTP]: DNS lookup succeeded. IP=82.196.4.208 146 | I (23497) [HTTP]: ... allocated socket 147 | 148 | I (23787) [HTTP]: ... connected 149 | I (23797) [HTTP]: ... socket send success 150 | I (23797) [HTTP]: ... reading HTTP response... 151 | Header: 152 | ------- 153 | HTTP/1.1 200 OK 154 | Date: Mon, 19 Jun 2017 09:30:57 GMT 155 | Server: Apache/2.4.7 (Ubuntu) 156 | Last-Modified: Sat, 18 Mar 2017 17:32:44 GMT 157 | ETag: "149-54b04ae918eb8" 158 | Accept-Ranges: bytes 159 | Content-Length: 329 160 | Vary: Accept-Encoding 161 | Content-Type: text/plain 162 | ------- 163 | Data: 164 | ----- 165 | Welcome to ESP32 166 | The ESP32 is a low cost, low power microcontroller with integrated Wi-Fi & dual-mode Bluetooth, 167 | which employs a dual-core Tensilica Xtensa LX6 microprocessor. 168 | ESP32 is created and developed by Espressif Systems, a Shanghai-based Chinese company, 169 | and is manufactured by TSMC using their 40 nm process. 170 | 171 | 2017 LoBo 172 | 173 | ----- 174 | I (29267) [HTTP]: ... done reading from socket. 581 bytes read, 581 in buffer, errno=22 175 | 176 | 177 | I (31317) [PPPOS CLIENT]: Disconnect requested. 178 | W (31347) [PPPOS CLIENT]: status_cb: User interrupt (disconnected) 179 | I (32447) [PPPOS CLIENT]: AT COMMAND: [AT..] 180 | I (32467) [PPPOS CLIENT]: AT RESPONSE: [..OK..] 181 | I (32567) [PPPOS CLIENT]: AT COMMAND: [AT+CFUN=4..] 182 | I (35057) [PPPOS CLIENT]: AT RESPONSE: [..OK..] 183 | I (35057) [PPPOS CLIENT]: Disconnected. 184 | I (35127) [HTTP]: Waiting 300 sec... 185 | I (35127) [HTTP]: ================================================================ 186 | 187 | 188 | I (35127) [HTTPS]: Seeding the random number generator 189 | I (35127) [HTTPS]: Loading the CA root certificate... 190 | I (35137) [HTTPS]: Setting hostname for TLS session... 191 | I (35137) [HTTPS]: Setting up the SSL/TLS structure... 192 | 193 | I (35157) [PPPOS CLIENT]: Reconnect requested. 194 | I (35157) [PPPOS CLIENT]: GSM initialization start 195 | I (35757) [PPPOS CLIENT]: AT COMMAND: [AT..] 196 | I (35777) [PPPOS CLIENT]: AT RESPONSE: [..OK..] 197 | I (35877) [PPPOS CLIENT]: AT COMMAND: [ATZ..] 198 | I (35897) [PPPOS CLIENT]: AT RESPONSE: [..OK..] 199 | I (35997) [PPPOS CLIENT]: AT COMMAND: [ATE0..] 200 | I (36017) [PPPOS CLIENT]: AT RESPONSE: [ATE0...OK..] 201 | I (36117) [PPPOS CLIENT]: AT COMMAND: [AT+CFUN=1..] 202 | I (36137) [PPPOS CLIENT]: AT RESPONSE: [..OK..] 203 | I (37237) [PPPOS CLIENT]: AT COMMAND: [AT+CNMI=0,0,0,0,0..] 204 | I (37257) [PPPOS CLIENT]: AT RESPONSE: [..OK..] 205 | I (37357) [PPPOS CLIENT]: AT COMMAND: [AT+CPIN?..] 206 | I (37377) [PPPOS CLIENT]: AT RESPONSE: [..+CPIN: READY....OK..] 207 | I (37477) [PPPOS CLIENT]: AT COMMAND: [AT+CREG?..] 208 | I (37497) [PPPOS CLIENT]: AT BAD RESPONSE: [..+CREG: 0,2....OK..] 209 | W (37497) [PPPOS CLIENT]: Wrong response, restarting... 210 | I (40497) [PPPOS CLIENT]: Skip command: [AT..] 211 | I (40497) [PPPOS CLIENT]: Skip command: [ATZ..] 212 | I (40497) [PPPOS CLIENT]: Skip command: [ATE0..] 213 | I (40497) [PPPOS CLIENT]: Skip command: [AT+CFUN=1..] 214 | I (40507) [PPPOS CLIENT]: Skip command: [AT+CNMI=0,0,0,0,0..] 215 | I (40507) [PPPOS CLIENT]: Skip command: [AT+CPIN?..] 216 | I (40617) [PPPOS CLIENT]: AT COMMAND: [AT+CREG?..] 217 | I (40637) [PPPOS CLIENT]: AT RESPONSE: [..+CREG: 0,1....OK..] 218 | I (40737) [PPPOS CLIENT]: AT COMMAND: [AT+CGDCONT=1,"IP","internet.ht.hr"..] 219 | I (40757) [PPPOS CLIENT]: AT RESPONSE: [..OK..] 220 | I (40857) [PPPOS CLIENT]: AT COMMAND: [AT+CGDATA="PPP",1..] 221 | I (40877) [PPPOS CLIENT]: AT RESPONSE: [..CONNECT..] 222 | I (41877) [PPPOS CLIENT]: GSM initialized. 223 | I (42917) [PPPOS CLIENT]: status_cb: Connected 224 | I (42917) [PPPOS CLIENT]: ipaddr = 10.226.211.69 225 | I (42917) [PPPOS CLIENT]: gateway = 10.64.64.64 226 | I (42917) [PPPOS CLIENT]: netmask = 255.255.255.255 227 | I (42927) [PPPOS CLIENT]: ip6addr = :: 228 | I (42937) [HTTPS]: ===== HTTPS GET REQUEST ========================================= 229 | 230 | I (42937) [HTTPS]: Connecting to www.howsmyssl.com:443... 231 | I (43787) [HTTPS]: Connected. 232 | I (43787) [HTTPS]: Performing the SSL/TLS handshake... 233 | I (46807) [HTTPS]: Verifying peer X.509 certificate... 234 | W (46807) [HTTPS]: Failed to verify peer certificate! 235 | W (46807) [HTTPS]: verification info: ! The certificate Common Name (CN) does not match with the expected CN 236 | 237 | I (46817) [HTTPS]: Writing HTTP request... 238 | I (46827) [HTTPS]: 102 bytes written 239 | I (46827) [HTTPS]: Reading HTTP response... 240 | I (48007) [HTTPS]: 5524 bytes read, 5524 in buffer 241 | Header: 242 | ------- 243 | HTTP/1.1 200 OK 244 | Content-Length: 5289 245 | Access-Control-Allow-Origin: * 246 | Connection: close 247 | Content-Type: application/json 248 | Date: Mon, 19 Jun 2017 09:31:19 GMT 249 | Strict-Transport-Security: max-age=631138519; includeSubdomains; preload 250 | ------- 251 | I (48027) [HTTPS]: JSON data received. 252 | I (48037) [HTTPS]: parsing JSON data: 253 | given_cipher_suites = [Array] of 131 items 254 | TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 255 | TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 256 | TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 257 | + 128 more... 258 | ephemeral_keys_supported = True 259 | session_ticket_supported = True 260 | tls_compression_supported = False 261 | unknown_cipher_suite_supported = False 262 | beast_vuln = False 263 | able_to_detect_n_minus_one_splitting = False 264 | insecure_cipher_suites = {Object} 265 | tls_version = TLS 1.2 266 | rating = Probably Okay 267 | 268 | I (50087) [PPPOS CLIENT]: Disconnect requested. 269 | W (50117) [PPPOS CLIENT]: status_cb: User interrupt (disconnected) 270 | I (51217) [PPPOS CLIENT]: AT COMMAND: [AT..] 271 | I (51237) [PPPOS CLIENT]: AT RESPONSE: [..OK..] 272 | I (51337) [PPPOS CLIENT]: AT COMMAND: [AT+CFUN=4..] 273 | I (53797) [PPPOS CLIENT]: AT RESPONSE: [..OK..] 274 | I (53797) [PPPOS CLIENT]: Disconnected. 275 | I (53797) [HTTPS]: Waiting 300 sec... 276 | I (53797) [HTTPS]: ================================================================= 277 | 278 | 279 | I (53807) [SMS]: ===== SMS TEST ================================================= 280 | 281 | I (53917) [PPPOS CLIENT]: AT COMMAND: [AT+CFUN?..] 282 | I (56117) [PPPOS CLIENT]: AT COMMAND: [AT+CFUN=1..] 283 | I (56137) [PPPOS CLIENT]: AT RESPONSE: [..OK..] 284 | I (58237) [PPPOS CLIENT]: AT COMMAND: [AT+CFUN?..] 285 | I (58257) [PPPOS CLIENT]: AT RESPONSE: [..+CFUN: 1....OK..] 286 | I (58357) [PPPOS CLIENT]: AT COMMAND: [AT+CMGF=1..] 287 | I (58377) [PPPOS CLIENT]: AT RESPONSE: [..OK..] 288 | I (58477) [PPPOS CLIENT]: AT COMMAND: [AT+CMGS="+38599xxxxxxx"..] 289 | I (58497) [PPPOS CLIENT]: AT RESPONSE: [..> ] 290 | I (58597) [PPPOS CLIENT]: AT COMMAND: [Hi from ESP32 via GSM.This is the test message..] 291 | I (65617) [PPPOS CLIENT]: AT RESPONSE: [..+CMGS: 35....OK..] 292 | SMS sent successfully 293 | I (65717) [PPPOS CLIENT]: AT COMMAND: [AT+CFUN?..] 294 | I (65737) [PPPOS CLIENT]: AT RESPONSE: [..+CFUN: 1....OK..] 295 | I (65837) [PPPOS CLIENT]: AT COMMAND: [AT+CMGF=1..] 296 | I (65857) [PPPOS CLIENT]: AT RESPONSE: [..OK..] 297 | I (65957) [PPPOS CLIENT]: AT COMMAND: [AT+CMGL="ALL"..] 298 | 299 | No messages 300 | I (68157) [PPPOS CLIENT]: AT COMMAND: [AT+CFUN?..] 301 | I (70357) [PPPOS CLIENT]: AT COMMAND: [AT+CFUN=4..] 302 | I (74097) [PPPOS CLIENT]: AT RESPONSE: [..OK..] 303 | I (74097) [SMS]: Waiting 300 sec... 304 | I (74097) [SMS]: ================================================================ 305 | 306 | . 307 | . 308 | . 309 | 310 | I (4238867) [SMS]: ===== SMS TEST ================================================= 311 | 312 | I (4238977) [PPPOS CLIENT]: AT COMMAND: [AT+CFUN?..] 313 | I (4241177) [PPPOS CLIENT]: AT COMMAND: [AT+CFUN=1..] 314 | I (4241197) [PPPOS CLIENT]: AT RESPONSE: [..OK..] 315 | I (4243297) [PPPOS CLIENT]: AT COMMAND: [AT+CFUN?..] 316 | I (4243317) [PPPOS CLIENT]: AT RESPONSE: [..+CFUN: 1....OK..] 317 | I (4243417) [PPPOS CLIENT]: AT COMMAND: [AT+CMGF=1..] 318 | I (4243437) [PPPOS CLIENT]: AT RESPONSE: [..OK..] 319 | I (4243537) [PPPOS CLIENT]: AT COMMAND: [AT+CMGL="ALL"..] 320 | 321 | Received messages: 1 322 | ------------------------------------------- 323 | Message #1: idx=1, from: +38599xxxxxxx, status: REC UNREAD, time: 17/06/19,12:37:52+08, tz=GMT+2, timestamp: Wed Jul 19 12:37:52 2017 324 | 325 | Text: [ 326 | Esp32 info, send me a reply 327 | ] 328 | 329 | I (4245807) [PPPOS CLIENT]: AT COMMAND: [AT+CFUN?..] 330 | I (4245827) [PPPOS CLIENT]: AT RESPONSE: [..+CFUN: 1....OK..] 331 | I (4245927) [PPPOS CLIENT]: AT COMMAND: [AT+CMGF=1..] 332 | I (4245947) [PPPOS CLIENT]: AT RESPONSE: [..OK..] 333 | I (4246047) [PPPOS CLIENT]: AT COMMAND: [AT+CMGS="+38599xxxxxxx"..] 334 | I (4246067) [PPPOS CLIENT]: AT RESPONSE: [..> ] 335 | I (4246167) [PPPOS CLIENT]: AT COMMAND: [Hi, +38599xxxxxxx.My time is now.06/19/17 10:41:17.] 336 | I (4250777) [PPPOS CLIENT]: AT RESPONSE: [..+CMGS: 38....OK..] 337 | Response sent successfully 338 | Delete message at index 1 339 | I (4250877) [PPPOS CLIENT]: AT COMMAND: [AT+CFUN?..] 340 | I (4250897) [PPPOS CLIENT]: AT RESPONSE: [..+CFUN: 1....OK..] 341 | I (4250997) [PPPOS CLIENT]: AT COMMAND: [AT+CMGF=1..] 342 | I (4251017) [PPPOS CLIENT]: AT RESPONSE: [..OK..] 343 | I (4251117) [PPPOS CLIENT]: AT COMMAND: [AT+CMGD=1..] 344 | I (4251227) [PPPOS CLIENT]: AT RESPONSE: [..OK..] 345 | Delete OK 346 | I (4251327) [PPPOS CLIENT]: AT COMMAND: [AT+CFUN?..] 347 | I (4253527) [PPPOS CLIENT]: AT COMMAND: [AT+CFUN=4..] 348 | I (4254357) [PPPOS CLIENT]: AT RESPONSE: [..OK..] 349 | I (4254357) [SMS]: Waiting 300 sec... 350 | I (4254357) [SMS]: ================================================================ 351 | 352 | 353 | ``` 354 | -------------------------------------------------------------------------------- /components/pppos/component.mk: -------------------------------------------------------------------------------- 1 | # 2 | # Component Makefile 3 | # 4 | 5 | COMPONENT_SRCDIRS := . 6 | COMPONENT_ADD_INCLUDEDIRS := . -------------------------------------------------------------------------------- /components/pppos/libGSM.c: -------------------------------------------------------------------------------- 1 | /* PPPoS Client Example with GSM (tested with Telit GL865-DUAL-V3) 2 | 3 | This example code is in the Public Domain (or CC0 licensed, at your option.) 4 | 5 | Unless required by applicable law or agreed to in writing, this 6 | software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 7 | CONDITIONS OF ANY KIND, either express or implied. 8 | */ 9 | #include 10 | #include "freertos/FreeRTOS.h" 11 | #include "freertos/task.h" 12 | #include "esp_system.h" 13 | #include "esp_log.h" 14 | 15 | #include "driver/uart.h" 16 | #include "driver/gpio.h" 17 | #include "tcpip_adapter.h" 18 | #include "netif/ppp/pppos.h" 19 | #include "netif/ppp/ppp.h" 20 | #include "lwip/pppapi.h" 21 | 22 | #include "libGSM.h" 23 | 24 | 25 | // === GSM configuration that you can set via 'make menuconfig'. === 26 | #define UART_GPIO_TX CONFIG_GSM_TX 27 | #define UART_GPIO_RX CONFIG_GSM_RX 28 | #define UART_BDRATE CONFIG_GSM_BDRATE 29 | 30 | #ifdef CONFIG_GSM_DEBUG 31 | #define GSM_DEBUG 1 32 | #else 33 | #define GSM_DEBUG 0 34 | #endif 35 | #define BUF_SIZE (1024) 36 | #define GSM_OK_Str "OK" 37 | #define PPPOSMUTEX_TIMEOUT 1000 / portTICK_RATE_MS 38 | 39 | #define PPPOS_CLIENT_STACK_SIZE 1024*3 40 | 41 | 42 | // shared variables, use mutex to access them 43 | static uint8_t gsm_status = GSM_STATE_FIRSTINIT; 44 | static int do_pppos_connect = 1; 45 | static uint32_t pppos_rx_count; 46 | static uint32_t pppos_tx_count; 47 | static uint8_t pppos_task_started = 0; 48 | static uint8_t gsm_rfOff = 0; 49 | 50 | // local variables 51 | static QueueHandle_t pppos_mutex = NULL; 52 | const char *PPP_User = CONFIG_GSM_INTERNET_USER; 53 | const char *PPP_Pass = CONFIG_GSM_INTERNET_PASSWORD; 54 | static int uart_num = UART_NUM_1; 55 | 56 | static uint8_t tcpip_adapter_initialized = 0; 57 | 58 | // The PPP control block 59 | static ppp_pcb *ppp = NULL; 60 | 61 | // The PPP IP interface 62 | struct netif ppp_netif; 63 | 64 | static const char *TAG = "[PPPOS CLIENT]"; 65 | 66 | typedef struct 67 | { 68 | char *cmd; 69 | uint16_t cmdSize; 70 | char *cmdResponseOnOk; 71 | uint16_t timeoutMs; 72 | uint16_t delayMs; 73 | uint8_t skip; 74 | }GSM_Cmd; 75 | 76 | static GSM_Cmd cmd_AT = 77 | { 78 | .cmd = "AT\r\n", 79 | .cmdSize = sizeof("AT\r\n")-1, 80 | .cmdResponseOnOk = GSM_OK_Str, 81 | .timeoutMs = 300, 82 | .delayMs = 0, 83 | .skip = 0, 84 | }; 85 | 86 | static GSM_Cmd cmd_NoSMSInd = 87 | { 88 | .cmd = "AT+CNMI=0,0,0,0,0\r\n", 89 | .cmdSize = sizeof("AT+CNMI=0,0,0,0,0\r\n")-1, 90 | .cmdResponseOnOk = GSM_OK_Str, 91 | .timeoutMs = 1000, 92 | .delayMs = 0, 93 | .skip = 0, 94 | }; 95 | 96 | static GSM_Cmd cmd_Reset = 97 | { 98 | .cmd = "ATZ\r\n", 99 | .cmdSize = sizeof("ATZ\r\n")-1, 100 | .cmdResponseOnOk = GSM_OK_Str, 101 | .timeoutMs = 300, 102 | .delayMs = 0, 103 | .skip = 0, 104 | }; 105 | 106 | static GSM_Cmd cmd_RFOn = 107 | { 108 | .cmd = "AT+CFUN=1\r\n", 109 | .cmdSize = sizeof("ATCFUN=1,0\r\n")-1, 110 | .cmdResponseOnOk = GSM_OK_Str, 111 | .timeoutMs = 10000, 112 | .delayMs = 1000, 113 | .skip = 0, 114 | }; 115 | 116 | static GSM_Cmd cmd_EchoOff = 117 | { 118 | .cmd = "ATE0\r\n", 119 | .cmdSize = sizeof("ATE0\r\n")-1, 120 | .cmdResponseOnOk = GSM_OK_Str, 121 | .timeoutMs = 300, 122 | .delayMs = 0, 123 | .skip = 0, 124 | }; 125 | 126 | static GSM_Cmd cmd_Pin = 127 | { 128 | .cmd = "AT+CPIN?\r\n", 129 | .cmdSize = sizeof("AT+CPIN?\r\n")-1, 130 | .cmdResponseOnOk = "CPIN: READY", 131 | .timeoutMs = 5000, 132 | .delayMs = 0, 133 | .skip = 0, 134 | }; 135 | 136 | static GSM_Cmd cmd_Reg = 137 | { 138 | .cmd = "AT+CREG?\r\n", 139 | .cmdSize = sizeof("AT+CREG?\r\n")-1, 140 | .cmdResponseOnOk = "CREG: 0,1", 141 | .timeoutMs = 3000, 142 | .delayMs = 2000, 143 | .skip = 0, 144 | }; 145 | 146 | static GSM_Cmd cmd_APN = 147 | { 148 | .cmd = NULL, 149 | .cmdSize = 0, 150 | .cmdResponseOnOk = GSM_OK_Str, 151 | .timeoutMs = 8000, 152 | .delayMs = 0, 153 | .skip = 0, 154 | }; 155 | 156 | static GSM_Cmd cmd_Connect = 157 | { 158 | .cmd = "AT+CGDATA=\"PPP\",1\r\n", 159 | .cmdSize = sizeof("AT+CGDATA=\"PPP\",1\r\n")-1, 160 | //.cmd = "ATDT*99***1#\r\n", 161 | //.cmdSize = sizeof("ATDT*99***1#\r\n")-1, 162 | .cmdResponseOnOk = "CONNECT", 163 | .timeoutMs = 30000, 164 | .delayMs = 1000, 165 | .skip = 0, 166 | }; 167 | 168 | static GSM_Cmd *GSM_Init[] = 169 | { 170 | &cmd_AT, 171 | &cmd_Reset, 172 | &cmd_EchoOff, 173 | &cmd_RFOn, 174 | &cmd_NoSMSInd, 175 | &cmd_Pin, 176 | &cmd_Reg, 177 | &cmd_APN, 178 | &cmd_Connect, 179 | }; 180 | 181 | #define GSM_InitCmdsSize (sizeof(GSM_Init)/sizeof(GSM_Cmd *)) 182 | 183 | 184 | // PPP status callback 185 | //-------------------------------------------------------------- 186 | static void ppp_status_cb(ppp_pcb *pcb, int err_code, void *ctx) 187 | { 188 | struct netif *pppif = ppp_netif(pcb); 189 | LWIP_UNUSED_ARG(ctx); 190 | 191 | switch(err_code) { 192 | case PPPERR_NONE: { 193 | #if GSM_DEBUG 194 | ESP_LOGI(TAG,"status_cb: Connected"); 195 | #if PPP_IPV4_SUPPORT 196 | ESP_LOGI(TAG," ipaddr = %s", ipaddr_ntoa(&pppif->ip_addr)); 197 | ESP_LOGI(TAG," gateway = %s", ipaddr_ntoa(&pppif->gw)); 198 | ESP_LOGI(TAG," netmask = %s", ipaddr_ntoa(&pppif->netmask)); 199 | #endif 200 | 201 | #if PPP_IPV6_SUPPORT 202 | ESP_LOGI(TAG," ip6addr = %s", ip6addr_ntoa(netif_ip6_addr(pppif, 0))); 203 | #endif 204 | #endif 205 | xSemaphoreTake(pppos_mutex, PPPOSMUTEX_TIMEOUT); 206 | gsm_status = GSM_STATE_CONNECTED; 207 | xSemaphoreGive(pppos_mutex); 208 | break; 209 | } 210 | case PPPERR_PARAM: { 211 | #if GSM_DEBUG 212 | ESP_LOGE(TAG,"status_cb: Invalid parameter"); 213 | #endif 214 | break; 215 | } 216 | case PPPERR_OPEN: { 217 | #if GSM_DEBUG 218 | ESP_LOGE(TAG,"status_cb: Unable to open PPP session"); 219 | #endif 220 | break; 221 | } 222 | case PPPERR_DEVICE: { 223 | #if GSM_DEBUG 224 | ESP_LOGE(TAG,"status_cb: Invalid I/O device for PPP"); 225 | #endif 226 | break; 227 | } 228 | case PPPERR_ALLOC: { 229 | #if GSM_DEBUG 230 | ESP_LOGE(TAG,"status_cb: Unable to allocate resources"); 231 | #endif 232 | break; 233 | } 234 | case PPPERR_USER: { 235 | /* ppp_free(); -- can be called here */ 236 | #if GSM_DEBUG 237 | ESP_LOGW(TAG,"status_cb: User interrupt (disconnected)"); 238 | #endif 239 | xSemaphoreTake(pppos_mutex, PPPOSMUTEX_TIMEOUT); 240 | gsm_status = GSM_STATE_DISCONNECTED; 241 | xSemaphoreGive(pppos_mutex); 242 | break; 243 | } 244 | case PPPERR_CONNECT: { 245 | #if GSM_DEBUG 246 | ESP_LOGE(TAG,"status_cb: Connection lost"); 247 | #endif 248 | xSemaphoreTake(pppos_mutex, PPPOSMUTEX_TIMEOUT); 249 | gsm_status = GSM_STATE_DISCONNECTED; 250 | xSemaphoreGive(pppos_mutex); 251 | break; 252 | } 253 | case PPPERR_AUTHFAIL: { 254 | #if GSM_DEBUG 255 | ESP_LOGE(TAG,"status_cb: Failed authentication challenge"); 256 | #endif 257 | break; 258 | } 259 | case PPPERR_PROTOCOL: { 260 | #if GSM_DEBUG 261 | ESP_LOGE(TAG,"status_cb: Failed to meet protocol"); 262 | #endif 263 | break; 264 | } 265 | case PPPERR_PEERDEAD: { 266 | #if GSM_DEBUG 267 | ESP_LOGE(TAG,"status_cb: Connection timeout"); 268 | #endif 269 | break; 270 | } 271 | case PPPERR_IDLETIMEOUT: { 272 | #if GSM_DEBUG 273 | ESP_LOGE(TAG,"status_cb: Idle Timeout"); 274 | #endif 275 | break; 276 | } 277 | case PPPERR_CONNECTTIME: { 278 | #if GSM_DEBUG 279 | ESP_LOGE(TAG,"status_cb: Max connect time reached"); 280 | #endif 281 | break; 282 | } 283 | case PPPERR_LOOPBACK: { 284 | #if GSM_DEBUG 285 | ESP_LOGE(TAG,"status_cb: Loopback detected"); 286 | #endif 287 | break; 288 | } 289 | default: { 290 | #if GSM_DEBUG 291 | ESP_LOGE(TAG,"status_cb: Unknown error code %d", err_code); 292 | #endif 293 | break; 294 | } 295 | } 296 | } 297 | 298 | // === Handle sending data to GSM modem === 299 | //------------------------------------------------------------------------------ 300 | static u32_t ppp_output_callback(ppp_pcb *pcb, u8_t *data, u32_t len, void *ctx) 301 | { 302 | uint32_t ret = uart_write_bytes(uart_num, (const char*)data, len); 303 | uart_wait_tx_done(uart_num, 10 / portTICK_RATE_MS); 304 | if (ret > 0) { 305 | xSemaphoreTake(pppos_mutex, PPPOSMUTEX_TIMEOUT); 306 | pppos_rx_count += ret; 307 | xSemaphoreGive(pppos_mutex); 308 | } 309 | return ret; 310 | } 311 | 312 | //--------------------------------------------------------- 313 | static void infoCommand(char *cmd, int cmdSize, char *info) 314 | { 315 | char buf[cmdSize+2]; 316 | memset(buf, 0, cmdSize+2); 317 | 318 | for (int i=0; i 0x7F))) buf[i] = '.'; 320 | else buf[i] = cmd[i]; 321 | if (buf[i] == '\0') break; 322 | } 323 | ESP_LOGI(TAG,"%s [%s]", info, buf); 324 | } 325 | 326 | //---------------------------------------------------------------------------------------------------------------------- 327 | static int atCmd_waitResponse(char * cmd, char *resp, char * resp1, int cmdSize, int timeout, char **response, int size) 328 | { 329 | char sresp[256] = {'\0'}; 330 | char data[256] = {'\0'}; 331 | int len, res = 1, idx = 0, tot = 0, timeoutCnt = 0; 332 | 333 | // ** Send command to GSM 334 | vTaskDelay(100 / portTICK_PERIOD_MS); 335 | uart_flush(uart_num); 336 | 337 | if (cmd != NULL) { 338 | if (cmdSize == -1) cmdSize = strlen(cmd); 339 | #if GSM_DEBUG 340 | infoCommand(cmd, cmdSize, "AT COMMAND:"); 341 | #endif 342 | uart_write_bytes(uart_num, (const char*)cmd, cmdSize); 343 | uart_wait_tx_done(uart_num, 100 / portTICK_RATE_MS); 344 | } 345 | 346 | if (response != NULL) { 347 | // Read GSM response into buffer 348 | char *pbuf = *response; 349 | len = uart_read_bytes(uart_num, (uint8_t*)data, 256, timeout / portTICK_RATE_MS); 350 | while (len > 0) { 351 | if ((tot+len) >= size) { 352 | char *ptemp = realloc(pbuf, size+512); 353 | if (ptemp == NULL) return 0; 354 | size += 512; 355 | pbuf = ptemp; 356 | } 357 | memcpy(pbuf+tot, data, len); 358 | tot += len; 359 | response[tot] = '\0'; 360 | len = uart_read_bytes(uart_num, (uint8_t*)data, 256, 100 / portTICK_RATE_MS); 361 | } 362 | *response = pbuf; 363 | return tot; 364 | } 365 | 366 | // ** Wait for and check the response 367 | idx = 0; 368 | while(1) 369 | { 370 | memset(data, 0, 256); 371 | len = 0; 372 | len = uart_read_bytes(uart_num, (uint8_t*)data, 256, 10 / portTICK_RATE_MS); 373 | if (len > 0) { 374 | for (int i=0; i= 0x20) && (data[i] < 0x80)) sresp[idx++] = data[i]; 377 | else sresp[idx++] = 0x2e; 378 | } 379 | } 380 | tot += len; 381 | } 382 | else { 383 | if (tot > 0) { 384 | // Check the response 385 | if (strstr(sresp, resp) != NULL) { 386 | #if GSM_DEBUG 387 | ESP_LOGI(TAG,"AT RESPONSE: [%s]", sresp); 388 | #endif 389 | break; 390 | } 391 | else { 392 | if (resp1 != NULL) { 393 | if (strstr(sresp, resp1) != NULL) { 394 | #if GSM_DEBUG 395 | ESP_LOGI(TAG,"AT RESPONSE (1): [%s]", sresp); 396 | #endif 397 | res = 2; 398 | break; 399 | } 400 | } 401 | // no match 402 | #if GSM_DEBUG 403 | ESP_LOGI(TAG,"AT BAD RESPONSE: [%s]", sresp); 404 | #endif 405 | res = 0; 406 | break; 407 | } 408 | } 409 | } 410 | 411 | timeoutCnt += 10; 412 | if (timeoutCnt > timeout) { 413 | // timeout 414 | #if GSM_DEBUG 415 | ESP_LOGE(TAG,"AT: TIMEOUT"); 416 | #endif 417 | res = 0; 418 | break; 419 | } 420 | } 421 | 422 | return res; 423 | } 424 | 425 | //------------------------------------ 426 | static void _disconnect(uint8_t rfOff) 427 | { 428 | int res = atCmd_waitResponse("AT\r\n", GSM_OK_Str, NULL, 4, 1000, NULL, 0); 429 | if (res == 1) { 430 | if (rfOff) { 431 | cmd_Reg.timeoutMs = 10000; 432 | res = atCmd_waitResponse("AT+CFUN=4\r\n", GSM_OK_Str, NULL, 11, 10000, NULL, 0); // disable RF function 433 | } 434 | return; 435 | } 436 | 437 | #if GSM_DEBUG 438 | ESP_LOGI(TAG,"ONLINE, DISCONNECTING..."); 439 | #endif 440 | vTaskDelay(1000 / portTICK_PERIOD_MS); 441 | uart_flush(uart_num); 442 | uart_write_bytes(uart_num, "+++", 3); 443 | uart_wait_tx_done(uart_num, 10 / portTICK_RATE_MS); 444 | vTaskDelay(1100 / portTICK_PERIOD_MS); 445 | 446 | int n = 0; 447 | res = atCmd_waitResponse("ATH\r\n", GSM_OK_Str, "NO CARRIER", 5, 3000, NULL, 0); 448 | while (res == 0) { 449 | n++; 450 | if (n > 10) { 451 | #if GSM_DEBUG 452 | ESP_LOGI(TAG,"STILL CONNECTED."); 453 | #endif 454 | n = 0; 455 | vTaskDelay(1000 / portTICK_PERIOD_MS); 456 | uart_flush(uart_num); 457 | uart_write_bytes(uart_num, "+++", 3); 458 | uart_wait_tx_done(uart_num, 10 / portTICK_RATE_MS); 459 | vTaskDelay(1000 / portTICK_PERIOD_MS); 460 | } 461 | vTaskDelay(100 / portTICK_PERIOD_MS); 462 | res = atCmd_waitResponse("ATH\r\n", GSM_OK_Str, "NO CARRIER", 5, 3000, NULL, 0); 463 | } 464 | vTaskDelay(100 / portTICK_PERIOD_MS); 465 | if (rfOff) { 466 | cmd_Reg.timeoutMs = 10000; 467 | res = atCmd_waitResponse("AT+CFUN=4\r\n", GSM_OK_Str, NULL, 11, 3000, NULL, 0); 468 | } 469 | #if GSM_DEBUG 470 | ESP_LOGI(TAG,"DISCONNECTED."); 471 | #endif 472 | } 473 | 474 | //---------------------------- 475 | static void enableAllInitCmd() 476 | { 477 | for (int idx = 0; idx < GSM_InitCmdsSize; idx++) { 478 | GSM_Init[idx]->skip = 0; 479 | } 480 | } 481 | 482 | /* 483 | * PPPoS TASK 484 | * Handles GSM initialization, disconnects and GSM modem responses 485 | */ 486 | //----------------------------- 487 | static void pppos_client_task() 488 | { 489 | xSemaphoreTake(pppos_mutex, PPPOSMUTEX_TIMEOUT); 490 | pppos_task_started = 1; 491 | xSemaphoreGive(pppos_mutex); 492 | 493 | // Allocate receive buffer 494 | char* data = (char*) malloc(BUF_SIZE); 495 | if (data == NULL) { 496 | #if GSM_DEBUG 497 | ESP_LOGE(TAG,"Failed to allocate data buffer."); 498 | #endif 499 | goto exit; 500 | } 501 | 502 | if (gpio_set_direction(UART_GPIO_TX, GPIO_MODE_OUTPUT)) goto exit; 503 | if (gpio_set_direction(UART_GPIO_RX, GPIO_MODE_INPUT)) goto exit; 504 | if (gpio_set_pull_mode(UART_GPIO_RX, GPIO_PULLUP_ONLY)) goto exit; 505 | 506 | char PPP_ApnATReq[sizeof(CONFIG_GSM_APN)+24]; 507 | 508 | uart_config_t uart_config = { 509 | .baud_rate = UART_BDRATE, 510 | .data_bits = UART_DATA_8_BITS, 511 | .parity = UART_PARITY_DISABLE, 512 | .stop_bits = UART_STOP_BITS_1, 513 | .flow_ctrl = UART_HW_FLOWCTRL_DISABLE 514 | }; 515 | 516 | //Configure UART1 parameters 517 | if (uart_param_config(uart_num, &uart_config)) goto exit; 518 | //Set UART1 pins(TX, RX, RTS, CTS) 519 | if (uart_set_pin(uart_num, UART_GPIO_TX, UART_GPIO_RX, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE)) goto exit; 520 | if (uart_driver_install(uart_num, BUF_SIZE * 2, BUF_SIZE * 2, 0, NULL, 0)) goto exit; 521 | 522 | // Set APN from config 523 | sprintf(PPP_ApnATReq, "AT+CGDCONT=1,\"IP\",\"%s\"\r\n", CONFIG_GSM_APN); 524 | cmd_APN.cmd = PPP_ApnATReq; 525 | cmd_APN.cmdSize = strlen(PPP_ApnATReq); 526 | 527 | _disconnect(1); // Disconnect if connected 528 | 529 | xSemaphoreTake(pppos_mutex, PPPOSMUTEX_TIMEOUT); 530 | pppos_tx_count = 0; 531 | pppos_rx_count = 0; 532 | gsm_status = GSM_STATE_FIRSTINIT; 533 | xSemaphoreGive(pppos_mutex); 534 | 535 | enableAllInitCmd(); 536 | 537 | while(1) 538 | { 539 | #if GSM_DEBUG 540 | ESP_LOGI(TAG,"GSM initialization start"); 541 | #endif 542 | vTaskDelay(500 / portTICK_PERIOD_MS); 543 | 544 | int gsmCmdIter = 0; 545 | int nfail = 0; 546 | // * GSM Initialization loop 547 | while(gsmCmdIter < GSM_InitCmdsSize) 548 | { 549 | if (GSM_Init[gsmCmdIter]->skip) { 550 | #if GSM_DEBUG 551 | infoCommand(GSM_Init[gsmCmdIter]->cmd, GSM_Init[gsmCmdIter]->cmdSize, "Skip command:"); 552 | #endif 553 | gsmCmdIter++; 554 | continue; 555 | } 556 | if (atCmd_waitResponse(GSM_Init[gsmCmdIter]->cmd, 557 | GSM_Init[gsmCmdIter]->cmdResponseOnOk, NULL, 558 | GSM_Init[gsmCmdIter]->cmdSize, 559 | GSM_Init[gsmCmdIter]->timeoutMs, NULL, 0) == 0) 560 | { 561 | // * No response or not as expected, start from first initialization command 562 | #if GSM_DEBUG 563 | ESP_LOGW(TAG,"Wrong response, restarting..."); 564 | #endif 565 | 566 | nfail++; 567 | if (nfail > 20) goto exit; 568 | 569 | vTaskDelay(3000 / portTICK_PERIOD_MS); 570 | gsmCmdIter = 0; 571 | continue; 572 | } 573 | 574 | if (GSM_Init[gsmCmdIter]->delayMs > 0) vTaskDelay(GSM_Init[gsmCmdIter]->delayMs / portTICK_PERIOD_MS); 575 | GSM_Init[gsmCmdIter]->skip = 1; 576 | if (GSM_Init[gsmCmdIter] == &cmd_Reg) GSM_Init[gsmCmdIter]->delayMs = 0; 577 | // Next command 578 | gsmCmdIter++; 579 | } 580 | 581 | #if GSM_DEBUG 582 | ESP_LOGI(TAG,"GSM initialized."); 583 | #endif 584 | 585 | xSemaphoreTake(pppos_mutex, PPPOSMUTEX_TIMEOUT); 586 | if (gsm_status == GSM_STATE_FIRSTINIT) { 587 | xSemaphoreGive(pppos_mutex); 588 | // ** After first successful initialization create PPP control block 589 | ppp = pppapi_pppos_create(&ppp_netif, 590 | ppp_output_callback, ppp_status_cb, NULL); 591 | 592 | if (ppp == NULL) { 593 | #if GSM_DEBUG 594 | ESP_LOGE(TAG, "Error initializing PPPoS"); 595 | #endif 596 | break; // end task 597 | } 598 | //netif_set_default(&ppp_netif); 599 | } 600 | else xSemaphoreGive(pppos_mutex); 601 | 602 | pppapi_set_default(ppp); 603 | pppapi_set_auth(ppp, PPPAUTHTYPE_PAP, PPP_User, PPP_Pass); 604 | //pppapi_set_auth(ppp, PPPAUTHTYPE_NONE, PPP_User, PPP_Pass); 605 | 606 | xSemaphoreTake(pppos_mutex, PPPOSMUTEX_TIMEOUT); 607 | gsm_status = GSM_STATE_IDLE; 608 | xSemaphoreGive(pppos_mutex); 609 | pppapi_connect(ppp, 0); 610 | 611 | // *** LOOP: Handle GSM modem responses & disconnects *** 612 | while(1) { 613 | // === Check if disconnect requested === 614 | xSemaphoreTake(pppos_mutex, PPPOSMUTEX_TIMEOUT); 615 | if (do_pppos_connect <= 0) { 616 | int end_task = do_pppos_connect; 617 | do_pppos_connect = 1; 618 | xSemaphoreGive(pppos_mutex); 619 | #if GSM_DEBUG 620 | printf("\r\n"); 621 | ESP_LOGI(TAG, "Disconnect requested."); 622 | #endif 623 | 624 | pppapi_close(ppp, 0); 625 | int gstat = 1; 626 | while (gsm_status != GSM_STATE_DISCONNECTED) { 627 | // Handle data received from GSM 628 | memset(data, 0, BUF_SIZE); 629 | int len = uart_read_bytes(uart_num, (uint8_t*)data, BUF_SIZE, 30 / portTICK_RATE_MS); 630 | if (len > 0) { 631 | pppos_input_tcpip(ppp, (u8_t*)data, len); 632 | xSemaphoreTake(pppos_mutex, PPPOSMUTEX_TIMEOUT); 633 | pppos_tx_count += len; 634 | xSemaphoreGive(pppos_mutex); 635 | } 636 | xSemaphoreTake(pppos_mutex, PPPOSMUTEX_TIMEOUT); 637 | gstat = gsm_status; 638 | xSemaphoreGive(pppos_mutex); 639 | } 640 | vTaskDelay(1000 / portTICK_PERIOD_MS); 641 | 642 | xSemaphoreTake(pppos_mutex, PPPOSMUTEX_TIMEOUT); 643 | uint8_t rfoff = gsm_rfOff; 644 | xSemaphoreGive(pppos_mutex); 645 | _disconnect(rfoff); // Disconnect GSM if still connected 646 | 647 | #if GSM_DEBUG 648 | ESP_LOGI(TAG, "Disconnected."); 649 | #endif 650 | 651 | gsmCmdIter = 0; 652 | enableAllInitCmd(); 653 | xSemaphoreTake(pppos_mutex, PPPOSMUTEX_TIMEOUT); 654 | gsm_status = GSM_STATE_IDLE; 655 | do_pppos_connect = 0; 656 | xSemaphoreGive(pppos_mutex); 657 | 658 | if (end_task < 0) goto exit; 659 | 660 | // === Wait for reconnect request === 661 | gstat = 0; 662 | while (gstat == 0) { 663 | vTaskDelay(100 / portTICK_PERIOD_MS); 664 | xSemaphoreTake(pppos_mutex, PPPOSMUTEX_TIMEOUT); 665 | gstat = do_pppos_connect; 666 | xSemaphoreGive(pppos_mutex); 667 | } 668 | #if GSM_DEBUG 669 | printf("\r\n"); 670 | ESP_LOGI(TAG, "Reconnect requested."); 671 | #endif 672 | break; 673 | } 674 | 675 | // === Check if disconnected === 676 | if (gsm_status == GSM_STATE_DISCONNECTED) { 677 | xSemaphoreGive(pppos_mutex); 678 | #if GSM_DEBUG 679 | printf("\r\n"); 680 | ESP_LOGE(TAG, "Disconnected, trying again..."); 681 | #endif 682 | pppapi_close(ppp, 0); 683 | 684 | enableAllInitCmd(); 685 | gsmCmdIter = 0; 686 | gsm_status = GSM_STATE_IDLE; 687 | vTaskDelay(10000 / portTICK_PERIOD_MS); 688 | break; 689 | } 690 | else xSemaphoreGive(pppos_mutex); 691 | 692 | // === Handle data received from GSM === 693 | memset(data, 0, BUF_SIZE); 694 | int len = uart_read_bytes(uart_num, (uint8_t*)data, BUF_SIZE, 30 / portTICK_RATE_MS); 695 | if (len > 0) { 696 | pppos_input_tcpip(ppp, (u8_t*)data, len); 697 | xSemaphoreTake(pppos_mutex, PPPOSMUTEX_TIMEOUT); 698 | pppos_tx_count += len; 699 | xSemaphoreGive(pppos_mutex); 700 | } 701 | 702 | } // Handle GSM modem responses & disconnects loop 703 | } // main task loop 704 | 705 | exit: 706 | if (data) free(data); // free data buffer 707 | if (ppp) ppp_free(ppp); 708 | 709 | xSemaphoreTake(pppos_mutex, PPPOSMUTEX_TIMEOUT); 710 | pppos_task_started = 0; 711 | gsm_status = GSM_STATE_FIRSTINIT; 712 | xSemaphoreGive(pppos_mutex); 713 | #if GSM_DEBUG 714 | ESP_LOGE(TAG, "PPPoS TASK TERMINATED"); 715 | #endif 716 | vTaskDelete(NULL); 717 | } 718 | 719 | //============= 720 | int ppposInit() 721 | { 722 | if (pppos_mutex != NULL) xSemaphoreTake(pppos_mutex, PPPOSMUTEX_TIMEOUT); 723 | do_pppos_connect = 1; 724 | int gstat = 0; 725 | int task_s = pppos_task_started; 726 | if (pppos_mutex != NULL) xSemaphoreGive(pppos_mutex); 727 | 728 | if (task_s == 0) { 729 | if (pppos_mutex == NULL) pppos_mutex = xSemaphoreCreateMutex(); 730 | if (pppos_mutex == NULL) return 0; 731 | 732 | if (tcpip_adapter_initialized == 0) { 733 | tcpip_adapter_init(); 734 | tcpip_adapter_initialized = 1; 735 | } 736 | xTaskCreate(&pppos_client_task, "pppos_client_task", PPPOS_CLIENT_STACK_SIZE, NULL, 10, NULL); 737 | while (task_s == 0) { 738 | vTaskDelay(10 / portTICK_RATE_MS); 739 | xSemaphoreTake(pppos_mutex, PPPOSMUTEX_TIMEOUT); 740 | task_s = pppos_task_started; 741 | xSemaphoreGive(pppos_mutex); 742 | } 743 | } 744 | 745 | while (gstat != 1) { 746 | vTaskDelay(10 / portTICK_RATE_MS); 747 | xSemaphoreTake(pppos_mutex, PPPOSMUTEX_TIMEOUT); 748 | gstat = gsm_status; 749 | task_s = pppos_task_started; 750 | xSemaphoreGive(pppos_mutex); 751 | if (task_s == 0) return 0; 752 | } 753 | 754 | return 1; 755 | } 756 | 757 | //=================================================== 758 | void ppposDisconnect(uint8_t end_task, uint8_t rfoff) 759 | { 760 | xSemaphoreTake(pppos_mutex, PPPOSMUTEX_TIMEOUT); 761 | int gstat = gsm_status; 762 | xSemaphoreGive(pppos_mutex); 763 | 764 | if (gstat == GSM_STATE_IDLE) return; 765 | 766 | gstat = 0; 767 | 768 | vTaskDelay(2000 / portTICK_RATE_MS); 769 | xSemaphoreTake(pppos_mutex, PPPOSMUTEX_TIMEOUT); 770 | if (end_task) do_pppos_connect = -1; 771 | else do_pppos_connect = 0; 772 | gsm_rfOff = rfoff; 773 | xSemaphoreGive(pppos_mutex); 774 | 775 | while (gstat == 0) { 776 | xSemaphoreTake(pppos_mutex, PPPOSMUTEX_TIMEOUT); 777 | gstat = do_pppos_connect; 778 | xSemaphoreGive(pppos_mutex); 779 | vTaskDelay(10 / portTICK_RATE_MS); 780 | } 781 | while (gstat != 0) { 782 | vTaskDelay(100 / portTICK_RATE_MS); 783 | xSemaphoreTake(pppos_mutex, PPPOSMUTEX_TIMEOUT); 784 | gstat = do_pppos_connect; 785 | xSemaphoreGive(pppos_mutex); 786 | } 787 | } 788 | 789 | //=================== 790 | int ppposStatus() 791 | { 792 | xSemaphoreTake(pppos_mutex, PPPOSMUTEX_TIMEOUT); 793 | int gstat = gsm_status; 794 | xSemaphoreGive(pppos_mutex); 795 | 796 | return gstat; 797 | } 798 | 799 | //======================================================== 800 | void getRxTxCount(uint32_t *rx, uint32_t *tx, uint8_t rst) 801 | { 802 | xSemaphoreTake(pppos_mutex, PPPOSMUTEX_TIMEOUT); 803 | *rx = pppos_rx_count; 804 | *tx = pppos_tx_count; 805 | if (rst) { 806 | pppos_rx_count = 0; 807 | pppos_tx_count = 0; 808 | } 809 | xSemaphoreGive(pppos_mutex); 810 | } 811 | 812 | //=================== 813 | void resetRxTxCount() 814 | { 815 | xSemaphoreTake(pppos_mutex, PPPOSMUTEX_TIMEOUT); 816 | pppos_rx_count = 0; 817 | pppos_tx_count = 0; 818 | xSemaphoreGive(pppos_mutex); 819 | } 820 | 821 | //============= 822 | int gsm_RFOff() 823 | { 824 | xSemaphoreTake(pppos_mutex, PPPOSMUTEX_TIMEOUT); 825 | int gstat = gsm_status; 826 | xSemaphoreGive(pppos_mutex); 827 | 828 | if (gstat != GSM_STATE_IDLE) return 0; 829 | 830 | uint8_t f = 1; 831 | char buf[64] = {'\0'}; 832 | char *pbuf = buf; 833 | int res = atCmd_waitResponse("AT+CFUN?\r\n", NULL, NULL, -1, 2000, &pbuf, 63); 834 | if (res > 0) { 835 | if (strstr(buf, "+CFUN: 4")) f = 0; 836 | } 837 | 838 | if (f) { 839 | cmd_Reg.timeoutMs = 500; 840 | return atCmd_waitResponse("AT+CFUN=4\r\n", GSM_OK_Str, NULL, 11, 10000, NULL, 0); // disable RF function 841 | } 842 | return 1; 843 | } 844 | 845 | //============ 846 | int gsm_RFOn() 847 | { 848 | xSemaphoreTake(pppos_mutex, PPPOSMUTEX_TIMEOUT); 849 | int gstat = gsm_status; 850 | xSemaphoreGive(pppos_mutex); 851 | 852 | if (gstat != GSM_STATE_IDLE) return 0; 853 | 854 | uint8_t f = 1; 855 | char buf[64] = {'\0'}; 856 | char *pbuf = buf; 857 | int res = atCmd_waitResponse("AT+CFUN?\r\n", NULL, NULL, -1, 2000, &pbuf, 63); 858 | if (res > 0) { 859 | if (strstr(buf, "+CFUN: 1")) f = 0; 860 | } 861 | 862 | if (f) { 863 | cmd_Reg.timeoutMs = 0; 864 | return atCmd_waitResponse("AT+CFUN=1\r\n", GSM_OK_Str, NULL, 11, 10000, NULL, 0); // disable RF function 865 | } 866 | return 1; 867 | } 868 | 869 | //-------------------- 870 | static int sms_ready() 871 | { 872 | if (ppposStatus() != GSM_STATE_IDLE) return 0; 873 | 874 | int res = atCmd_waitResponse("AT+CFUN?\r\n", "+CFUN: 1", NULL, -1, 1000, NULL, 0); 875 | if (res != 1) return 0; 876 | 877 | res = atCmd_waitResponse("AT+CMGF=1\r\n", GSM_OK_Str, NULL, -1, 1000, NULL, 0); 878 | if (res != 1) return 0; 879 | return 1; 880 | } 881 | 882 | //================================== 883 | int smsSend(char *smsnum, char *msg) 884 | { 885 | if (sms_ready() == 0) return 0; 886 | 887 | char buf[64]; 888 | int len = strlen(msg); 889 | 890 | sprintf(buf, "AT+CMGS=\"%s\"\r\n", smsnum); 891 | int res = atCmd_waitResponse(buf, "> ", NULL, -1, 1000, NULL, 0); 892 | if (res != 1) { 893 | res = atCmd_waitResponse("\x1B", GSM_OK_Str, NULL, 1, 1000, NULL, 0); 894 | return 0; 895 | } 896 | 897 | char *msgbuf = malloc(len+2); 898 | if (msgbuf == NULL) return 0; 899 | 900 | sprintf(msgbuf, "%s\x1A", msg); 901 | res = atCmd_waitResponse(msgbuf, "+CMGS: ", "ERROR", len+1, 40000, NULL, 0); 902 | if (res != 1) { 903 | res = atCmd_waitResponse("\x1B", GSM_OK_Str, NULL, 1, 1000, NULL, 0); 904 | res = 0; 905 | } 906 | 907 | free(msgbuf); 908 | return res; 909 | } 910 | 911 | // Get number of messages in buffer 912 | //------------------------------ 913 | static int numSMS(char *rbuffer) 914 | { 915 | if (strlen(rbuffer) == 0) return 0; 916 | 917 | char *msgidx = rbuffer; 918 | int nmsg = 0; 919 | while (1) { 920 | msgidx = strstr(msgidx, "+CMGL: "); 921 | if (msgidx == NULL) break; 922 | nmsg++; 923 | msgidx += 7; 924 | } 925 | return nmsg; 926 | } 927 | 928 | // Parse message at index idx to message structure 929 | //----------------------------------------------------- 930 | static int getSMS(char *rbuffer, int idx, SMS_Msg *msg) 931 | { 932 | // Find requested message pointer 933 | char *msgidx = rbuffer; 934 | int nmsg = 0; 935 | while (1) { 936 | msgidx = strstr(msgidx, "+CMGL: "); 937 | if (msgidx == NULL) break; 938 | nmsg++; 939 | msgidx += 7; 940 | if (nmsg == idx) break; 941 | } 942 | if (nmsg != idx) return 0; 943 | 944 | // Clear message structure 945 | memset(msg, 0, sizeof(SMS_Msg)); 946 | 947 | // Get message info 948 | char *pend = strstr(msgidx, "\r\n"); 949 | if (pend == NULL) return 0; 950 | 951 | int len = pend-msgidx; 952 | char hdr[len+4]; 953 | char buf[32]; 954 | 955 | memset(hdr, 0, len+4); 956 | memcpy(hdr, msgidx, len); 957 | hdr[len] = '\0'; 958 | 959 | // Get message body 960 | msgidx = pend + 2; 961 | pend = strstr(msgidx, "\r\n"); 962 | if (pend == NULL) return 0; 963 | 964 | // Allocate message body buffer and copy the data 965 | len = pend-msgidx; 966 | char *msgdata = calloc(len+2, 1); 967 | memcpy(msgdata, msgidx, len); 968 | msg->msg = msgdata; 969 | 970 | // Parse message info 971 | msgidx = hdr; 972 | pend = strstr(hdr, ",\""); 973 | int i = 1; 974 | while (pend != NULL) { 975 | len = pend-msgidx; 976 | if ((len < 32) && (len > 0)) { 977 | memset(buf, 0, 32); 978 | strncpy(buf, msgidx, len); 979 | buf[len] = '\0'; 980 | if (buf[len-1] == '"') buf[len-1] = '\0'; 981 | 982 | if (i == 1) msg->idx = (int)strtol(buf, NULL, 0); // message index 983 | else if (i == 2) strcpy(msg->stat, buf); // message status 984 | else if (i == 3) strcpy(msg->from, buf); // phone number of message sender 985 | else if (i == 5) strcpy(msg->time, buf); // the time when the message was sent 986 | } 987 | i++; 988 | msgidx = pend + 2; 989 | pend = strstr(msgidx, ",\""); 990 | if (pend == NULL) pend = strstr(msgidx, "\""); 991 | } 992 | if (strlen(msg->time) >= 20) { 993 | // Convert message time to time structure 994 | int hh,mm,ss,yy,mn,dd, tz; 995 | struct tm tm; 996 | sscanf(msg->time, "%u/%u/%u,%u:%u:%u%d", &yy, &mn, &dd, &hh, &mm, &ss, &tz); 997 | tm.tm_hour = hh; 998 | tm.tm_min = mm; 999 | tm.tm_sec = ss; 1000 | tm.tm_year = yy+100; 1001 | tm.tm_mon = mn; 1002 | tm.tm_mday = dd; 1003 | msg->time_value = mktime(&tm); // Linux time 1004 | msg->tz = tz/4; // time zone info 1005 | } 1006 | return nmsg; 1007 | } 1008 | 1009 | //=========================================== 1010 | void smsRead(SMS_Messages *SMSmesg, int sort) 1011 | { 1012 | SMSmesg->messages = NULL; 1013 | SMSmesg->nmsg = 0; 1014 | 1015 | if (sms_ready() == 0) return; 1016 | 1017 | int size = 512; 1018 | char *rbuffer = malloc(size); 1019 | if (rbuffer == NULL) return; 1020 | 1021 | int res = atCmd_waitResponse("AT+CMGL=\"ALL\"\r\n", NULL, NULL, -1, 2000, &rbuffer, size); 1022 | if (res <= 0) { 1023 | free(rbuffer); 1024 | return; 1025 | } 1026 | 1027 | int nmsg = numSMS(rbuffer); 1028 | if (nmsg > 0) { 1029 | // Allocate buffer for nmsg messages 1030 | SMS_Msg *messages = calloc(nmsg, sizeof(SMS_Msg)); 1031 | if (messages == NULL) { 1032 | free(rbuffer); 1033 | return; 1034 | } 1035 | SMS_Msg msg; 1036 | for (int i=0; i 0) { 1038 | memcpy(messages + (i * sizeof(SMS_Msg)), &msg, sizeof(SMS_Msg)); 1039 | SMSmesg->nmsg++; 1040 | } 1041 | } 1042 | if ((SMSmesg->nmsg) && (sort != 0)) { 1043 | SMS_Msg *smessages = calloc(SMSmesg->nmsg, sizeof(SMS_Msg)); 1044 | uint8_t mm[SMSmesg->nmsg]; 1045 | memset(mm, 1, SMSmesg->nmsg); 1046 | if (sort > 0) { 1047 | for (int idx = 0; idx < SMSmesg->nmsg; idx++) { 1048 | // find minimal time 1049 | time_t tm = 0x7FFFFFFF; 1050 | for (int i=0; inmsg; i++) { 1051 | if (mm[i]) { 1052 | if ((messages + (i * sizeof(SMS_Msg)))->time_value < tm) tm = (messages + (i * sizeof(SMS_Msg)))->time_value; 1053 | } 1054 | } 1055 | // Copy the message 1056 | for (int i=0; inmsg; i++) { 1057 | if (mm[i]) { 1058 | if ((messages + (i * sizeof(SMS_Msg)))->time_value == tm) { 1059 | memcpy(smessages + (idx * sizeof(SMS_Msg)), messages + (i * sizeof(SMS_Msg)), sizeof(SMS_Msg)); 1060 | mm[i] = 0; // mark as processed 1061 | break; 1062 | } 1063 | } 1064 | } 1065 | } 1066 | } 1067 | else { 1068 | for (int idx = 0; idx < SMSmesg->nmsg; idx++) { 1069 | // find maximal time 1070 | time_t tm = 0; 1071 | for (int i=0; inmsg; i++) { 1072 | if (mm[i]) { 1073 | if ((messages + (i * sizeof(SMS_Msg)))->time_value > tm) tm = (messages + (i * sizeof(SMS_Msg)))->time_value; 1074 | } 1075 | } 1076 | // Copy the message 1077 | for (int i=0; inmsg; i++) { 1078 | if (mm[i]) { 1079 | if ((messages + (i * sizeof(SMS_Msg)))->time_value == tm) { 1080 | memcpy(smessages + (idx * sizeof(SMS_Msg)), messages + (i * sizeof(SMS_Msg)), sizeof(SMS_Msg)); 1081 | mm[i] = 0; // mark as processed 1082 | break; 1083 | } 1084 | } 1085 | } 1086 | } 1087 | } 1088 | SMSmesg->messages = smessages; 1089 | free(messages); 1090 | } 1091 | else { 1092 | if (SMSmesg->nmsg) SMSmesg->messages = messages; 1093 | else free(messages); 1094 | } 1095 | } 1096 | free(rbuffer); 1097 | } 1098 | 1099 | //==================== 1100 | int smsDelete(int idx) 1101 | { 1102 | if (sms_ready() == 0) return 0; 1103 | 1104 | char buf[64]; 1105 | sprintf(buf,"AT+CMGD=%d\r\n", idx); 1106 | 1107 | return atCmd_waitResponse(buf, GSM_OK_Str, NULL, -1, 5000, NULL, 0); 1108 | } 1109 | 1110 | -------------------------------------------------------------------------------- /components/pppos/libGSM.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Author: LoBo (loboris@gmail.com, loboris.github) 3 | * 4 | */ 5 | 6 | 7 | #ifndef _LIBGSM_H_ 8 | #define _LIBGSM_H_ 9 | 10 | #define GSM_STATE_DISCONNECTED 0 11 | #define GSM_STATE_CONNECTED 1 12 | #define GSM_STATE_IDLE 89 13 | #define GSM_STATE_FIRSTINIT 98 14 | 15 | 16 | typedef struct 17 | { 18 | int idx; 19 | char *msg; 20 | char stat[32]; 21 | char from[32]; 22 | char time[32]; 23 | time_t time_value; 24 | int tz; 25 | }SMS_Msg; 26 | 27 | typedef struct 28 | { 29 | int nmsg; 30 | SMS_Msg *messages; 31 | }SMS_Messages; 32 | 33 | extern struct netif ppp_netif; 34 | 35 | /* 36 | * Create GSM/PPPoS task if not already created 37 | * Initialize GSM and connect to Internet 38 | * Handle all PPPoS requests 39 | * Disconnect/Reconnect from/to Internet on user request 40 | */ 41 | //============== 42 | int ppposInit(); 43 | 44 | /* 45 | * Disconnect from Internet 46 | * If 'end_task' = 1 also terminate GSM/PPPoS task 47 | * If 'rfoff' = 1, turns off GSM RF section to preserve power 48 | * If already disconnected, this function does nothing 49 | */ 50 | //==================================================== 51 | void ppposDisconnect(uint8_t end_task, uint8_t rfoff); 52 | 53 | /* 54 | * Get transmitted and received bytes count 55 | * If 'rst' = 1, resets the counters 56 | */ 57 | //========================================================= 58 | void getRxTxCount(uint32_t *rx, uint32_t *tx, uint8_t rst); 59 | 60 | /* 61 | * Resets transmitted and received bytes counters 62 | */ 63 | //==================== 64 | void resetRxTxCount(); 65 | 66 | /* 67 | * Get GSM/Task status 68 | * 69 | * Result: 70 | * GSM_STATE_DISCONNECTED (0) Disconnected from Internet 71 | * GSM_STATE_CONNECTED (1) Connected to Internet 72 | * GSM_STATE_IDLE (89) Disconnected from Internet, Task idle, waiting for reconnect request 73 | * GSM_STATE_FIRSTINIT (98) Task started, initializing PPPoS 74 | */ 75 | //================ 76 | int ppposStatus(); 77 | 78 | /* 79 | * Turn GSM RF Off 80 | */ 81 | //============== 82 | int gsm_RFOff(); 83 | 84 | /* 85 | * Turn GSM RF On 86 | */ 87 | //============= 88 | int gsm_RFOn(); 89 | 90 | /* 91 | * Send SMS 92 | * 93 | * Params: 94 | * smsnum: Pointer to phone number in international format (+) 95 | * msg: Pointer to message text 96 | */ 97 | //================================== 98 | int smsSend(char *smsnum, char *msg); 99 | 100 | /* 101 | * Read all SMS messages to 'SMS_Messages' structure 102 | */ 103 | //============================================ 104 | void smsRead(SMS_Messages *SMSmesg, int sort); 105 | 106 | /* 107 | * Delete the message at GSM message index 'idx' 108 | */ 109 | int smsDelete(int idx); 110 | 111 | 112 | #endif 113 | -------------------------------------------------------------------------------- /main/Kconfig: -------------------------------------------------------------------------------- 1 | menu "GSM PPPoS configuration" 2 | 3 | config GSM_DEBUG 4 | bool "Enable GSM debugging" 5 | default y 6 | help 7 | Show GSM debug messages 8 | 9 | config GSM_TX 10 | int "UART Output to GSM Module" 11 | default 21 12 | range 1 30 13 | help 14 | UART Tx pin, connected to GSM Module Rx pin. 15 | 16 | config GSM_RX 17 | int "UART Input from GSM Module" 18 | default 31 19 | range 1 38 20 | help 21 | UART Rx pin, connected to GSM Module Tx pin. 22 | 23 | config GSM_BDRATE 24 | int "UART Baud rate" 25 | default 115200 26 | help 27 | UART baudrate to comunicate with GSM module 28 | 29 | config GSM_INTERNET_USER 30 | string "Internet User" 31 | default "" 32 | help 33 | Network provider internet user. 34 | 35 | config GSM_INTERNET_PASSWORD 36 | string "Internet password" 37 | default "" 38 | help 39 | Network provider internet password 40 | 41 | config GSM_APN 42 | string "Internet APN" 43 | default "providerAPN" 44 | help 45 | Network provider's APN for internet access 46 | 47 | config GSM_USE_WIFI_AP 48 | bool "Start WiFi and AP" 49 | default n 50 | help 51 | Start WiFi as Acces Point and create WebServer task 52 | 53 | config GSM_SEND_SMS 54 | bool "Send SMS message" 55 | default n 56 | help 57 | Send SMS messages during example run 58 | 59 | config GSM_SMS_NUMBER 60 | string "SMS number" 61 | depends on GSM_SEND_SMS 62 | default "+1998765432" 63 | help 64 | SMS number for sending messages 65 | Enter the number in international format (+123999876543) 66 | 67 | config GSM_SMS_INTERVAL 68 | int "SMS message interval" 69 | depends on GSM_SEND_SMS 70 | default 300000 71 | range 180000 3600000 72 | help 73 | Set SMS message interval in mili seconds 74 | 75 | endmenu 76 | 77 | -------------------------------------------------------------------------------- /main/component.mk: -------------------------------------------------------------------------------- 1 | # 2 | # "main" pseudo-component makefile. 3 | # 4 | # (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.) 5 | 6 | # embed files from the "certs" directory as binary data symbols 7 | # in the app 8 | COMPONENT_EMBED_TXTFILES := server_root_cert.pem 9 | 10 | 11 | -------------------------------------------------------------------------------- /main/pppos_client_main.c: -------------------------------------------------------------------------------- 1 | /* PPPoS Client Example with GSM 2 | * (tested with SIM800) 3 | * Author: LoBo (loboris@gmail.com, loboris.github) 4 | 5 | This example code is in the Public Domain (or CC0 licensed, at your option.) 6 | 7 | Unless required by applicable law or agreed to in writing, this 8 | software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 9 | CONDITIONS OF ANY KIND, either express or implied. 10 | */ 11 | 12 | 13 | #include 14 | #include "freertos/FreeRTOS.h" 15 | #include "freertos/task.h" 16 | #include "freertos/event_groups.h" 17 | #include "esp_system.h" 18 | #include "esp_wifi.h" 19 | #include "esp_event_loop.h" 20 | #include "esp_log.h" 21 | #include "nvs_flash.h" 22 | #include "freertos/semphr.h" 23 | 24 | #include "driver/uart.h" 25 | 26 | #include "netif/ppp/pppos.h" 27 | #include "netif/ppp/ppp.h" 28 | #include "lwip/err.h" 29 | #include "lwip/sockets.h" 30 | #include "lwip/sys.h" 31 | #include "lwip/netdb.h" 32 | #include "lwip/dns.h" 33 | #include "lwip/pppapi.h" 34 | 35 | #include "mbedtls/platform.h" 36 | #include "mbedtls/net.h" 37 | #include "mbedtls/esp_debug.h" 38 | #include "mbedtls/ssl.h" 39 | #include "mbedtls/entropy.h" 40 | #include "mbedtls/ctr_drbg.h" 41 | #include "mbedtls/error.h" 42 | #include "mbedtls/certs.h" 43 | 44 | #include 45 | #include 46 | 47 | #include "apps/sntp/sntp.h" 48 | #include "cJSON.h" 49 | 50 | #include "libGSM.h" 51 | 52 | #ifdef CONFIG_GSM_USE_WIFI_AP 53 | #include "lwip/api.h" 54 | #include "lwip/err.h" 55 | #include "lwip/netdb.h" 56 | #endif 57 | 58 | #define EXAMPLE_TASK_PAUSE 300 // pause between task runs in seconds 59 | #define TASK_SEMAPHORE_WAIT 140000 // time to wait for mutex in miliseconds 60 | 61 | QueueHandle_t http_mutex; 62 | 63 | static const char *TIME_TAG = "[SNTP]"; 64 | static const char *HTTP_TAG = "[HTTP]"; 65 | static const char *HTTPS_TAG = "[HTTPS]"; 66 | 67 | #ifdef CONFIG_GSM_SEND_SMS 68 | static const char *SMS_TAG = "[SMS]"; 69 | #endif 70 | 71 | #ifdef CONFIG_GSM_USE_WIFI_AP 72 | static const char *WEBSRV_TAG = "[WebServer]"; 73 | const static char http_html_hdr[] = "HTTP/1.1 200 OK\nContent-type: text/html\n\n"; 74 | const static char http_index_html[] = "" 75 | "\n" 76 | "\n" 77 | " \n" 78 | " \n" 82 | "HELLO ESP32\n" 83 | "\n" 84 | "\n" 85 | "

Hello World, from ESP32!

\n"; 86 | #endif 87 | 88 | // =============================================================================================== 89 | // ==== Http/Https get requests ================================================================== 90 | // =============================================================================================== 91 | 92 | // Constants that aren't configurable in menuconfig 93 | #define WEB_SERVER "loboris.eu" 94 | #define WEB_PORT 80 95 | #define WEB_URL "http://loboris.eu/ESP32/info.txt" 96 | #define WEB_URL1 "http://loboris.eu" 97 | 98 | #define SSL_WEB_SERVER "www.howsmyssl.com" 99 | #define SSL_WEB_URL "https://www.howsmyssl.com/a/check" 100 | #define SSL_WEB_PORT "443" 101 | 102 | static const char *REQUEST = "GET " WEB_URL " HTTP/1.1\r\n" 103 | "Host: "WEB_SERVER"\r\n" 104 | "User-Agent: esp-idf/1.0 esp32\r\n" 105 | "\r\n"; 106 | 107 | static const char *REQUEST1 = "GET " WEB_URL1 " HTTP/1.1\r\n" 108 | "Host: "WEB_SERVER"\r\n" 109 | "User-Agent: esp-idf/1.0 esp32\r\n" 110 | "\r\n"; 111 | 112 | static const char *SSL_REQUEST = "GET " SSL_WEB_URL " HTTP/1.1\r\n" 113 | "Host: "SSL_WEB_SERVER"\r\n" 114 | "User-Agent: esp-idf/1.0 esp32\r\n" 115 | "\r\n"; 116 | 117 | /* Root cert for howsmyssl.com, taken from server_root_cert.pem 118 | 119 | The PEM file was extracted from the output of this command: 120 | openssl s_client -showcerts -connect www.howsmyssl.com:443 child; 136 | while (subitem) 137 | { 138 | printf("%s = ", subitem->string); 139 | if (subitem->type == cJSON_String) printf("%s\r\n", subitem->valuestring); 140 | else if (subitem->type == cJSON_Number) printf("%d\r\n", subitem->valueint); 141 | else if (subitem->type == cJSON_False) printf("False\r\n"); 142 | else if (subitem->type == cJSON_True) printf("True\r\n"); 143 | else if (subitem->type == cJSON_NULL) printf("NULL\r\n"); 144 | else if (subitem->type == cJSON_Object) { 145 | printf("{Object}\r\n"); 146 | // handle subitem 147 | if (subitem->child) { 148 | cJSON *subitemData = cJSON_GetObjectItem(subitem,subitem->string); 149 | if (subitemData) { 150 | level++; 151 | parse_object(subitemData); 152 | level--; 153 | } 154 | } 155 | } 156 | else if (subitem->type == cJSON_Array) { 157 | int arr_count = cJSON_GetArraySize(subitem); 158 | printf("[Array] of %d items\r\n", arr_count); 159 | int n; 160 | for (n = 0; n < 3; n++) { 161 | // Get the JSON element and then get the values as before 162 | cJSON *arritem = cJSON_GetArrayItem(subitem, n); 163 | if ((arritem) && (arritem->valuestring)) printf(" %s\n", arritem->valuestring); 164 | else break; 165 | } 166 | if (arr_count > 3 ) printf(" + %d more...\r\n", arr_count-3); 167 | } 168 | else printf("[?]\r\n"); 169 | 170 | subitem=subitem->next; 171 | } 172 | } 173 | 174 | //============================================ 175 | static void https_get_task(void *pvParameters) 176 | { 177 | if (!(xSemaphoreTake(http_mutex, TASK_SEMAPHORE_WAIT))) { 178 | ESP_LOGE(HTTPS_TAG, "*** ERROR: CANNOT GET MUTEX ***n"); 179 | while (1) { 180 | vTaskDelay(10000 / portTICK_PERIOD_MS); 181 | } 182 | } 183 | 184 | char buf[512]; 185 | char *buffer; 186 | int ret, flags, len, rlen=0, totlen=0; 187 | 188 | buffer = malloc(8192); 189 | if (!buffer) { 190 | xSemaphoreGive(http_mutex); 191 | ESP_LOGE(HTTPS_TAG, "*** ERROR allocating receive buffer ***"); 192 | while (1) { 193 | vTaskDelay(10000 / portTICK_PERIOD_MS); 194 | } 195 | } 196 | 197 | mbedtls_entropy_context entropy; 198 | mbedtls_ctr_drbg_context ctr_drbg; 199 | mbedtls_ssl_context ssl; 200 | mbedtls_x509_crt cacert; 201 | mbedtls_ssl_config conf; 202 | mbedtls_net_context server_fd; 203 | 204 | mbedtls_ssl_init(&ssl); 205 | mbedtls_x509_crt_init(&cacert); 206 | mbedtls_ctr_drbg_init(&ctr_drbg); 207 | ESP_LOGI(HTTPS_TAG, "Seeding the random number generator"); 208 | 209 | mbedtls_ssl_config_init(&conf); 210 | 211 | mbedtls_entropy_init(&entropy); 212 | if((ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, 213 | NULL, 0)) != 0) 214 | { 215 | ESP_LOGE(HTTPS_TAG, "mbedtls_ctr_drbg_seed returned %d", ret); 216 | xSemaphoreGive(http_mutex); 217 | while (1) { 218 | vTaskDelay(10000 / portTICK_PERIOD_MS); 219 | } 220 | } 221 | 222 | ESP_LOGI(HTTPS_TAG, "Loading the CA root certificate..."); 223 | 224 | ret = mbedtls_x509_crt_parse(&cacert, server_root_cert_pem_start, 225 | server_root_cert_pem_end-server_root_cert_pem_start); 226 | 227 | if(ret < 0) 228 | { 229 | ESP_LOGE(HTTPS_TAG, "mbedtls_x509_crt_parse returned -0x%x\n\n", -ret); 230 | xSemaphoreGive(http_mutex); 231 | while (1) { 232 | vTaskDelay(10000 / portTICK_PERIOD_MS); 233 | } 234 | } 235 | 236 | ESP_LOGI(HTTPS_TAG, "Setting hostname for TLS session..."); 237 | 238 | // Host name set here should match CN in server certificate 239 | if((ret = mbedtls_ssl_set_hostname(&ssl, WEB_SERVER)) != 0) 240 | { 241 | ESP_LOGE(HTTPS_TAG, "mbedtls_ssl_set_hostname returned -0x%x", -ret); 242 | xSemaphoreGive(http_mutex); 243 | while (1) { 244 | vTaskDelay(10000 / portTICK_PERIOD_MS); 245 | } 246 | } 247 | 248 | ESP_LOGI(HTTPS_TAG, "Setting up the SSL/TLS structure..."); 249 | 250 | if((ret = mbedtls_ssl_config_defaults(&conf, 251 | MBEDTLS_SSL_IS_CLIENT, 252 | MBEDTLS_SSL_TRANSPORT_STREAM, 253 | MBEDTLS_SSL_PRESET_DEFAULT)) != 0) 254 | { 255 | ESP_LOGE(HTTPS_TAG, "mbedtls_ssl_config_defaults returned %d", ret); 256 | goto exit; 257 | } 258 | 259 | // MBEDTLS_SSL_VERIFY_OPTIONAL is bad for security, in this example it will print 260 | // a warning if CA verification fails but it will continue to connect. 261 | // You should consider using MBEDTLS_SSL_VERIFY_REQUIRED in your own code. 262 | mbedtls_ssl_conf_authmode(&conf, MBEDTLS_SSL_VERIFY_OPTIONAL); 263 | mbedtls_ssl_conf_ca_chain(&conf, &cacert, NULL); 264 | mbedtls_ssl_conf_rng(&conf, mbedtls_ctr_drbg_random, &ctr_drbg); 265 | #ifdef CONFIG_MBEDTLS_DEBUG 266 | mbedtls_esp_enable_debug_log(&conf, 4); 267 | #endif 268 | 269 | if ((ret = mbedtls_ssl_setup(&ssl, &conf)) != 0) 270 | { 271 | ESP_LOGE(HTTPS_TAG, "mbedtls_ssl_setup returned -0x%x\n\n", -ret); 272 | goto exit; 273 | } 274 | 275 | goto start; 276 | 277 | while(1) { 278 | if (!(xSemaphoreTake(http_mutex, TASK_SEMAPHORE_WAIT))) { 279 | ESP_LOGE(HTTPS_TAG, "===== ERROR: CANNOT GET MUTEX ===================================\n"); 280 | vTaskDelay(30000 / portTICK_PERIOD_MS); 281 | continue; 282 | } 283 | start: 284 | // ** We must be connected to Internet 285 | if (ppposInit() == 0) goto finished; 286 | 287 | ESP_LOGI(HTTPS_TAG, "===== HTTPS GET REQUEST =========================================\n"); 288 | //netif_set_default(&ppp_netif); 289 | 290 | mbedtls_net_init(&server_fd); 291 | 292 | ESP_LOGI(HTTPS_TAG, "Connecting to %s:%s...", SSL_WEB_SERVER, SSL_WEB_PORT); 293 | 294 | if ((ret = mbedtls_net_connect(&server_fd, SSL_WEB_SERVER, 295 | SSL_WEB_PORT, MBEDTLS_NET_PROTO_TCP)) != 0) 296 | { 297 | ESP_LOGE(HTTPS_TAG, "mbedtls_net_connect returned -%x", -ret); 298 | goto exit; 299 | } 300 | 301 | ESP_LOGI(HTTPS_TAG, "Connected."); 302 | 303 | mbedtls_ssl_set_bio(&ssl, &server_fd, mbedtls_net_send, mbedtls_net_recv, NULL); 304 | 305 | ESP_LOGI(HTTPS_TAG, "Performing the SSL/TLS handshake..."); 306 | 307 | while ((ret = mbedtls_ssl_handshake(&ssl)) != 0) 308 | { 309 | if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) 310 | { 311 | ESP_LOGE(HTTPS_TAG, "mbedtls_ssl_handshake returned -0x%x", -ret); 312 | goto exit; 313 | } 314 | } 315 | 316 | ESP_LOGI(HTTPS_TAG, "Verifying peer X.509 certificate..."); 317 | 318 | if ((flags = mbedtls_ssl_get_verify_result(&ssl)) != 0) 319 | { 320 | // In real life, we probably want to close connection if ret != 0 321 | ESP_LOGW(HTTPS_TAG, "Failed to verify peer certificate!"); 322 | bzero(buf, sizeof(buf)); 323 | mbedtls_x509_crt_verify_info(buf, sizeof(buf), " ! ", flags); 324 | ESP_LOGW(HTTPS_TAG, "verification info: %s", buf); 325 | } 326 | else { 327 | ESP_LOGI(HTTPS_TAG, "Certificate verified."); 328 | } 329 | 330 | ESP_LOGI(HTTPS_TAG, "Writing HTTP request..."); 331 | 332 | while((ret = mbedtls_ssl_write(&ssl, (const unsigned char *)SSL_REQUEST, strlen(SSL_REQUEST))) <= 0) 333 | { 334 | if(ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) 335 | { 336 | ESP_LOGE(HTTPS_TAG, "mbedtls_ssl_write returned -0x%x", -ret); 337 | goto exit; 338 | } 339 | } 340 | 341 | len = ret; 342 | ESP_LOGI(HTTPS_TAG, "%d bytes written", len); 343 | ESP_LOGI(HTTPS_TAG, "Reading HTTP response..."); 344 | 345 | rlen = 0; 346 | totlen = 0; 347 | do 348 | { 349 | len = sizeof(buf) - 1; 350 | bzero(buf, sizeof(buf)); 351 | ret = mbedtls_ssl_read(&ssl, (unsigned char *)buf, len); 352 | 353 | if(ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE) 354 | continue; 355 | 356 | if(ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) { 357 | ret = 0; 358 | break; 359 | } 360 | 361 | if(ret < 0) 362 | { 363 | ESP_LOGE(HTTPS_TAG, "mbedtls_ssl_read returned -0x%x", -ret); 364 | break; 365 | } 366 | 367 | if(ret == 0) 368 | { 369 | ESP_LOGI(HTTPS_TAG, "connection closed"); 370 | break; 371 | } 372 | 373 | len = ret; 374 | //ESP_LOGI(HTTPS_TAG, "%d bytes read", len); 375 | totlen += len; 376 | if ((rlen + len) < 8192) { 377 | memcpy(buffer+rlen, buf, len); 378 | rlen += len; 379 | } 380 | } while(1); 381 | 382 | mbedtls_ssl_close_notify(&ssl); 383 | 384 | exit: 385 | mbedtls_ssl_session_reset(&ssl); 386 | mbedtls_net_free(&server_fd); 387 | 388 | ESP_LOGI(HTTPS_TAG, "%d bytes read, %d in buffer", totlen, rlen); 389 | if(ret != 0) 390 | { 391 | mbedtls_strerror(ret, buf, 100); 392 | ESP_LOGE(HTTPS_TAG, "Last error was: -0x%x - %s", -ret, buf); 393 | } 394 | 395 | buffer[rlen] = '\0'; 396 | char *json_ptr = strstr(buffer, "{\"given_cipher_suites\":"); 397 | char *hdr_end_ptr = strstr(buffer, "\r\n\r\n"); 398 | if (hdr_end_ptr) { 399 | *hdr_end_ptr = '\0'; 400 | printf("Header:\r\n-------\r\n%s\r\n-------\r\n", buffer); 401 | } 402 | if (json_ptr) { 403 | ESP_LOGI(HTTPS_TAG, "JSON data received."); 404 | //printf("JSON: [\n%s]\n", json_ptr); 405 | //ToDo: Check json in latest esp-idf 406 | cJSON *root = cJSON_Parse(json_ptr); 407 | ESP_LOGI(HTTPS_TAG, "JSON string parsed."); 408 | if (root) { 409 | ESP_LOGI(HTTPS_TAG, "parsing JSON data:"); 410 | level = 1; 411 | parse_object(root); 412 | cJSON_Delete(root); 413 | } 414 | } 415 | 416 | // We can disconnect from Internet now and turn off RF to save power 417 | //ppposDisconnect(0, 1); 418 | 419 | finished: 420 | ESP_LOGI(HTTPS_TAG, "Waiting %d sec...", EXAMPLE_TASK_PAUSE); 421 | ESP_LOGI(HTTPS_TAG, "=================================================================\n\n"); 422 | xSemaphoreGive(http_mutex); 423 | for(int countdown = EXAMPLE_TASK_PAUSE; countdown >= 0; countdown--) { 424 | vTaskDelay(1000 / portTICK_PERIOD_MS); 425 | } 426 | } 427 | } 428 | 429 | 430 | //=========================================== 431 | static void http_get_task(void *pvParameters) 432 | { 433 | if (!(xSemaphoreTake(http_mutex, TASK_SEMAPHORE_WAIT))) { 434 | ESP_LOGE(HTTP_TAG, "*** ERROR: CANNOT GET MUTEX ***n"); 435 | while (1) { 436 | vTaskDelay(10000 / portTICK_PERIOD_MS); 437 | } 438 | } 439 | 440 | const struct addrinfo hints = { 441 | .ai_family = AF_INET, 442 | .ai_socktype = SOCK_STREAM, 443 | }; 444 | struct addrinfo *res; 445 | struct in_addr *addr; 446 | int s, r; 447 | char recv_buf[128]; 448 | char *buffer; 449 | int rlen=0, totlen=0; 450 | 451 | buffer = malloc(2048); 452 | if (!buffer) { 453 | ESP_LOGE(HTTPS_TAG, "*** ERROR allocating receive buffer ***"); 454 | xSemaphoreGive(http_mutex); 455 | while (1) { 456 | vTaskDelay(10000 / portTICK_PERIOD_MS); 457 | } 458 | } 459 | 460 | goto start; 461 | 462 | while(1) { 463 | if (!(xSemaphoreTake(http_mutex, TASK_SEMAPHORE_WAIT))) { 464 | ESP_LOGE(HTTP_TAG, "===== ERROR: CANNOT GET MUTEX ==================================\n"); 465 | vTaskDelay(30000 / portTICK_PERIOD_MS); 466 | continue; 467 | } 468 | start: 469 | // ** We must be connected to Internet 470 | if (ppposInit() == 0) goto finished; 471 | 472 | ESP_LOGI(HTTP_TAG, "===== HTTP GET REQUEST =========================================\n"); 473 | 474 | //netif_set_default(&ppp_netif); 475 | int err = getaddrinfo(WEB_SERVER, "80", &hints, &res); 476 | 477 | if(err != 0 || res == NULL) { 478 | ESP_LOGE(HTTP_TAG, "DNS lookup failed err=%d res=%p", err, res); 479 | xSemaphoreGive(http_mutex); 480 | vTaskDelay(1000 / portTICK_PERIOD_MS); 481 | continue; 482 | } 483 | 484 | /* Code to print the resolved IP. 485 | 486 | Note: inet_ntoa is non-reentrant, look at ipaddr_ntoa_r for "real" code */ 487 | addr = &((struct sockaddr_in *)res->ai_addr)->sin_addr; 488 | ESP_LOGI(HTTP_TAG, "DNS lookup succeeded. IP=%s", inet_ntoa(*addr)); 489 | 490 | s = socket(res->ai_family, res->ai_socktype, 0); 491 | if(s < 0) { 492 | ESP_LOGE(HTTP_TAG, "... Failed to allocate socket."); 493 | freeaddrinfo(res); 494 | xSemaphoreGive(http_mutex); 495 | vTaskDelay(1000 / portTICK_PERIOD_MS); 496 | continue; 497 | } 498 | ESP_LOGI(HTTP_TAG, "... allocated socket\r\n"); 499 | 500 | if(connect(s, res->ai_addr, res->ai_addrlen) != 0) { 501 | ESP_LOGE(HTTP_TAG, "... socket connect failed errno=%d", errno); 502 | close(s); 503 | freeaddrinfo(res); 504 | xSemaphoreGive(http_mutex); 505 | vTaskDelay(4000 / portTICK_PERIOD_MS); 506 | continue; 507 | } 508 | 509 | ESP_LOGI(HTTP_TAG, "... connected"); 510 | freeaddrinfo(res); 511 | 512 | if (write(s, REQUEST, strlen(REQUEST)) < 0) { 513 | ESP_LOGE(HTTP_TAG, "... socket send failed"); 514 | close(s); 515 | xSemaphoreGive(http_mutex); 516 | vTaskDelay(4000 / portTICK_PERIOD_MS); 517 | continue; 518 | } 519 | ESP_LOGI(HTTP_TAG, "... socket send success"); 520 | ESP_LOGI(HTTP_TAG, "... reading HTTP response..."); 521 | 522 | memset(buffer, 0, 2048); 523 | /* Read HTTP response */ 524 | int opt = 500; 525 | int first_block = 1; 526 | char *cont_len = NULL; 527 | int clen = 0; 528 | rlen = 0; 529 | totlen = 0; 530 | char *hdr_end_ptr = NULL; 531 | do { 532 | bzero(recv_buf, sizeof(recv_buf)); 533 | r = read(s, recv_buf, sizeof(recv_buf)-1); 534 | totlen += r; 535 | if ((rlen + r) < 2048) { 536 | memcpy(buffer+rlen, recv_buf, r); 537 | rlen += r; 538 | buffer[rlen] = '\0'; 539 | if (clen == 0) { 540 | cont_len = strstr(buffer, "Content-Length: "); 541 | if (cont_len) { 542 | cont_len += 16; 543 | if (strstr(cont_len, "\r\n")) { 544 | char slen[16] = {0}; 545 | memcpy(slen, cont_len, strstr(cont_len, "\r\n")-cont_len); 546 | clen = atoi(slen); 547 | } 548 | } 549 | } 550 | if (hdr_end_ptr == NULL) { 551 | hdr_end_ptr = strstr(buffer, "\r\n\r\n"); 552 | if (hdr_end_ptr) { 553 | *hdr_end_ptr = '\0'; 554 | hdr_end_ptr += 4; 555 | } 556 | } 557 | else if (clen > 0) { 558 | if (strlen(hdr_end_ptr) >= clen) break; 559 | } 560 | } 561 | if (first_block) { 562 | lwip_setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &opt, sizeof(int)); 563 | first_block = 0; 564 | } 565 | } while(r > 0); 566 | 567 | if (hdr_end_ptr) { 568 | printf("Header:\r\n-------\r\n%s\r\n-------\r\n", buffer); 569 | printf("Data:\r\n-----\r\n%s\r\n-----\r\n", hdr_end_ptr); 570 | } 571 | ESP_LOGI(HTTP_TAG, "... done reading from socket. %d bytes read, %d in buffer, errno=%d\r\n", totlen, rlen, errno); 572 | close(s); 573 | 574 | // We can disconnect from Internet now and turn off RF to save power 575 | //ppposDisconnect(0, 1); 576 | 577 | finished: 578 | ESP_LOGI(HTTP_TAG, "Waiting %d sec...", EXAMPLE_TASK_PAUSE); 579 | ESP_LOGI(HTTP_TAG, "================================================================\n\n"); 580 | xSemaphoreGive(http_mutex); 581 | for(int countdown = EXAMPLE_TASK_PAUSE; countdown >= 0; countdown--) { 582 | vTaskDelay(1000 / portTICK_PERIOD_MS); 583 | } 584 | } 585 | } 586 | 587 | #ifdef CONFIG_GSM_SEND_SMS 588 | 589 | //====================================== 590 | static void sms_task(void *pvParameters) 591 | { 592 | if (!(xSemaphoreTake(http_mutex, TASK_SEMAPHORE_WAIT))) { 593 | ESP_LOGE(SMS_TAG, "*** ERROR: CANNOT GET MUTEX ***n"); 594 | while (1) { 595 | vTaskDelay(10000 / portTICK_PERIOD_MS); 596 | } 597 | } 598 | 599 | SMS_Messages messages; 600 | uint32_t sms_time = 0; 601 | char buf[160]; 602 | 603 | goto start; 604 | 605 | while(1) { 606 | if (!(xSemaphoreTake(http_mutex, TASK_SEMAPHORE_WAIT))) { 607 | ESP_LOGE(SMS_TAG, "===== ERROR: CANNOT GET MUTEX ==================================\n"); 608 | vTaskDelay(30000 / portTICK_PERIOD_MS); 609 | continue; 610 | } 611 | start: 612 | ESP_LOGI(SMS_TAG, "===== SMS TEST =================================================\n"); 613 | 614 | // ** For SMS operations we have to off line ** 615 | ppposDisconnect(0, 0); 616 | gsm_RFOn(); // Turn on RF if it was turned off 617 | vTaskDelay(2000 / portTICK_RATE_MS); 618 | 619 | if (clock() > sms_time) { 620 | if (smsSend(CONFIG_GSM_SMS_NUMBER, "Hi from ESP32 via GSM\rThis is the test message.") == 1) { 621 | printf("SMS sent successfully\r\n"); 622 | } 623 | else { 624 | printf("SMS send failed\r\n"); 625 | } 626 | sms_time = clock() + CONFIG_GSM_SMS_INTERVAL; // next sms send time 627 | } 628 | 629 | smsRead(&messages, -1); 630 | if (messages.nmsg) { 631 | printf("\r\nReceived messages: %d\r\n", messages.nmsg); 632 | SMS_Msg *msg; 633 | for (int i=0; itime_value ); 637 | printf("-------------------------------------------\r\n"); 638 | printf("Message #%d: idx=%d, from: %s, status: %s, time: %s, tz=GMT+%d, timestamp: %s\r\n", 639 | i+1, msg->idx, msg->from, msg->stat, msg->time, msg->tz, asctime(timeinfo)); 640 | printf("Text: [\r\n%s\r\n]\r\n\r\n", msg->msg); 641 | 642 | // Check if SMS text contains known command 643 | if (strstr(msg->msg, "Esp32 info") == msg->msg) { 644 | char buffer[80]; 645 | time_t rawtime; 646 | time(&rawtime); 647 | timeinfo = localtime( &rawtime ); 648 | strftime(buffer,80,"%x %H:%M:%S", timeinfo); 649 | sprintf(buf, "Hi, %s\rMy time is now\r%s", msg->from, buffer); 650 | if (smsSend(CONFIG_GSM_SMS_NUMBER, buf) == 1) { 651 | printf("Response sent successfully\r\n"); 652 | } 653 | else { 654 | printf("Response send failed\r\n"); 655 | } 656 | } 657 | // Free allocated message text buffer 658 | if (msg->msg) free(msg->msg); 659 | if ((i+1) == messages.nmsg) { 660 | printf("Delete message at index %d\r\n", msg->idx); 661 | if (smsDelete(msg->idx) == 0) printf("Delete ERROR\r\n"); 662 | else printf("Delete OK\r\n"); 663 | } 664 | } 665 | free(messages.messages); 666 | } 667 | else printf("\r\nNo messages\r\n"); 668 | 669 | // ** We can turn off GSM RF to save power 670 | gsm_RFOff(); 671 | // ** We can now go back on line, or stay off line ** 672 | //ppposInit(); 673 | 674 | ESP_LOGI(SMS_TAG, "Waiting %d sec...", EXAMPLE_TASK_PAUSE); 675 | ESP_LOGI(SMS_TAG, "================================================================\n\n"); 676 | 677 | xSemaphoreGive(http_mutex); 678 | for(int countdown = EXAMPLE_TASK_PAUSE; countdown >= 0; countdown--) { 679 | vTaskDelay(1000 / portTICK_PERIOD_MS); 680 | } 681 | } 682 | } 683 | #endif 684 | 685 | 686 | #ifdef CONFIG_GSM_USE_WIFI_AP 687 | 688 | // ==== WiFi handling & simple WebServer ==================================================== 689 | 690 | // FreeRTOS event group to signal when we are connected & ready to make a request 691 | static EventGroupHandle_t wifi_event_group; 692 | 693 | // The event group allows multiple bits for each event, 694 | const int CONNECTED_BIT = BIT0; 695 | const int APSTARTED_BIT = BIT1; 696 | 697 | //------------------------------------------------------------------- 698 | esp_err_t esp32_wifi_eventHandler(void *ctx, system_event_t *event) { 699 | switch(event->event_id) { 700 | case SYSTEM_EVENT_STA_START: 701 | esp_wifi_connect(); 702 | break; 703 | case SYSTEM_EVENT_STA_GOT_IP: 704 | xEventGroupSetBits(wifi_event_group, CONNECTED_BIT); 705 | break; 706 | case SYSTEM_EVENT_STA_DISCONNECTED: 707 | /* This is a workaround as ESP32 WiFi libs don't currently 708 | auto-reassociate. */ 709 | esp_wifi_connect(); 710 | xEventGroupClearBits(wifi_event_group, CONNECTED_BIT); 711 | break; 712 | case SYSTEM_EVENT_AP_START: 713 | xEventGroupSetBits(wifi_event_group, APSTARTED_BIT); 714 | ESP_LOGD(WEBSRV_TAG, "AP Started"); 715 | break; 716 | case SYSTEM_EVENT_AP_STOP: 717 | xEventGroupClearBits(wifi_event_group, APSTARTED_BIT); 718 | ESP_LOGD(WEBSRV_TAG, "AP Stopped"); 719 | break; 720 | case SYSTEM_EVENT_AP_STACONNECTED: 721 | ESP_LOGD(WEBSRV_TAG, "station connected to access point. Connected stations:"); 722 | wifi_sta_list_t sta_list; 723 | ESP_ERROR_CHECK( esp_wifi_ap_get_sta_list(&sta_list)); 724 | for(int i = 0; i < sta_list.num; i++) { 725 | //Print the mac address of the connected station 726 | wifi_sta_info_t sta = sta_list.sta[i]; 727 | ESP_LOGD(WEBSRV_TAG, "Station %d MAC: %02X:%02X:%02X:%02X:%02X:%02X\n", i, sta.mac[0], sta.mac[1], sta.mac[2], sta.mac[3], sta.mac[4], sta.mac[5]); 728 | } 729 | break; 730 | case SYSTEM_EVENT_AP_STADISCONNECTED: 731 | ESP_LOGD(WEBSRV_TAG, "station disconnected from access point"); 732 | break; 733 | default: 734 | break; 735 | } 736 | return ESP_OK; 737 | } 738 | 739 | //---------------------------------------------------------------------------------------- 740 | static void http_get_fromInternet(struct netconn *conn, const char *request, uint8_t type) 741 | { 742 | ESP_LOGD(WEBSRV_TAG, "Get data from Internet"); 743 | const struct addrinfo hints = { 744 | .ai_family = AF_INET, 745 | .ai_socktype = SOCK_STREAM, 746 | }; 747 | struct addrinfo *res; 748 | int s, r; 749 | char recv_buf[128]; 750 | int rlen=0, totlen=0; 751 | char *buffer = NULL; 752 | char *hdr_end_ptr = NULL; 753 | 754 | // ======================================================= 755 | // Other tasks may use PPPoS, wait until they are finished 756 | // ======================================================= 757 | if (!(xSemaphoreTake(http_mutex, TASK_SEMAPHORE_WAIT))) { 758 | ESP_LOGE(WEBSRV_TAG, "ERROR: CANNOT GET MUTEX"); 759 | return; 760 | } 761 | 762 | // ** We must be connected to Internet 763 | if (ppposInit() == 0) { 764 | ESP_LOGE(WEBSRV_TAG, "PPPoS not initialized"); 765 | xSemaphoreGive(http_mutex); 766 | return; 767 | } 768 | 769 | int err = getaddrinfo(WEB_SERVER, "80", &hints, &res); 770 | if(err != 0 || res == NULL) { 771 | ESP_LOGE(WEBSRV_TAG, "DNS lookup failed err=%d res=%p", err, res); 772 | xSemaphoreGive(http_mutex); 773 | return; 774 | } 775 | 776 | // Create socket and connect to http server 777 | s = socket(res->ai_family, res->ai_socktype, 0); 778 | if (s < 0) { 779 | ESP_LOGE(WEBSRV_TAG, "... Failed to allocate socket."); 780 | freeaddrinfo(res); 781 | xSemaphoreGive(http_mutex); 782 | return; 783 | } 784 | 785 | if(connect(s, res->ai_addr, res->ai_addrlen) != 0) { 786 | ESP_LOGE(WEBSRV_TAG, "... socket connect failed errno=%d", errno); 787 | close(s); 788 | freeaddrinfo(res); 789 | xSemaphoreGive(http_mutex); 790 | return; 791 | } 792 | 793 | freeaddrinfo(res); 794 | 795 | // Send GET request 796 | if (write(s, request, strlen(request)) < 0) { 797 | ESP_LOGE(WEBSRV_TAG, "... socket send failed"); 798 | close(s); 799 | xSemaphoreGive(http_mutex); 800 | return; 801 | } 802 | 803 | // Get the response to buffer 804 | buffer = malloc(2048); 805 | if (!buffer) { 806 | ESP_LOGE(WEBSRV_TAG, "ERROR allocating receive buffer"); 807 | close(s); 808 | buffer = NULL; 809 | xSemaphoreGive(http_mutex); 810 | return; 811 | } 812 | memset(buffer, 0, 2048); 813 | /* Read HTTP response */ 814 | int opt = 500; 815 | int first_block = 1; 816 | char *cont_len = NULL; 817 | int clen = 0; 818 | rlen = 0; 819 | totlen = 0; 820 | do { 821 | bzero(recv_buf, sizeof(recv_buf)); 822 | r = read(s, recv_buf, sizeof(recv_buf)-1); 823 | totlen += r; 824 | if ((rlen + r) < 2048) { 825 | memcpy(buffer+rlen, recv_buf, r); 826 | rlen += r; 827 | buffer[rlen] = '\0'; 828 | if (clen == 0) { 829 | cont_len = strstr(buffer, "Content-Length: "); 830 | if (cont_len) { 831 | cont_len += 16; 832 | if (strstr(cont_len, "\r\n")) { 833 | char slen[16] = {0}; 834 | memcpy(slen, cont_len, strstr(cont_len, "\r\n")-cont_len); 835 | clen = atoi(slen); 836 | } 837 | } 838 | } 839 | if (hdr_end_ptr == NULL) { 840 | hdr_end_ptr = strstr(buffer, "\r\n\r\n"); 841 | if (hdr_end_ptr) hdr_end_ptr += 4; 842 | } 843 | else if (clen > 0) { 844 | if (strlen(hdr_end_ptr) >= clen) break; 845 | } 846 | } 847 | if (first_block) { 848 | lwip_setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &opt, sizeof(int)); 849 | first_block = 0; 850 | } 851 | } while(r > 0); 852 | 853 | close(s); 854 | xSemaphoreGive(http_mutex); 855 | 856 | // Send the response to the client connected via WiFi AP 857 | if (hdr_end_ptr) { 858 | ESP_LOGI(WEBSRV_TAG, "Received data: rlen=%d, total=%d, body=%d [%d]", rlen, totlen, strlen(hdr_end_ptr), clen); 859 | } 860 | else { 861 | ESP_LOGE(WEBSRV_TAG, "No header end found, rlen=%d", rlen); 862 | free(buffer); 863 | buffer = NULL; 864 | return; 865 | } 866 | 867 | if (type) netconn_write(conn, "

Received via PPPoS:

\r\n
", 39, NETCONN_NOCOPY); 868 | netconn_write(conn, hdr_end_ptr, strlen(hdr_end_ptr), NETCONN_NOCOPY); 869 | if (type) netconn_write(conn, "
\r\n", 13, NETCONN_NOCOPY); 870 | free(buffer); 871 | buffer = NULL; 872 | 873 | return; 874 | } 875 | 876 | 877 | //----------------------------------------------------------- 878 | static void http_server_netconn_serve(struct netconn *conn) { 879 | 880 | struct netbuf *inbuf; 881 | char *buf; 882 | u16_t buflen; 883 | err_t err; 884 | 885 | err = netconn_recv(conn, &inbuf); 886 | 887 | if (err == ERR_OK) { 888 | 889 | netbuf_data(inbuf, (void**)&buf, &buflen); 890 | 891 | // extract the first line, with the request 892 | char *first_line = strtok(buf, "\n"); 893 | 894 | if (first_line) { 895 | // default page 896 | if (strstr(first_line, "GET / ")) { 897 | netconn_write(conn, http_html_hdr, sizeof(http_html_hdr) - 1, NETCONN_NOCOPY); 898 | netconn_write(conn, http_index_html, sizeof(http_index_html) - 1, NETCONN_NOCOPY); 899 | http_get_fromInternet(conn, REQUEST, 1); 900 | netconn_write(conn, "\n\n", 16, NETCONN_NOCOPY); 901 | ESP_LOGI(WEBSRV_TAG, "Got request from client"); 902 | } 903 | else if (strstr(first_line, "GET /test ")) { 904 | http_get_fromInternet(conn, REQUEST1, 0); 905 | ESP_LOGI(WEBSRV_TAG, "Got [test] request from client"); 906 | } 907 | else { 908 | ESP_LOGW(WEBSRV_TAG, "Unknown request type [%s]", first_line); 909 | } 910 | } 911 | else { 912 | ESP_LOGE(WEBSRV_TAG, "Unknown request"); 913 | } 914 | } 915 | 916 | // close the connection and free the buffer 917 | netconn_close(conn); 918 | netbuf_delete(inbuf); 919 | } 920 | 921 | //------------------------------------------- 922 | static void http_server(void *pvParameters) { 923 | 924 | struct netconn *conn, *newconn; 925 | err_t err; 926 | conn = netconn_new(NETCONN_TCP); 927 | netconn_bind(conn, NULL, 80); 928 | netconn_listen(conn); 929 | ESP_LOGD(WEBSRV_TAG, "HTTP Server listening..."); 930 | do { 931 | err = netconn_accept(conn, &newconn); 932 | ESP_LOGD(WEBSRV_TAG, "New client connected"); 933 | if (err == ERR_OK) { 934 | http_server_netconn_serve(newconn); 935 | netconn_delete(newconn); 936 | } 937 | } while(err == ERR_OK); 938 | netconn_close(conn); 939 | netconn_delete(conn); 940 | ESP_LOGE(WEBSRV_TAG, "Netconn accept error, task halted!"); 941 | } 942 | 943 | // ========================================================================================== 944 | 945 | #endif 946 | 947 | 948 | //============= 949 | void app_main() 950 | { 951 | http_mutex = xSemaphoreCreateMutex(); 952 | 953 | #ifdef CONFIG_GSM_USE_WIFI_AP 954 | // ----- Set AP(STA)--------------------------------------------------- 955 | nvs_flash_init(); 956 | tcpip_adapter_init(); 957 | wifi_event_group = xEventGroupCreate(); 958 | ESP_ERROR_CHECK( esp_event_loop_init(esp32_wifi_eventHandler, NULL) ); 959 | wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); 960 | ESP_ERROR_CHECK( esp_wifi_init(&cfg) ); 961 | ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM) ); 962 | ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_AP) ); 963 | wifi_config_t apConfig = { 964 | .ap = { 965 | .ssid="ESP32_TESTAP", 966 | .ssid_len=0, 967 | .password="", 968 | .channel=0, 969 | .authmode=WIFI_AUTH_OPEN, 970 | .ssid_hidden=0, 971 | .max_connection=8, 972 | .beacon_interval=100 973 | }, 974 | }; 975 | ESP_ERROR_CHECK( esp_wifi_set_config(WIFI_IF_AP, &apConfig) ); 976 | 977 | //wifi_config_t staConfig = { 978 | // .sta = { 979 | // .ssid = "MySSID", 980 | // .password = "MyPassword", 981 | // } 982 | //}; 983 | //ESP_ERROR_CHECK( esp_wifi_set_config(WIFI_IF_STA, &staConfig) ); 984 | 985 | ESP_ERROR_CHECK( esp_wifi_start() ); 986 | // --------------------------------------------------------------------- 987 | 988 | xEventGroupWaitBits(wifi_event_group, APSTARTED_BIT, pdFALSE, pdTRUE, portMAX_DELAY); 989 | // start the HTTP Server task 990 | xTaskCreate(&http_server, "http_server", 2048, NULL, 5, NULL); 991 | 992 | vTaskDelay(1000 / portTICK_RATE_MS); 993 | #endif 994 | 995 | if (ppposInit() == 0) { 996 | ESP_LOGE("PPPoS EXAMPLE", "ERROR: GSM not initialized, HALTED"); 997 | while (1) { 998 | vTaskDelay(1000 / portTICK_RATE_MS); 999 | } 1000 | } 1001 | 1002 | // ==== Get time from NTP server ===== 1003 | time_t now = 0; 1004 | struct tm timeinfo = { 0 }; 1005 | int retry = 0; 1006 | const int retry_count = 10; 1007 | 1008 | time(&now); 1009 | localtime_r(&now, &timeinfo); 1010 | 1011 | while (1) { 1012 | printf("\r\n"); 1013 | ESP_LOGI(TIME_TAG,"OBTAINING TIME"); 1014 | ESP_LOGI(TIME_TAG, "Initializing SNTP"); 1015 | sntp_setoperatingmode(SNTP_OPMODE_POLL); 1016 | sntp_setservername(0, "pool.ntp.org"); 1017 | sntp_init(); 1018 | ESP_LOGI(TIME_TAG,"SNTP INITIALIZED"); 1019 | 1020 | // wait for time to be set 1021 | now = 0; 1022 | while ((timeinfo.tm_year < (2016 - 1900)) && (++retry < retry_count)) { 1023 | ESP_LOGI(TIME_TAG, "Waiting for system time to be set... (%d/%d)", retry, retry_count); 1024 | vTaskDelay(2000 / portTICK_PERIOD_MS); 1025 | time(&now); 1026 | localtime_r(&now, &timeinfo); 1027 | if (ppposStatus() != GSM_STATE_CONNECTED) break; 1028 | } 1029 | if (ppposStatus() != GSM_STATE_CONNECTED) { 1030 | sntp_stop(); 1031 | ESP_LOGE(TIME_TAG, "Disconnected, waiting for reconnect"); 1032 | retry = 0; 1033 | while (ppposStatus() != GSM_STATE_CONNECTED) { 1034 | vTaskDelay(100 / portTICK_RATE_MS); 1035 | } 1036 | continue; 1037 | } 1038 | 1039 | if (retry < retry_count) { 1040 | ESP_LOGI(TIME_TAG, "TIME SET TO %s", asctime(&timeinfo)); 1041 | break; 1042 | } 1043 | else { 1044 | ESP_LOGI(TIME_TAG, "ERROR OBTAINING TIME\n"); 1045 | } 1046 | sntp_stop(); 1047 | break; 1048 | } 1049 | 1050 | // ==== Create PPPoS tasks ==== 1051 | xTaskCreate(&http_get_task, "http_get_task", 4096, NULL, 5, NULL); 1052 | xTaskCreate(&https_get_task, "https_get_task", 16384, NULL, 4, NULL); 1053 | #ifdef CONFIG_GSM_SEND_SMS 1054 | // ==== Create SMS task ==== 1055 | xTaskCreate(&sms_task, "sms_task", 4096, NULL, 3, NULL); 1056 | #endif 1057 | 1058 | while(1) 1059 | { 1060 | vTaskDelay(1000 / portTICK_RATE_MS); 1061 | } 1062 | } 1063 | -------------------------------------------------------------------------------- /main/server_root_cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIEkjCCA3qgAwIBAgIQCgFBQgAAAVOFc2oLheynCDANBgkqhkiG9w0BAQsFADA/ 3 | MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT 4 | DkRTVCBSb290IENBIFgzMB4XDTE2MDMxNzE2NDA0NloXDTIxMDMxNzE2NDA0Nlow 5 | SjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUxldCdzIEVuY3J5cHQxIzAhBgNVBAMT 6 | GkxldCdzIEVuY3J5cHQgQXV0aG9yaXR5IFgzMIIBIjANBgkqhkiG9w0BAQEFAAOC 7 | AQ8AMIIBCgKCAQEAnNMM8FrlLke3cl03g7NoYzDq1zUmGSXhvb418XCSL7e4S0EF 8 | q6meNQhY7LEqxGiHC6PjdeTm86dicbp5gWAf15Gan/PQeGdxyGkOlZHP/uaZ6WA8 9 | SMx+yk13EiSdRxta67nsHjcAHJyse6cF6s5K671B5TaYucv9bTyWaN8jKkKQDIZ0 10 | Z8h/pZq4UmEUEz9l6YKHy9v6Dlb2honzhT+Xhq+w3Brvaw2VFn3EK6BlspkENnWA 11 | a6xK8xuQSXgvopZPKiAlKQTGdMDQMc2PMTiVFrqoM7hD8bEfwzB/onkxEz0tNvjj 12 | /PIzark5McWvxI0NHWQWM6r6hCm21AvA2H3DkwIDAQABo4IBfTCCAXkwEgYDVR0T 13 | AQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwfwYIKwYBBQUHAQEEczBxMDIG 14 | CCsGAQUFBzABhiZodHRwOi8vaXNyZy50cnVzdGlkLm9jc3AuaWRlbnRydXN0LmNv 15 | bTA7BggrBgEFBQcwAoYvaHR0cDovL2FwcHMuaWRlbnRydXN0LmNvbS9yb290cy9k 16 | c3Ryb290Y2F4My5wN2MwHwYDVR0jBBgwFoAUxKexpHsscfrb4UuQdf/EFWCFiRAw 17 | VAYDVR0gBE0wSzAIBgZngQwBAgEwPwYLKwYBBAGC3xMBAQEwMDAuBggrBgEFBQcC 18 | ARYiaHR0cDovL2Nwcy5yb290LXgxLmxldHNlbmNyeXB0Lm9yZzA8BgNVHR8ENTAz 19 | MDGgL6AthitodHRwOi8vY3JsLmlkZW50cnVzdC5jb20vRFNUUk9PVENBWDNDUkwu 20 | Y3JsMB0GA1UdDgQWBBSoSmpjBH3duubRObemRWXv86jsoTANBgkqhkiG9w0BAQsF 21 | AAOCAQEA3TPXEfNjWDjdGBX7CVW+dla5cEilaUcne8IkCJLxWh9KEik3JHRRHGJo 22 | uM2VcGfl96S8TihRzZvoroed6ti6WqEBmtzw3Wodatg+VyOeph4EYpr/1wXKtx8/ 23 | wApIvJSwtmVi4MFU5aMqrSDE6ea73Mj2tcMyo5jMd6jmeWUHK8so/joWUoHOUgwu 24 | X4Po1QYz+3dszkDqMp4fklxBwXRsW10KXzPMTZ+sOPAveyxindmjkW8lGy+QsRlG 25 | PfZ+G6Z6h7mjem0Y+iWlkYcV4PIWL1iwBi8saCbGS5jN2p8M+X+Q7UNKEkROb3N6 26 | KOqkqm57TH2H3eDJAkSnh6/DNFu0Qg== 27 | -----END CERTIFICATE----- 28 | -------------------------------------------------------------------------------- /pppapi.c.patch: -------------------------------------------------------------------------------- 1 | --- pppapi.c 2017-10-11 14:36:42.000000000 +0200 2 | +++ pppapi.c.patched 2017-10-11 14:39:14.000000000 +0200 3 | @@ -48,9 +48,9 @@ 4 | static err_t 5 | pppapi_do_ppp_set_default(struct tcpip_api_call *m) 6 | { 7 | - struct pppapi_msg_msg *msg = (struct pppapi_msg_msg *)m; 8 | + struct pppapi_msg *msg = (struct pppapi_msg *)m; 9 | 10 | - ppp_set_default(msg->ppp); 11 | + ppp_set_default(msg->msg.ppp); 12 | return ERR_OK; 13 | } 14 | 15 | @@ -103,8 +103,8 @@ 16 | static err_t 17 | pppapi_do_ppp_set_notify_phase_callback(struct tcpip_api_call *m) 18 | { 19 | - struct pppapi_msg_msg *msg = (struct pppapi_msg_msg *)m; 20 | - ppp_set_notify_phase_callback(msg->ppp, msg->msg.setnotifyphasecb.notify_phase_cb); 21 | + struct pppapi_msg *msg = (struct pppapi_msg *)m; 22 | + ppp_set_notify_phase_callback(msg->msg.ppp, msg->msg.msg.setnotifyphasecb.notify_phase_cb); 23 | return ERR_OK; 24 | } 25 | 26 | @@ -164,11 +164,11 @@ 27 | static err_t 28 | pppapi_do_pppoe_create(struct tcpip_api_call *m) 29 | { 30 | - struct pppapi_msg_msg *msg = (struct pppapi_msg_msg *)m; 31 | + struct pppapi_msg *msg = (struct pppapi_msg *)m; 32 | 33 | - msg->ppp = pppoe_create(msg->msg.ethernetcreate.pppif, msg->msg.ethernetcreate.ethif, 34 | - msg->msg.ethernetcreate.service_name, msg->msg.ethernetcreate.concentrator_name, 35 | - msg->msg.ethernetcreate.link_status_cb, msg->msg.ethernetcreate.ctx_cb); 36 | + msg->msg.ppp = pppoe_create(msg->msg.msg.ethernetcreate.pppif, msg->msg.msg.ethernetcreate.ethif, 37 | + msg->msg.msg.ethernetcreate.service_name, msg->msg.msg.ethernetcreate.concentrator_name, 38 | + msg->msg.msg.ethernetcreate.link_status_cb, msg->msg.msg.ethernetcreate.ctx_cb); 39 | return ERR_OK; 40 | } 41 | 42 | @@ -201,17 +201,17 @@ 43 | static err_t 44 | pppapi_do_pppol2tp_create(struct tcpip_api_call *m) 45 | { 46 | - struct pppapi_msg_msg *msg = (struct pppapi_msg_msg *)m; 47 | + struct pppapi_msg *msg = (struct pppapi_msg *)m; 48 | 49 | - msg->ppp = pppol2tp_create(msg->msg.l2tpcreate.pppif, 50 | - msg->msg.l2tpcreate.netif, msg->msg.l2tpcreate.ipaddr, msg->msg.l2tpcreate.port, 51 | + msg->msg.ppp = pppol2tp_create(msg->msg.msg.l2tpcreate.pppif, 52 | + msg->msg.msg.l2tpcreate.netif, msg->msg.msg.l2tpcreate.ipaddr, msg->msg.msg.l2tpcreate.port, 53 | #if PPPOL2TP_AUTH_SUPPORT 54 | - msg->msg.l2tpcreate.secret, 55 | - msg->msg.l2tpcreate.secret_len, 56 | + msg->msg.msg.l2tpcreate.secret, 57 | + msg->msg.msg.l2tpcreate.secret_len, 58 | #else /* PPPOL2TP_AUTH_SUPPORT */ 59 | NULL, 60 | #endif /* PPPOL2TP_AUTH_SUPPORT */ 61 | - msg->msg.l2tpcreate.link_status_cb, msg->msg.l2tpcreate.ctx_cb); 62 | + msg->msg.msg.l2tpcreate.link_status_cb, msg->msg.msg.l2tpcreate.ctx_cb); 63 | return ERR_OK; 64 | } 65 | 66 | @@ -325,9 +325,9 @@ 67 | static err_t 68 | pppapi_do_ppp_free(struct tcpip_api_call *m) 69 | { 70 | - struct pppapi_msg_msg *msg = (struct pppapi_msg_msg *)m; 71 | + struct pppapi_msg *msg = (struct pppapi_msg *)m; 72 | 73 | - return ppp_free(msg->ppp); 74 | + return ppp_free(msg->msg.ppp); 75 | } 76 | 77 | /** 78 | -------------------------------------------------------------------------------- /pppapi.c.patched: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 3 | * Point To Point Protocol Sequential API module 4 | * 5 | */ 6 | 7 | /* 8 | * Redistribution and use in source and binary forms, with or without modification, 9 | * are permitted provided that the following conditions are met: 10 | * 11 | * 1. Redistributions of source code must retain the above copyright notice, 12 | * this list of conditions and the following disclaimer. 13 | * 2. Redistributions in binary form must reproduce the above copyright notice, 14 | * this list of conditions and the following disclaimer in the documentation 15 | * and/or other materials provided with the distribution. 16 | * 3. The name of the author may not be used to endorse or promote products 17 | * derived from this software without specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 20 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 22 | * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 23 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 24 | * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 27 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 28 | * OF SUCH DAMAGE. 29 | * 30 | * This file is part of the lwIP TCP/IP stack. 31 | * 32 | */ 33 | 34 | #include "lwip/opt.h" 35 | 36 | #if LWIP_PPP_API /* don't build if not configured for use in lwipopts.h */ 37 | 38 | #include "lwip/pppapi.h" 39 | #include "lwip/priv/tcpip_priv.h" 40 | #include "netif/ppp/pppoe.h" 41 | #include "netif/ppp/pppol2tp.h" 42 | #include "netif/ppp/pppos.h" 43 | 44 | 45 | /** 46 | * Call ppp_set_default() inside the tcpip_thread context. 47 | */ 48 | static err_t 49 | pppapi_do_ppp_set_default(struct tcpip_api_call *m) 50 | { 51 | struct pppapi_msg *msg = (struct pppapi_msg *)m; 52 | 53 | ppp_set_default(msg->msg.ppp); 54 | return ERR_OK; 55 | } 56 | 57 | /** 58 | * Call ppp_set_default() in a thread-safe way by running that function inside the 59 | * tcpip_thread context. 60 | */ 61 | void 62 | pppapi_set_default(ppp_pcb *pcb) 63 | { 64 | struct pppapi_msg msg; 65 | msg.msg.ppp = pcb; 66 | tcpip_api_call(pppapi_do_ppp_set_default, &msg.call); 67 | } 68 | 69 | 70 | /** 71 | * Call ppp_set_auth() inside the tcpip_thread context. 72 | */ 73 | static err_t 74 | pppapi_do_ppp_set_auth(struct tcpip_api_call *m) 75 | { 76 | struct pppapi_msg *msg = (struct pppapi_msg *)m; 77 | 78 | ppp_set_auth(msg->msg.ppp, msg->msg.msg.setauth.authtype, 79 | msg->msg.msg.setauth.user, msg->msg.msg.setauth.passwd); 80 | return ERR_OK; 81 | } 82 | 83 | /** 84 | * Call ppp_set_auth() in a thread-safe way by running that function inside the 85 | * tcpip_thread context. 86 | */ 87 | void 88 | pppapi_set_auth(ppp_pcb *pcb, u8_t authtype, const char *user, const char *passwd) 89 | { 90 | struct pppapi_msg msg; 91 | msg.msg.ppp = pcb; 92 | msg.msg.msg.setauth.authtype = authtype; 93 | msg.msg.msg.setauth.user = user; 94 | msg.msg.msg.setauth.passwd = passwd; 95 | tcpip_api_call(pppapi_do_ppp_set_auth, &msg.call); 96 | } 97 | 98 | 99 | #if PPP_NOTIFY_PHASE 100 | /** 101 | * Call ppp_set_notify_phase_callback() inside the tcpip_thread context. 102 | */ 103 | static err_t 104 | pppapi_do_ppp_set_notify_phase_callback(struct tcpip_api_call *m) 105 | { 106 | struct pppapi_msg *msg = (struct pppapi_msg *)m; 107 | ppp_set_notify_phase_callback(msg->msg.ppp, msg->msg.msg.setnotifyphasecb.notify_phase_cb); 108 | return ERR_OK; 109 | } 110 | 111 | /** 112 | * Call ppp_set_notify_phase_callback() in a thread-safe way by running that function inside the 113 | * tcpip_thread context. 114 | */ 115 | void 116 | pppapi_set_notify_phase_callback(ppp_pcb *pcb, ppp_notify_phase_cb_fn notify_phase_cb) 117 | { 118 | struct pppapi_msg msg; 119 | msg.function = pppapi_do_ppp_set_notify_phase_callback; 120 | msg.msg.ppp = pcb; 121 | msg.msg.msg.setnotifyphasecb.notify_phase_cb = notify_phase_cb; 122 | tcpip_api_call(pppapi_do_ppp_set_notify_phase_callback, &msg.call); 123 | } 124 | #endif /* PPP_NOTIFY_PHASE */ 125 | 126 | 127 | #if PPPOS_SUPPORT 128 | /** 129 | * Call pppos_create() inside the tcpip_thread context. 130 | */ 131 | static err_t 132 | pppapi_do_pppos_create(struct tcpip_api_call *m) 133 | { 134 | struct pppapi_msg *msg = (struct pppapi_msg *)(m); 135 | 136 | msg->msg.ppp = pppos_create(msg->msg.msg.serialcreate.pppif, msg->msg.msg.serialcreate.output_cb, 137 | msg->msg.msg.serialcreate.link_status_cb, msg->msg.msg.serialcreate.ctx_cb); 138 | return ERR_OK; 139 | } 140 | 141 | /** 142 | * Call pppos_create() in a thread-safe way by running that function inside the 143 | * tcpip_thread context. 144 | */ 145 | ppp_pcb* 146 | pppapi_pppos_create(struct netif *pppif, pppos_output_cb_fn output_cb, 147 | ppp_link_status_cb_fn link_status_cb, void *ctx_cb) 148 | { 149 | struct pppapi_msg msg; 150 | msg.msg.msg.serialcreate.pppif = pppif; 151 | msg.msg.msg.serialcreate.output_cb = output_cb; 152 | msg.msg.msg.serialcreate.link_status_cb = link_status_cb; 153 | msg.msg.msg.serialcreate.ctx_cb = ctx_cb; 154 | tcpip_api_call(pppapi_do_pppos_create, &msg.call); 155 | return msg.msg.ppp; 156 | } 157 | #endif /* PPPOS_SUPPORT */ 158 | 159 | 160 | #if PPPOE_SUPPORT 161 | /** 162 | * Call pppoe_create() inside the tcpip_thread context. 163 | */ 164 | static err_t 165 | pppapi_do_pppoe_create(struct tcpip_api_call *m) 166 | { 167 | struct pppapi_msg *msg = (struct pppapi_msg *)m; 168 | 169 | msg->msg.ppp = pppoe_create(msg->msg.msg.ethernetcreate.pppif, msg->msg.msg.ethernetcreate.ethif, 170 | msg->msg.msg.ethernetcreate.service_name, msg->msg.msg.ethernetcreate.concentrator_name, 171 | msg->msg.msg.ethernetcreate.link_status_cb, msg->msg.msg.ethernetcreate.ctx_cb); 172 | return ERR_OK; 173 | } 174 | 175 | /** 176 | * Call pppoe_create() in a thread-safe way by running that function inside the 177 | * tcpip_thread context. 178 | */ 179 | ppp_pcb* 180 | pppapi_pppoe_create(struct netif *pppif, struct netif *ethif, const char *service_name, 181 | const char *concentrator_name, ppp_link_status_cb_fn link_status_cb, 182 | void *ctx_cb) 183 | { 184 | struct pppapi_msg msg; 185 | msg.msg.msg.ethernetcreate.pppif = pppif; 186 | msg.msg.msg.ethernetcreate.ethif = ethif; 187 | msg.msg.msg.ethernetcreate.service_name = service_name; 188 | msg.msg.msg.ethernetcreate.concentrator_name = concentrator_name; 189 | msg.msg.msg.ethernetcreate.link_status_cb = link_status_cb; 190 | msg.msg.msg.ethernetcreate.ctx_cb = ctx_cb; 191 | tcpip_api_call(pppapi_do_pppoe_create, &msg.call); 192 | return msg.msg.ppp; 193 | } 194 | #endif /* PPPOE_SUPPORT */ 195 | 196 | 197 | #if PPPOL2TP_SUPPORT 198 | /** 199 | * Call pppol2tp_create() inside the tcpip_thread context. 200 | */ 201 | static err_t 202 | pppapi_do_pppol2tp_create(struct tcpip_api_call *m) 203 | { 204 | struct pppapi_msg *msg = (struct pppapi_msg *)m; 205 | 206 | msg->msg.ppp = pppol2tp_create(msg->msg.msg.l2tpcreate.pppif, 207 | msg->msg.msg.l2tpcreate.netif, msg->msg.msg.l2tpcreate.ipaddr, msg->msg.msg.l2tpcreate.port, 208 | #if PPPOL2TP_AUTH_SUPPORT 209 | msg->msg.msg.l2tpcreate.secret, 210 | msg->msg.msg.l2tpcreate.secret_len, 211 | #else /* PPPOL2TP_AUTH_SUPPORT */ 212 | NULL, 213 | #endif /* PPPOL2TP_AUTH_SUPPORT */ 214 | msg->msg.msg.l2tpcreate.link_status_cb, msg->msg.msg.l2tpcreate.ctx_cb); 215 | return ERR_OK; 216 | } 217 | 218 | /** 219 | * Call pppol2tp_create() in a thread-safe way by running that function inside the 220 | * tcpip_thread context. 221 | */ 222 | ppp_pcb* 223 | pppapi_pppol2tp_create(struct netif *pppif, struct netif *netif, ip_addr_t *ipaddr, u16_t port, 224 | const u8_t *secret, u8_t secret_len, 225 | ppp_link_status_cb_fn link_status_cb, void *ctx_cb) 226 | { 227 | struct pppapi_msg msg; 228 | msg.msg.msg.l2tpcreate.pppif = pppif; 229 | msg.msg.msg.l2tpcreate.netif = netif; 230 | msg.msg.msg.l2tpcreate.ipaddr = ipaddr; 231 | msg.msg.msg.l2tpcreate.port = port; 232 | #if PPPOL2TP_AUTH_SUPPORT 233 | msg.msg.msg.l2tpcreate.secret = secret; 234 | msg.msg.msg.l2tpcreate.secret_len = secret_len; 235 | #endif /* PPPOL2TP_AUTH_SUPPORT */ 236 | msg.msg.msg.l2tpcreate.link_status_cb = link_status_cb; 237 | msg.msg.msg.l2tpcreate.ctx_cb = ctx_cb; 238 | tcpip_api_call(pppapi_do_pppol2tp_create, &msg.call); 239 | return msg.msg.ppp; 240 | } 241 | #endif /* PPPOL2TP_SUPPORT */ 242 | 243 | 244 | /** 245 | * Call ppp_connect() inside the tcpip_thread context. 246 | */ 247 | static err_t 248 | pppapi_do_ppp_connect(struct tcpip_api_call *m) 249 | { 250 | struct pppapi_msg *msg = (struct pppapi_msg *)m; 251 | 252 | return ppp_connect(msg->msg.ppp, msg->msg.msg.connect.holdoff); 253 | } 254 | 255 | /** 256 | * Call ppp_connect() in a thread-safe way by running that function inside the 257 | * tcpip_thread context. 258 | */ 259 | err_t 260 | pppapi_connect(ppp_pcb *pcb, u16_t holdoff) 261 | { 262 | struct pppapi_msg msg; 263 | msg.msg.ppp = pcb; 264 | msg.msg.msg.connect.holdoff = holdoff; 265 | return tcpip_api_call(pppapi_do_ppp_connect, &msg.call); 266 | } 267 | 268 | 269 | #if PPP_SERVER 270 | /** 271 | * Call ppp_listen() inside the tcpip_thread context. 272 | */ 273 | static void 274 | pppapi_do_ppp_listen(struct pppapi_msg_msg *msg) 275 | { 276 | msg->err = ppp_listen(msg->ppp, msg->msg.listen.addrs); 277 | TCPIP_PPPAPI_ACK(msg); 278 | } 279 | 280 | /** 281 | * Call ppp_listen() in a thread-safe way by running that function inside the 282 | * tcpip_thread context. 283 | */ 284 | err_t 285 | pppapi_listen(ppp_pcb *pcb, struct ppp_addrs *addrs) 286 | { 287 | struct pppapi_msg msg; 288 | msg.function = pppapi_do_ppp_listen; 289 | msg.msg.ppp = pcb; 290 | msg.msg.msg.listen.addrs = addrs; 291 | TCPIP_PPPAPI(&msg); 292 | return msg.msg.err; 293 | } 294 | #endif /* PPP_SERVER */ 295 | 296 | 297 | /** 298 | * Call ppp_close() inside the tcpip_thread context. 299 | */ 300 | static err_t 301 | pppapi_do_ppp_close(struct tcpip_api_call *m) 302 | { 303 | struct pppapi_msg *msg = (struct pppapi_msg *)m; 304 | 305 | return ppp_close(msg->msg.ppp, msg->msg.msg.close.nocarrier); 306 | } 307 | 308 | /** 309 | * Call ppp_close() in a thread-safe way by running that function inside the 310 | * tcpip_thread context. 311 | */ 312 | err_t 313 | pppapi_close(ppp_pcb *pcb, u8_t nocarrier) 314 | { 315 | struct pppapi_msg msg; 316 | msg.msg.ppp = pcb; 317 | msg.msg.msg.close.nocarrier = nocarrier; 318 | return tcpip_api_call(pppapi_do_ppp_close, &msg.call); 319 | } 320 | 321 | 322 | /** 323 | * Call ppp_free() inside the tcpip_thread context. 324 | */ 325 | static err_t 326 | pppapi_do_ppp_free(struct tcpip_api_call *m) 327 | { 328 | struct pppapi_msg *msg = (struct pppapi_msg *)m; 329 | 330 | return ppp_free(msg->msg.ppp); 331 | } 332 | 333 | /** 334 | * Call ppp_free() in a thread-safe way by running that function inside the 335 | * tcpip_thread context. 336 | */ 337 | err_t 338 | pppapi_free(ppp_pcb *pcb) 339 | { 340 | struct pppapi_msg msg; 341 | msg.msg.ppp = pcb; 342 | return tcpip_api_call(pppapi_do_ppp_free, &msg.call); 343 | } 344 | 345 | 346 | /** 347 | * Call ppp_ioctl() inside the tcpip_thread context. 348 | */ 349 | static err_t 350 | pppapi_do_ppp_ioctl(struct tcpip_api_call *m) 351 | { 352 | struct pppapi_msg *msg = (struct pppapi_msg *)m; 353 | 354 | return ppp_ioctl(msg->msg.ppp, msg->msg.msg.ioctl.cmd, msg->msg.msg.ioctl.arg); 355 | } 356 | 357 | /** 358 | * Call ppp_ioctl() in a thread-safe way by running that function inside the 359 | * tcpip_thread context. 360 | */ 361 | err_t 362 | pppapi_ioctl(ppp_pcb *pcb, u8_t cmd, void *arg) 363 | { 364 | struct pppapi_msg msg; 365 | msg.msg.ppp = pcb; 366 | msg.msg.msg.ioctl.cmd = cmd; 367 | msg.msg.msg.ioctl.arg = arg; 368 | return tcpip_api_call(pppapi_do_ppp_ioctl, &msg.call); 369 | } 370 | 371 | #endif /* LWIP_PPP_API */ 372 | -------------------------------------------------------------------------------- /sdkconfig.defaults: -------------------------------------------------------------------------------- 1 | # Override some defaults to enable PPP 2 | CONFIG_PPP_SUPPORT=y 3 | CONFIG_PPP_PAP_SUPPORT=y 4 | CONFIG_PPP_DEBUG_ON=n 5 | CONFIG_TCPIP_TASK_STACK_SIZE=4096 6 | CONFIG_ESP32_DEFAULT_CPU_FREQ_240=y 7 | CONFIG_FREERTOS_HZ=1000 8 | CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS=2 9 | CONFIG_ESPTOOLPY_AFTER_NORESET=y 10 | --------------------------------------------------------------------------------