diff --git a/CMakeLists.txt b/CMakeLists.txt index aaa59b0fbb6..8e760225a04 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -95,6 +95,7 @@ set(ARDUINO_ALL_LIBRARIES LittleFS NetBIOS Network + PPP Preferences RainMaker SD_MMC @@ -157,6 +158,10 @@ set(ARDUINO_LIBRARY_LittleFS_SRCS libraries/LittleFS/src/LittleFS.cpp) set(ARDUINO_LIBRARY_NetBIOS_SRCS libraries/NetBIOS/src/NetBIOS.cpp) +set(ARDUINO_LIBRARY_PPP_SRCS + libraries/PPP/src/PPP.cpp + libraries/PPP/src/ppp.c) + set(ARDUINO_LIBRARY_Preferences_SRCS libraries/Preferences/src/Preferences.cpp) set(ARDUINO_LIBRARY_RainMaker_SRCS diff --git a/Kconfig.projbuild b/Kconfig.projbuild index d753f436f70..979afc02213 100644 --- a/Kconfig.projbuild +++ b/Kconfig.projbuild @@ -321,6 +321,16 @@ config ARDUINO_SELECTIVE_Networking depends on ARDUINO_SELECTIVE_COMPILATION default y +config ARDUINO_SELECTIVE_Ethernet + bool "Enable Ethernet" + depends on ARDUINO_SELECTIVE_COMPILATION + default y + +config ARDUINO_SELECTIVE_PPP + bool "Enable PPP" + depends on ARDUINO_SELECTIVE_COMPILATION + default y + config ARDUINO_SELECTIVE_ArduinoOTA bool "Enable ArduinoOTA" depends on ARDUINO_SELECTIVE_COMPILATION && ARDUINO_SELECTIVE_Networking diff --git a/cores/esp32/esp32-hal-periman.c b/cores/esp32/esp32-hal-periman.c index e6fc3e66b71..acd75dadcb3 100644 --- a/cores/esp32/esp32-hal-periman.c +++ b/cores/esp32/esp32-hal-periman.c @@ -104,6 +104,12 @@ const char* perimanGetTypeName(peripheral_bus_type_t type) { case ESP32_BUS_TYPE_ETHERNET_MCD: return "ETHERNET_MCD"; case ESP32_BUS_TYPE_ETHERNET_MDIO: return "ETHERNET_MDIO"; case ESP32_BUS_TYPE_ETHERNET_PWR: return "ETHERNET_PWR"; +#endif +#if CONFIG_LWIP_PPP_SUPPORT + case ESP32_BUS_TYPE_PPP_TX: return "PPP_MODEM_TX"; + case ESP32_BUS_TYPE_PPP_RX: return "PPP_MODEM_RX"; + case ESP32_BUS_TYPE_PPP_RTS: return "PPP_MODEM_RTS"; + case ESP32_BUS_TYPE_PPP_CTS: return "PPP_MODEM_CTS"; #endif default: return "UNKNOWN"; } diff --git a/cores/esp32/esp32-hal-periman.h b/cores/esp32/esp32-hal-periman.h index 989795d8ade..c2d16017adb 100644 --- a/cores/esp32/esp32-hal-periman.h +++ b/cores/esp32/esp32-hal-periman.h @@ -102,6 +102,12 @@ extern "C" { ESP32_BUS_TYPE_ETHERNET_MCD, // IO is used as ETHERNET MCD pin ESP32_BUS_TYPE_ETHERNET_MDIO, // IO is used as ETHERNET MDIO pin ESP32_BUS_TYPE_ETHERNET_PWR, // IO is used as ETHERNET PWR pin +#endif +#if CONFIG_LWIP_PPP_SUPPORT + ESP32_BUS_TYPE_PPP_TX, // IO is used as PPP Modem TX pin + ESP32_BUS_TYPE_PPP_RX, // IO is used as PPP Modem RX pin + ESP32_BUS_TYPE_PPP_RTS, // IO is used as PPP Modem RTS pin + ESP32_BUS_TYPE_PPP_CTS, // IO is used as PPP Modem CTS pin #endif ESP32_BUS_TYPE_MAX } peripheral_bus_type_t; diff --git a/idf_component.yml b/idf_component.yml index c9c0342647b..2a76aec4d81 100644 --- a/idf_component.yml +++ b/idf_component.yml @@ -45,6 +45,7 @@ dependencies: idf: ">=5.1" # mdns 1.2.1 is necessary to build H2 with no WiFi mdns: "^1.2.3" + espressif/esp_modem: "^1.1.0" chmorgan/esp-libhelix-mp3: version: "1.0.3" require: public diff --git a/libraries/Network/src/NetworkEvents.cpp b/libraries/Network/src/NetworkEvents.cpp index a7955ee6cf2..f8ff3e9544c 100644 --- a/libraries/Network/src/NetworkEvents.cpp +++ b/libraries/Network/src/NetworkEvents.cpp @@ -319,16 +319,14 @@ const char *NetworkEvents::eventName(arduino_event_id_t id) { case ARDUINO_EVENT_ETH_DISCONNECTED: return "ETH_DISCONNECTED"; case ARDUINO_EVENT_ETH_GOT_IP: return "ETH_GOT_IP"; case ARDUINO_EVENT_ETH_LOST_IP: return "ETH_LOST_IP"; - case ARDUINO_EVENT_ETH_GOT_IP6: - return "ETH_GOT_IP6"; - - // case ARDUINO_EVENT_PPP_START: return "PPP_START"; - // case ARDUINO_EVENT_PPP_STOP: return "PPP_STOP"; - // case ARDUINO_EVENT_PPP_CONNECTED: return "PPP_CONNECTED"; - // case ARDUINO_EVENT_PPP_DISCONNECTED: return "PPP_DISCONNECTED"; - // case ARDUINO_EVENT_PPP_GOT_IP: return "PPP_GOT_IP"; - // case ARDUINO_EVENT_PPP_LOST_IP: return "PPP_LOST_IP"; - // case ARDUINO_EVENT_PPP_GOT_IP6: return "PPP_GOT_IP6"; + case ARDUINO_EVENT_ETH_GOT_IP6: return "ETH_GOT_IP6"; + case ARDUINO_EVENT_PPP_START: return "PPP_START"; + case ARDUINO_EVENT_PPP_STOP: return "PPP_STOP"; + case ARDUINO_EVENT_PPP_CONNECTED: return "PPP_CONNECTED"; + case ARDUINO_EVENT_PPP_DISCONNECTED: return "PPP_DISCONNECTED"; + case ARDUINO_EVENT_PPP_GOT_IP: return "PPP_GOT_IP"; + case ARDUINO_EVENT_PPP_LOST_IP: return "PPP_LOST_IP"; + case ARDUINO_EVENT_PPP_GOT_IP6: return "PPP_GOT_IP6"; #if SOC_WIFI_SUPPORTED case ARDUINO_EVENT_WIFI_OFF: return "WIFI_OFF"; case ARDUINO_EVENT_WIFI_READY: return "WIFI_READY"; diff --git a/libraries/Network/src/NetworkEvents.h b/libraries/Network/src/NetworkEvents.h index 2d6042461fc..ffa0070f96b 100644 --- a/libraries/Network/src/NetworkEvents.h +++ b/libraries/Network/src/NetworkEvents.h @@ -78,13 +78,13 @@ typedef enum { ARDUINO_EVENT_PROV_CRED_FAIL, ARDUINO_EVENT_PROV_CRED_SUCCESS, #endif - // ARDUINO_EVENT_PPP_START, - // ARDUINO_EVENT_PPP_STOP, - // ARDUINO_EVENT_PPP_CONNECTED, - // ARDUINO_EVENT_PPP_DISCONNECTED, - // ARDUINO_EVENT_PPP_GOT_IP, - // ARDUINO_EVENT_PPP_LOST_IP, - // ARDUINO_EVENT_PPP_GOT_IP6, + ARDUINO_EVENT_PPP_START, + ARDUINO_EVENT_PPP_STOP, + ARDUINO_EVENT_PPP_CONNECTED, + ARDUINO_EVENT_PPP_DISCONNECTED, + ARDUINO_EVENT_PPP_GOT_IP, + ARDUINO_EVENT_PPP_LOST_IP, + ARDUINO_EVENT_PPP_GOT_IP6, ARDUINO_EVENT_MAX } arduino_event_id_t; @@ -146,6 +146,7 @@ class NetworkEvents { friend class ESP_NetworkInterface; friend class ETHClass; + friend class PPPClass; #if SOC_WIFI_SUPPORTED friend class STAClass; friend class APClass; diff --git a/libraries/Network/src/NetworkInterface.cpp b/libraries/Network/src/NetworkInterface.cpp index 37e30900804..46b06d9611a 100644 --- a/libraries/Network/src/NetworkInterface.cpp +++ b/libraries/Network/src/NetworkInterface.cpp @@ -71,12 +71,11 @@ void NetworkInterface::_onIpEvent(int32_t event_id, void* event_data) { arduino_event.event_id = ARDUINO_EVENT_WIFI_STA_GOT_IP; } else #endif - // if(_interface_id == ESP_NETIF_ID_PPP){ - // arduino_event.event_id = ARDUINO_EVENT_PPP_GOT_IP; - // } else - if (_interface_id >= ESP_NETIF_ID_ETH && _interface_id < ESP_NETIF_ID_MAX) { - arduino_event.event_id = ARDUINO_EVENT_ETH_GOT_IP; - } + if (_interface_id == ESP_NETIF_ID_PPP) { + arduino_event.event_id = ARDUINO_EVENT_PPP_GOT_IP; + } else if (_interface_id >= ESP_NETIF_ID_ETH && _interface_id < ESP_NETIF_ID_MAX) { + arduino_event.event_id = ARDUINO_EVENT_ETH_GOT_IP; + } } else if (event_id == _lost_ip_event_id) { clearStatusBits(ESP_NETIF_HAS_IP_BIT); #if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_VERBOSE @@ -87,12 +86,11 @@ void NetworkInterface::_onIpEvent(int32_t event_id, void* event_data) { arduino_event.event_id = ARDUINO_EVENT_WIFI_STA_LOST_IP; } else #endif - // if(_interface_id == ESP_NETIF_ID_PPP){ - // arduino_event.event_id = ARDUINO_EVENT_PPP_LOST_IP; - // } else - if (_interface_id >= ESP_NETIF_ID_ETH && _interface_id < ESP_NETIF_ID_MAX) { - arduino_event.event_id = ARDUINO_EVENT_ETH_LOST_IP; - } + if (_interface_id == ESP_NETIF_ID_PPP) { + arduino_event.event_id = ARDUINO_EVENT_PPP_LOST_IP; + } else if (_interface_id >= ESP_NETIF_ID_ETH && _interface_id < ESP_NETIF_ID_MAX) { + arduino_event.event_id = ARDUINO_EVENT_ETH_LOST_IP; + } } else if (event_id == IP_EVENT_GOT_IP6) { ip_event_got_ip6_t* event = (ip_event_got_ip6_t*)event_data; esp_ip6_addr_type_t addr_type = esp_netif_ip6_get_addr_type(&event->ip6_info.ip); @@ -117,12 +115,11 @@ void NetworkInterface::_onIpEvent(int32_t event_id, void* event_data) { arduino_event.event_id = ARDUINO_EVENT_WIFI_AP_GOT_IP6; } else #endif - // if(_interface_id == ESP_NETIF_ID_PPP){ - // arduino_event.event_id = ARDUINO_EVENT_PPP_GOT_IP6; - // } else - if (_interface_id >= ESP_NETIF_ID_ETH && _interface_id < ESP_NETIF_ID_MAX) { - arduino_event.event_id = ARDUINO_EVENT_ETH_GOT_IP6; - } + if (_interface_id == ESP_NETIF_ID_PPP) { + arduino_event.event_id = ARDUINO_EVENT_PPP_GOT_IP6; + } else if (_interface_id >= ESP_NETIF_ID_ETH && _interface_id < ESP_NETIF_ID_MAX) { + arduino_event.event_id = ARDUINO_EVENT_ETH_GOT_IP6; + } #if SOC_WIFI_SUPPORTED } else if (event_id == IP_EVENT_AP_STAIPASSIGNED && _interface_id == ESP_NETIF_ID_AP) { setStatusBits(ESP_NETIF_HAS_IP_BIT); @@ -536,7 +533,7 @@ String NetworkInterface::impl_name(void) const { char netif_name[8]; esp_err_t err = esp_netif_get_netif_impl_name(_esp_netif, netif_name); if (err != ESP_OK) { - log_e("Failed to get netif impl_name: %d", err); + log_e("Failed to get netif impl_name: 0x%04x %s", err, esp_err_to_name(err)); return String(""); } return String(netif_name); @@ -562,7 +559,7 @@ bool NetworkInterface::setDefault() { } esp_err_t err = esp_netif_set_default_netif(_esp_netif); if (err != ESP_OK) { - log_e("Failed to set default netif: %d", err); + log_e("Failed to set default netif: 0x%04x %s", err, esp_err_to_name(err)); return false; } return true; @@ -576,15 +573,14 @@ bool NetworkInterface::isDefault() const { } uint8_t* NetworkInterface::macAddress(uint8_t* mac) const { - if (!mac || _esp_netif == NULL) { + if (!mac || _esp_netif == NULL || _interface_id == ESP_NETIF_ID_PPP) { return NULL; } esp_err_t err = esp_netif_get_mac(_esp_netif, mac); if (err != ESP_OK) { - log_e("Failed to get netif mac: %d", err); + log_e("Failed to get netif mac: 0x%04x %s", err, esp_err_to_name(err)); return NULL; } - // getMac(mac); return mac; } diff --git a/libraries/PPP/examples/PPP_Basic/PPP_Basic.ino b/libraries/PPP/examples/PPP_Basic/PPP_Basic.ino new file mode 100644 index 00000000000..16b30507703 --- /dev/null +++ b/libraries/PPP/examples/PPP_Basic/PPP_Basic.ino @@ -0,0 +1,141 @@ +#include + +#define PPP_MODEM_APN "internet" +#define PPP_MODEM_PIN "0000" // or NULL + +// WaveShare SIM7600 HW Flow Control +#define PPP_MODEM_RST 25 +#define PPP_MODEM_RST_LOW false //active HIGH +#define PPP_MODEM_TX 21 +#define PPP_MODEM_RX 22 +#define PPP_MODEM_RTS 26 +#define PPP_MODEM_CTS 27 +#define PPP_MODEM_FC ESP_MODEM_FLOW_CONTROL_HW +#define PPP_MODEM_MODEL PPP_MODEM_SIM7600 + +// SIM800 basic module with just TX,RX and RST +// #define PPP_MODEM_RST 0 +// #define PPP_MODEM_RST_LOW true //active LOW +// #define PPP_MODEM_TX 2 +// #define PPP_MODEM_RX 19 +// #define PPP_MODEM_RTS -1 +// #define PPP_MODEM_CTS -1 +// #define PPP_MODEM_FC ESP_MODEM_FLOW_CONTROL_NONE +// #define PPP_MODEM_MODEL PPP_MODEM_SIM800 + +void onEvent(arduino_event_id_t event, arduino_event_info_t info) { + switch (event) { + case ARDUINO_EVENT_PPP_START: + Serial.println("PPP Started"); + break; + case ARDUINO_EVENT_PPP_CONNECTED: + Serial.println("PPP Connected"); + break; + case ARDUINO_EVENT_PPP_GOT_IP: + Serial.println("PPP Got IP"); + break; + case ARDUINO_EVENT_PPP_LOST_IP: + Serial.println("PPP Lost IP"); + break; + case ARDUINO_EVENT_PPP_DISCONNECTED: + Serial.println("PPP Disconnected"); + break; + case ARDUINO_EVENT_PPP_STOP: + Serial.println("PPP Stopped"); + break; + default: + break; + } +} + +void testClient(const char* host, uint16_t port) { + NetworkClient client; + if (!client.connect(host, port)) { + Serial.println("Connection Failed"); + return; + } + client.printf("GET / HTTP/1.1\r\nHost: %s\r\n\r\n", host); + while (client.connected() && !client.available()) + ; + while (client.available()) { + client.read(); //Serial.write(client.read()); + } + + Serial.println("Connection Success"); + client.stop(); +} + +void setup() { + Serial.begin(115200); + + // Listen for modem events + Network.onEvent(onEvent); + + // Configure the modem + PPP.setApn(PPP_MODEM_APN); + PPP.setPin(PPP_MODEM_PIN); + PPP.setResetPin(PPP_MODEM_RST, PPP_MODEM_RST_LOW); + PPP.setPins(PPP_MODEM_TX, PPP_MODEM_RX, PPP_MODEM_RTS, PPP_MODEM_CTS, PPP_MODEM_FC); + + Serial.println("Starting the modem. It might take a while!"); + PPP.begin(PPP_MODEM_MODEL); + + Serial.print("Manufacturer: "); + Serial.println(PPP.cmd("AT+CGMI", 10000)); + Serial.print("Model: "); + Serial.println(PPP.moduleName()); + Serial.print("IMEI: "); + Serial.println(PPP.IMEI()); + + bool attached = PPP.attached(); + if (!attached) { + int i = 0; + unsigned int s = millis(); + Serial.print("Waiting to connect to network"); + while (!attached && ((++i) < 600)) { + Serial.print("."); + delay(100); + attached = PPP.attached(); + } + Serial.print((millis() - s) / 1000.0, 1); + Serial.println("s"); + attached = PPP.attached(); + } + + Serial.print("Attached: "); + Serial.println(attached); + Serial.print("State: "); + Serial.println(PPP.radioState()); + if (attached) { + Serial.print("Operator: "); + Serial.println(PPP.operatorName()); + Serial.print("IMSI: "); + Serial.println(PPP.IMSI()); + Serial.print("RSSI: "); + Serial.println(PPP.RSSI()); + int ber = PPP.BER(); + if (ber > 0) { + Serial.print("BER: "); + Serial.println(ber); + Serial.print("NetMode: "); + Serial.println(PPP.networkMode()); + } + + Serial.println("Switching to data mode..."); + PPP.mode(ESP_MODEM_MODE_CMUX); // Data and Command mixed mode + if (!PPP.waitStatusBits(ESP_NETIF_CONNECTED_BIT, 1000)) { + Serial.println("Failed to connect to internet!"); + } else { + Serial.println("Connected to internet!"); + } + } else { + Serial.println("Failed to connect to network!"); + } +} + +void loop() { + if (PPP.connected()) { + testClient("google.com", 80); + } + delay(20000); +} diff --git a/libraries/PPP/library.properties b/libraries/PPP/library.properties new file mode 100644 index 00000000000..abc4fb21a71 --- /dev/null +++ b/libraries/PPP/library.properties @@ -0,0 +1,9 @@ +name=PPP +version=1.0.0 +author=Hristo Gochkov +maintainer=Hristo Gochkov +sentence=Enables network connection using GSM Modem. +paragraph=With this library you can instantiate Servers, Clients and send/receive UDP packets through GSM Modem. +category=Communication +url= +architectures=esp32 diff --git a/libraries/PPP/src/PPP.cpp b/libraries/PPP/src/PPP.cpp new file mode 100644 index 00000000000..2f47582e291 --- /dev/null +++ b/libraries/PPP/src/PPP.cpp @@ -0,0 +1,792 @@ +#define ARDUINO_CORE_BUILD +#include "PPP.h" +#if CONFIG_LWIP_PPP_SUPPORT +#include "esp32-hal-periman.h" +#include "esp_netif.h" +#include "esp_netif_ppp.h" +#include +#include "driver/uart.h" +#include "hal/uart_ll.h" + +typedef struct { + void *arg; +} PdpContext; +#include "esp_modem_api.h" + +// Because of how esp_modem functions are declared, we need to workaround some APIs that take strings as input (output works OK) +// Following APIs work only when called through this interface +extern "C" { + esp_err_t _esp_modem_at(esp_modem_dce_t *dce_wrap, const char *at, char *p_out, int timeout); + esp_err_t _esp_modem_at_raw(esp_modem_dce_t *dce_wrap, const char *cmd, char *p_out, const char *pass, const char *fail, int timeout); + esp_err_t _esp_modem_send_sms(esp_modem_dce_t *dce_wrap, const char *number, const char *message); + esp_err_t _esp_modem_set_pin(esp_modem_dce_t *dce_wrap, const char *pin); + esp_err_t _esp_modem_set_operator(esp_modem_dce_t *dce_wrap, int mode, int format, const char *oper); + esp_err_t _esp_modem_set_network_bands(esp_modem_dce_t *dce_wrap, const char *mode, const int *bands, int size); +}; + +static PPPClass *_esp_modem = NULL; +static esp_event_handler_instance_t _ppp_ev_instance = NULL; + +#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_VERBOSE +static const char *_ppp_event_name(int32_t event_id) { + switch (event_id) { + case NETIF_PPP_ERRORNONE: return "No error."; + case NETIF_PPP_ERRORPARAM: return "Invalid parameter."; + case NETIF_PPP_ERROROPEN: return "Unable to open PPP session."; + case NETIF_PPP_ERRORDEVICE: return "Invalid I/O device for PPP."; + case NETIF_PPP_ERRORALLOC: return "Unable to allocate resources."; + case NETIF_PPP_ERRORUSER: return "User interrupt."; + case NETIF_PPP_ERRORCONNECT: return "Connection lost."; + case NETIF_PPP_ERRORAUTHFAIL: return "Failed authentication challenge."; + case NETIF_PPP_ERRORPROTOCOL: return "Failed to meet protocol."; + case NETIF_PPP_ERRORPEERDEAD: return "Connection timeout"; + case NETIF_PPP_ERRORIDLETIMEOUT: return "Idle Timeout"; + case NETIF_PPP_ERRORCONNECTTIME: return "Max connect time reached"; + case NETIF_PPP_ERRORLOOPBACK: return "Loopback detected"; + case NETIF_PPP_PHASE_DEAD: return "Phase Dead"; + case NETIF_PPP_PHASE_MASTER: return "Phase Master"; + case NETIF_PPP_PHASE_HOLDOFF: return "Phase Hold Off"; + case NETIF_PPP_PHASE_INITIALIZE: return "Phase Initialize"; + case NETIF_PPP_PHASE_SERIALCONN: return "Phase Serial Conn"; + case NETIF_PPP_PHASE_DORMANT: return "Phase Dormant"; + case NETIF_PPP_PHASE_ESTABLISH: return "Phase Establish"; + case NETIF_PPP_PHASE_AUTHENTICATE: return "Phase Authenticate"; + case NETIF_PPP_PHASE_CALLBACK: return "Phase Callback"; + case NETIF_PPP_PHASE_NETWORK: return "Phase Network"; + case NETIF_PPP_PHASE_RUNNING: return "Phase Running"; + case NETIF_PPP_PHASE_TERMINATE: return "Phase Terminate"; + case NETIF_PPP_PHASE_DISCONNECT: return "Phase Disconnect"; + case NETIF_PPP_CONNECT_FAILED: return "Connect Failed"; + default: break; + } + return "UNKNOWN"; +} + +static const char *_ppp_terminal_error_name(esp_modem_terminal_error_t err) { + switch (err) { + case ESP_MODEM_TERMINAL_BUFFER_OVERFLOW: return "Buffer Overflow"; + case ESP_MODEM_TERMINAL_CHECKSUM_ERROR: return "Checksum Error"; + case ESP_MODEM_TERMINAL_UNEXPECTED_CONTROL_FLOW: return "Unexpected Control Flow"; + case ESP_MODEM_TERMINAL_DEVICE_GONE: return "Device Gone"; + case ESP_MODEM_TERMINAL_UNKNOWN_ERROR: return "Unknown Error"; + default: break; + } + return "UNKNOWN"; +} +#endif + +static void _ppp_event_cb(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data) { + if (event_base == NETIF_PPP_STATUS) { + if (_esp_modem != NULL) { + _esp_modem->_onPppEvent(event_id, event_data); + } + } +} + +static void onPppArduinoEvent(arduino_event_id_t event, arduino_event_info_t info) { + if (event >= ARDUINO_EVENT_PPP_START && event <= ARDUINO_EVENT_PPP_GOT_IP6) { + _esp_modem->_onPppArduinoEvent(event, info); + } +} + +// PPP Error Callback +static void _ppp_error_cb(esp_modem_terminal_error_t err) { + log_v("PPP Driver Error %ld: %s", err, _ppp_terminal_error_name(err)); +} + +// PPP Arduino Events Callback +void PPPClass::_onPppArduinoEvent(arduino_event_id_t event, arduino_event_info_t info) { + log_v("PPP Arduino Event %ld: %s", event, Network.eventName(event)); + // if(event == ARDUINO_EVENT_PPP_GOT_IP){ + // if((getStatusBits() & ESP_NETIF_CONNECTED_BIT) == 0){ + // setStatusBits(ESP_NETIF_CONNECTED_BIT); + // arduino_event_t arduino_event; + // arduino_event.event_id = ARDUINO_EVENT_PPP_CONNECTED; + // Network.postEvent(&arduino_event); + // } + // } else + if (event == ARDUINO_EVENT_PPP_LOST_IP) { + if ((getStatusBits() & ESP_NETIF_CONNECTED_BIT) != 0) { + clearStatusBits(ESP_NETIF_CONNECTED_BIT); + arduino_event_t arduino_event; + arduino_event.event_id = ARDUINO_EVENT_PPP_DISCONNECTED; + Network.postEvent(&arduino_event); + } + } +} + +// PPP Driver Events Callback +void PPPClass::_onPppEvent(int32_t event, void *event_data) { + arduino_event_t arduino_event; + arduino_event.event_id = ARDUINO_EVENT_MAX; + + log_v("PPP Driver Event %ld: %s", event, _ppp_event_name(event)); + + if (event == NETIF_PPP_ERRORNONE) { + if ((getStatusBits() & ESP_NETIF_CONNECTED_BIT) == 0) { + setStatusBits(ESP_NETIF_CONNECTED_BIT); + arduino_event_t arduino_event; + arduino_event.event_id = ARDUINO_EVENT_PPP_CONNECTED; + Network.postEvent(&arduino_event); + } + } + + if (arduino_event.event_id < ARDUINO_EVENT_MAX) { + Network.postEvent(&arduino_event); + } +} + +esp_modem_dce_t *PPPClass::handle() const { + return _dce; +} + +PPPClass::PPPClass() + : _dce(NULL), _pin_tx(-1), _pin_rx(-1), _pin_rts(-1), _pin_cts(-1), _flow_ctrl(ESP_MODEM_FLOW_CONTROL_NONE), _pin_rst(-1), _pin_rst_act_low(true), _pin(NULL), _apn(NULL), _rx_buffer_size(4096), _tx_buffer_size(512), _mode(ESP_MODEM_MODE_COMMAND), _uart_num(UART_NUM_1) { +} + +PPPClass::~PPPClass() {} + +bool PPPClass::pppDetachBus(void *bus_pointer) { + PPPClass *bus = (PPPClass *)bus_pointer; + bus->end(); + return true; +} + +void PPPClass::setResetPin(int8_t rst, bool active_low) { + _pin_rst = digitalPinToGPIONumber(rst); + _pin_rst_act_low = active_low; +} + +bool PPPClass::setPins(int8_t tx, int8_t rx, int8_t rts, int8_t cts, esp_modem_flow_ctrl_t flow_ctrl) { + perimanSetBusDeinit(ESP32_BUS_TYPE_PPP_TX, PPPClass::pppDetachBus); + perimanSetBusDeinit(ESP32_BUS_TYPE_PPP_RX, PPPClass::pppDetachBus); + perimanSetBusDeinit(ESP32_BUS_TYPE_PPP_RTS, PPPClass::pppDetachBus); + perimanSetBusDeinit(ESP32_BUS_TYPE_PPP_CTS, PPPClass::pppDetachBus); + + if (_pin_tx >= 0) { + if (!perimanClearPinBus(_pin_tx)) { return false; } + } + if (_pin_rx >= 0) { + if (!perimanClearPinBus(_pin_rx)) { return false; } + } + if (_pin_rts >= 0) { + if (!perimanClearPinBus(_pin_rts)) { return false; } + } + if (_pin_cts >= 0) { + if (!perimanClearPinBus(_pin_cts)) { return false; } + } + + _flow_ctrl = flow_ctrl; + _pin_tx = digitalPinToGPIONumber(tx); + _pin_rx = digitalPinToGPIONumber(rx); + _pin_rts = digitalPinToGPIONumber(rts); + _pin_cts = digitalPinToGPIONumber(cts); + + if (_pin_tx >= 0) { + if (!perimanSetPinBus(_pin_tx, ESP32_BUS_TYPE_PPP_TX, (void *)(this), -1, -1)) { return false; } + } + if (_pin_rx >= 0) { + if (!perimanSetPinBus(_pin_rx, ESP32_BUS_TYPE_PPP_RX, (void *)(this), -1, -1)) { return false; } + } + if (_pin_rts >= 0) { + if (!perimanSetPinBus(_pin_rts, ESP32_BUS_TYPE_PPP_RTS, (void *)(this), -1, -1)) { return false; } + } + if (_pin_cts >= 0) { + if (!perimanSetPinBus(_pin_cts, ESP32_BUS_TYPE_PPP_CTS, (void *)(this), -1, -1)) { return false; } + } + return true; +} + +bool PPPClass::begin(ppp_modem_model_t model, uint8_t uart_num, int baud_rate) { + esp_err_t ret = ESP_OK; + bool pin_ok = false; + int trys = 0; + + if (_esp_netif != NULL || _dce != NULL) { + log_w("PPP Already Started"); + return true; + } + + if (_apn == NULL) { + log_e("APN is not set. Call 'PPP.setApn()' first"); + return false; + } + + if (_pin_tx < 0 || _pin_rx < 0) { + log_e("UART pins not set. Call 'PPP.setPins()' first"); + return false; + } + + if ((_pin_rts < 0 || _pin_cts < 0) && (_flow_ctrl != ESP_MODEM_FLOW_CONTROL_NONE)) { + log_e("UART CTS/RTS pins not set, but flow control is enabled!"); + return false; + } + + _uart_num = uart_num; + _esp_modem = this; + + Network.begin(); + + /* Listen for PPP status events */ + if (_ppp_ev_instance == NULL && esp_event_handler_instance_register(NETIF_PPP_STATUS, ESP_EVENT_ANY_ID, &_ppp_event_cb, NULL, &_ppp_ev_instance)) { + log_e("event_handler_instance_register for NETIF_PPP_STATUS Failed!"); + return false; + } + + /* Configure the PPP netif */ + esp_netif_config_t cfg = ESP_NETIF_DEFAULT_PPP(); + _esp_netif = esp_netif_new(&cfg); + if (_esp_netif == NULL) { + log_e("esp_netif_new failed"); + return false; + } + + /* Attach to receive IP events */ + initNetif(ESP_NETIF_ID_PPP); + + /* Configure the DTE */ + esp_modem_dte_config_t dte_config = ESP_MODEM_DTE_DEFAULT_CONFIG(); + dte_config.uart_config.tx_io_num = _pin_tx; + dte_config.uart_config.rx_io_num = _pin_rx; + dte_config.uart_config.rts_io_num = _pin_rts; + dte_config.uart_config.cts_io_num = _pin_cts; + dte_config.uart_config.flow_control = _flow_ctrl; + dte_config.uart_config.rx_buffer_size = _rx_buffer_size; + dte_config.uart_config.tx_buffer_size = _tx_buffer_size; + dte_config.uart_config.port_num = _uart_num; + dte_config.uart_config.baud_rate = baud_rate; + + /* Configure the DCE */ + esp_modem_dce_config_t dce_config = ESP_MODEM_DCE_DEFAULT_CONFIG(_apn); + + /* Reset the Modem */ + if (_pin_rst >= 0) { + log_v("Resetting the modem"); + if (_pin_rst_act_low) { + pinMode(_pin_rst, OUTPUT_OPEN_DRAIN); + } else { + pinMode(_pin_rst, OUTPUT); + } + digitalWrite(_pin_rst, !_pin_rst_act_low); + delay(200); + digitalWrite(_pin_rst, _pin_rst_act_low); + delay(100); + } + + /* Start the DCE */ + _dce = esp_modem_new_dev((esp_modem_dce_device_t)model, &dte_config, &dce_config, _esp_netif); + if (_dce == NULL) { + log_e("esp_modem_new_dev failed"); + goto err; + } + + esp_modem_set_error_cb(_dce, _ppp_error_cb); + + /* Wait for Modem to respond */ + if (_pin_rst >= 0) { + // wait to be able to talk to the modem + log_v("Waiting for response from the modem"); + while (esp_modem_sync(_dce) != ESP_OK && trys < 100) { + trys++; + delay(500); + } + if (trys >= 100) { + log_e("Failed to wait for communication"); + goto err; + } + } else { + // try to communicate with the modem + if (esp_modem_sync(_dce) != ESP_OK) { + log_v("Modem does not respond to AT, maybe in DATA mode? ...exiting network mode"); + esp_modem_set_mode(_dce, ESP_MODEM_MODE_COMMAND); + if (esp_modem_sync(_dce) != ESP_OK) { + log_e("Modem failed to respond to AT!"); + goto err; + } + } + } + + /* enable flow control */ + if (dte_config.uart_config.flow_control == ESP_MODEM_FLOW_CONTROL_HW) { + ret = esp_modem_set_flow_control(_dce, 2, 2); //2/2 means HW Flow Control. + if (ret != ESP_OK) { + log_e("Failed to set the hardware flow control: [%d] %s", ret, esp_err_to_name(ret)); + goto err; + } + } + + /* check if PIN needed */ + if (esp_modem_read_pin(_dce, pin_ok) == ESP_OK && pin_ok == false) { + if (_pin == NULL || _esp_modem_set_pin(_dce, _pin) != ESP_OK) { + log_e("PIN verification failed!"); + goto err; + } + } + + Network.onSysEvent(onPppArduinoEvent); + + setStatusBits(ESP_NETIF_STARTED_BIT); + arduino_event_t arduino_event; + arduino_event.event_id = ARDUINO_EVENT_PPP_START; + Network.postEvent(&arduino_event); + + return true; + +err: + PPPClass::pppDetachBus((void *)(this)); + return false; +} + +void PPPClass::end(void) { + if (_esp_modem && _esp_netif && _dce) { + + if ((getStatusBits() & ESP_NETIF_CONNECTED_BIT) != 0) { + clearStatusBits(ESP_NETIF_CONNECTED_BIT | ESP_NETIF_HAS_IP_BIT | ESP_NETIF_HAS_LOCAL_IP6_BIT | ESP_NETIF_HAS_GLOBAL_IP6_BIT); + arduino_event_t disconnect_event; + disconnect_event.event_id = ARDUINO_EVENT_PPP_DISCONNECTED; + Network.postEvent(&disconnect_event); + } + + clearStatusBits(ESP_NETIF_STARTED_BIT | ESP_NETIF_CONNECTED_BIT | ESP_NETIF_HAS_IP_BIT | ESP_NETIF_HAS_LOCAL_IP6_BIT | ESP_NETIF_HAS_GLOBAL_IP6_BIT | ESP_NETIF_HAS_STATIC_IP_BIT); + arduino_event_t arduino_event; + arduino_event.event_id = ARDUINO_EVENT_PPP_STOP; + Network.postEvent(&arduino_event); + } + + destroyNetif(); + + if (_ppp_ev_instance != NULL) { + if (esp_event_handler_unregister(NETIF_PPP_STATUS, ESP_EVENT_ANY_ID, &_ppp_event_cb) == ESP_OK) { + _ppp_ev_instance = NULL; + } + } + _esp_modem = NULL; + + Network.removeEvent(onPppArduinoEvent); + + if (_dce != NULL) { + esp_modem_destroy(_dce); + _dce = NULL; + } + + int8_t pin = -1; + if (_pin_tx != -1) { + pin = _pin_tx; + _pin_tx = -1; + perimanClearPinBus(pin); + } + if (_pin_rx != -1) { + pin = _pin_rx; + _pin_rx = -1; + perimanClearPinBus(pin); + } + if (_pin_rts != -1) { + pin = _pin_rts; + _pin_rts = -1; + perimanClearPinBus(pin); + } + if (_pin_cts != -1) { + pin = _pin_cts; + _pin_cts = -1; + perimanClearPinBus(pin); + } + + _mode = ESP_MODEM_MODE_COMMAND; +} + +bool PPPClass::sync() const { + if (_dce == NULL) { + return false; + } + + if (_mode == ESP_MODEM_MODE_DATA) { + log_e("Wrong modem mode. Should be ESP_MODEM_MODE_COMMAND"); + return false; + } + return esp_modem_sync(_dce) == ESP_OK; +} + +bool PPPClass::attached() const { + if (_dce == NULL) { + return false; + } + + if (_mode == ESP_MODEM_MODE_DATA) { + log_e("Wrong modem mode. Should be ESP_MODEM_MODE_COMMAND"); + return false; + } + + int m = 0; + esp_err_t err = esp_modem_get_network_attachment_state(_dce, m); + if (err != ESP_OK) { + // log_e("esp_modem_get_network_attachment_state failed with %d %s", err, esp_err_to_name(err)); + return false; + } + return m != 0; +} + +bool PPPClass::mode(esp_modem_dce_mode_t m) { + if (_dce == NULL) { + return 0; + } + + if (_mode == m) { + return true; + } + esp_err_t err = esp_modem_set_mode(_dce, m); + if (err != ESP_OK) { + log_e("esp_modem_set_mode failed with %d %s", err, esp_err_to_name(err)); + return false; + } + _mode = m; + return true; +} + +bool PPPClass::setApn(const char *apn) { + if (_apn != NULL) { + free((void *)_apn); + _apn = NULL; + } + if (apn != NULL) { + _apn = strdup(apn); + if (_apn == NULL) { + log_e("Failed to strdup APN"); + return false; + } + } + return true; +} + +bool PPPClass::setPin(const char *pin) { + if (_pin != NULL) { + free((void *)_pin); + _pin = NULL; + } + if (pin != NULL) { + for (int i = 0; i < strlen(pin); i++) { + if (pin[i] < 0x30 || pin[i] > 0x39) { + log_e("Bad character '%c' in PIN. Should be only digits", pin[i]); + return false; + } + } + _pin = strdup(pin); + if (_pin == NULL) { + log_e("Failed to strdup PIN"); + return false; + } + } + return true; +} + +int PPPClass::RSSI() const { + if (_dce == NULL) { + return -1; + } + + if (_mode == ESP_MODEM_MODE_DATA) { + log_e("Wrong modem mode. Should be ESP_MODEM_MODE_COMMAND"); + return -1; + } + + int rssi, ber; + esp_err_t err = esp_modem_get_signal_quality(_dce, rssi, ber); + if (err != ESP_OK) { + // log_e("esp_modem_get_signal_quality failed with %d %s", err, esp_err_to_name(err)); + return -1; + } + return rssi; +} + +int PPPClass::BER() const { + if (_dce == NULL) { + return -1; + } + + if (_mode == ESP_MODEM_MODE_DATA) { + log_e("Wrong modem mode. Should be ESP_MODEM_MODE_COMMAND"); + return -1; + } + + int rssi, ber; + esp_err_t err = esp_modem_get_signal_quality(_dce, rssi, ber); + if (err != ESP_OK) { + // log_e("esp_modem_get_signal_quality failed with %d %s", err, esp_err_to_name(err)); + return -1; + } + return ber; +} + +String PPPClass::IMSI() const { + if (_dce == NULL) { + return String(); + } + + if (_mode == ESP_MODEM_MODE_DATA) { + log_e("Wrong modem mode. Should be ESP_MODEM_MODE_COMMAND"); + return String(); + } + + char imsi[32]; + esp_err_t err = esp_modem_get_imsi(_dce, (std::string &)imsi); + if (err != ESP_OK) { + log_e("esp_modem_get_imsi failed with %d %s", err, esp_err_to_name(err)); + return String(); + } + + return String(imsi); +} + +String PPPClass::IMEI() const { + if (_dce == NULL) { + return String(); + } + + if (_mode == ESP_MODEM_MODE_DATA) { + log_e("Wrong modem mode. Should be ESP_MODEM_MODE_COMMAND"); + return String(); + } + + char imei[32]; + esp_err_t err = esp_modem_get_imei(_dce, (std::string &)imei); + if (err != ESP_OK) { + log_e("esp_modem_get_imei failed with %d %s", err, esp_err_to_name(err)); + return String(); + } + + return String(imei); +} + +String PPPClass::moduleName() const { + if (_dce == NULL) { + return String(); + } + + if (_mode == ESP_MODEM_MODE_DATA) { + log_e("Wrong modem mode. Should be ESP_MODEM_MODE_COMMAND"); + return String(); + } + + char name[32]; + esp_err_t err = esp_modem_get_module_name(_dce, (std::string &)name); + if (err != ESP_OK) { + log_e("esp_modem_get_module_name failed with %d %s", err, esp_err_to_name(err)); + return String(); + } + + return String(name); +} + +String PPPClass::operatorName() const { + if (_dce == NULL) { + return String(); + } + + if (_mode == ESP_MODEM_MODE_DATA) { + log_e("Wrong modem mode. Should be ESP_MODEM_MODE_COMMAND"); + return String(); + } + + char oper[32]; + int act = 0; + esp_err_t err = esp_modem_get_operator_name(_dce, (std::string &)oper, act); + if (err != ESP_OK) { + log_e("esp_modem_get_operator_name failed with %d %s", err, esp_err_to_name(err)); + return String(); + } + + return String(oper); +} + +int PPPClass::networkMode() const { + if (_dce == NULL) { + return -1; + } + + if (_mode == ESP_MODEM_MODE_DATA) { + log_e("Wrong modem mode. Should be ESP_MODEM_MODE_COMMAND"); + return -1; + } + + int m = 0; + esp_err_t err = esp_modem_get_network_system_mode(_dce, m); + if (err != ESP_OK) { + log_e("esp_modem_get_network_system_mode failed with %d %s", err, esp_err_to_name(err)); + return -1; + } + return m; +} + +int PPPClass::radioState() const { + if (_dce == NULL) { + return -1; + } + + if (_mode == ESP_MODEM_MODE_DATA) { + log_e("Wrong modem mode. Should be ESP_MODEM_MODE_COMMAND"); + return -1; + } + + int m = 0; + esp_err_t err = esp_modem_get_radio_state(_dce, m); + if (err != ESP_OK) { + // log_e("esp_modem_get_radio_state failed with %d %s", err, esp_err_to_name(err)); + return -1; + } + return m; +} + +bool PPPClass::powerDown() { + if (_dce == NULL) { + return false; + } + + if (_mode == ESP_MODEM_MODE_DATA) { + log_e("Wrong modem mode. Should be ESP_MODEM_MODE_COMMAND"); + return false; + } + + esp_err_t err = esp_modem_power_down(_dce); + if (err != ESP_OK) { + log_e("esp_modem_power_down failed with %d %s", err, esp_err_to_name(err)); + return false; + } + return true; +} + +bool PPPClass::reset() { + if (_dce == NULL) { + return false; + } + + if (_mode == ESP_MODEM_MODE_DATA) { + log_e("Wrong modem mode. Should be ESP_MODEM_MODE_COMMAND"); + return false; + } + + esp_err_t err = esp_modem_reset(_dce); + if (err != ESP_OK) { + log_e("esp_modem_reset failed with %d %s", err, esp_err_to_name(err)); + return false; + } + return true; +} + +bool PPPClass::storeProfile() { + if (_dce == NULL) { + return false; + } + + if (_mode == ESP_MODEM_MODE_DATA) { + log_e("Wrong modem mode. Should be ESP_MODEM_MODE_COMMAND"); + return false; + } + + esp_err_t err = esp_modem_store_profile(_dce); + if (err != ESP_OK) { + log_e("esp_modem_store_profile failed with %d %s", err, esp_err_to_name(err)); + return false; + } + return true; +} + +bool PPPClass::setBaudrate(int baudrate) { + if (_dce == NULL) { + return false; + } + + if (_mode == ESP_MODEM_MODE_DATA) { + log_e("Wrong modem mode. Should be ESP_MODEM_MODE_COMMAND"); + return false; + } + + esp_err_t err = esp_modem_set_baud(_dce, baudrate); + if (err != ESP_OK) { + log_e("esp_modem_set_baud failed with %d %s", err, esp_err_to_name(err)); + return false; + } + + uint32_t sclk_freq; + err = uart_get_sclk_freq(UART_SCLK_DEFAULT, &sclk_freq); + if (err != ESP_OK) { + log_e("uart_get_sclk_freq failed with %d %s", err, esp_err_to_name(err)); + return false; + } + uart_ll_set_baudrate(UART_LL_GET_HW(_uart_num), (uint32_t)baudrate, sclk_freq); + + return true; +} + +bool PPPClass::sms(const char *num, const char *message) { + if (_dce == NULL) { + return false; + } + + if (_mode == ESP_MODEM_MODE_DATA) { + log_e("Wrong modem mode. Should be ESP_MODEM_MODE_COMMAND"); + return false; + } + + for (int i = 0; i < strlen(num); i++) { + if (num[i] != '+' && num[i] != '#' && num[i] != '*' && (num[i] < 0x30 || num[i] > 0x39)) { + log_e("Bad character '%c' in SMS Number. Should be only digits and +, # or *", num[i]); + return false; + } + } + + esp_err_t err = esp_modem_sms_txt_mode(_dce, true); + if (err != ESP_OK) { + log_e("Setting text mode failed %d %s", err, esp_err_to_name(err)); + return false; + } + + err = esp_modem_sms_character_set(_dce); + if (err != ESP_OK) { + log_e("Setting GSM character set failed %d %s", err, esp_err_to_name(err)); + return false; + } + + err = _esp_modem_send_sms(_dce, num, message); + if (err != ESP_OK) { + log_e("esp_modem_send_sms() failed with %d %s", err, esp_err_to_name(err)); + return false; + } + return true; +} + +String PPPClass::cmd(const char *at_command, int timeout) { + if (_dce == NULL) { + return String(); + } + + if (_mode == ESP_MODEM_MODE_DATA) { + log_e("Wrong modem mode. Should be ESP_MODEM_MODE_COMMAND"); + return String(); + } + char out[128] = { 0 }; + esp_err_t err = _esp_modem_at(_dce, at_command, out, timeout); + if (err != ESP_OK) { + log_e("esp_modem_at failed %d %s", err, esp_err_to_name(err)); + return String(); + } + return String(out); +} + +size_t PPPClass::printDriverInfo(Print &out) const { + size_t bytes = 0; + if (_dce == NULL || _mode == ESP_MODEM_MODE_DATA) { + return bytes; + } + if (attached()) { + bytes += out.print(","); + bytes += out.print(operatorName()); + } + bytes += out.print(",RSSI:"); + bytes += out.print(RSSI()); + bytes += out.print(",BER:"); + bytes += out.print(BER()); + return bytes; +} + +PPPClass PPP; + +#endif /* CONFIG_LWIP_PPP_SUPPORT */ diff --git a/libraries/PPP/src/PPP.h b/libraries/PPP/src/PPP.h new file mode 100644 index 00000000000..0333aaf6b0c --- /dev/null +++ b/libraries/PPP/src/PPP.h @@ -0,0 +1,109 @@ +#pragma once + +#include "sdkconfig.h" +#if CONFIG_LWIP_PPP_SUPPORT +#include "Network.h" +#include "esp_modem_c_api_types.h" + +typedef enum { + PPP_MODEM_GENERIC = ESP_MODEM_DCE_GENETIC, + PPP_MODEM_SIM7600 = ESP_MODEM_DCE_SIM7600, + PPP_MODEM_SIM7070 = ESP_MODEM_DCE_SIM7070, + PPP_MODEM_SIM7000 = ESP_MODEM_DCE_SIM7000, + PPP_MODEM_BG96 = ESP_MODEM_DCE_BG96, + PPP_MODEM_SIM800 = ESP_MODEM_DCE_SIM800, +#if CONFIG_ESP_MODEM_ADD_CUSTOM_MODULE + PPP_MODEM_CUSTOM = ESP_MODEM_DCE_CUSTOM, +#endif + PPP_MODEM_MAX +} ppp_modem_model_t; + +class PPPClass : public NetworkInterface { +public: + PPPClass(); + ~PPPClass(); + + bool begin(ppp_modem_model_t model, uint8_t uart_num = 1, int baud_rate = 115200); + void end(); + + // Required for connecting to internet + bool setApn(const char* apn); + + // Required only if the SIM card is protected by PIN + bool setPin(const char* pin); + + // If the modem supports hardware flow control, it's best to use it + bool setPins(int8_t tx, int8_t rx, int8_t rts = -1, int8_t cts = -1, esp_modem_flow_ctrl_t flow_ctrl = ESP_MODEM_FLOW_CONTROL_NONE); + + // Using the reset pin of the module ensures that proper communication can be achieved + void setResetPin(int8_t rst, bool active_low = true); + + // Modem DCE APIs + int RSSI() const; + int BER() const; + String IMSI() const; + String IMEI() const; + String moduleName() const; // modem module name + String operatorName() const; // network operator name + int networkMode() const; // network type (GSM, LTE, etc.) + int radioState() const; // 0:minimal, 1:full + bool attached() const; // true is attached to network + bool sync() const; // true if responds to 'AT' + + // Switch the communication mode + bool mode(esp_modem_dce_mode_t m); + esp_modem_dce_mode_t mode() const { + return _mode; + } + + // Change temporary the baud rate of communication + bool setBaudrate(int baudrate); + + // Sens SMS message to a number + bool sms(const char* num, const char* message); + bool sms(String num, String message) { + return sms(num.c_str(), message.c_str()); + } + + // Send AT command with timeout in milliseconds + String cmd(const char* at_command, int timeout); + String cmd(String at_command, int timeout) { + return cmd(at_command.c_str(), timeout); + } + + // untested + bool powerDown(); + bool reset(); + bool storeProfile(); + + esp_modem_dce_t* handle() const; + +protected: + size_t printDriverInfo(Print& out) const; + +public: + void _onPppEvent(int32_t event_id, void* event_data); + void _onPppArduinoEvent(arduino_event_id_t event, arduino_event_info_t info); + +private: + esp_modem_dce_t* _dce; + int8_t _pin_tx; + int8_t _pin_rx; + int8_t _pin_rts; + int8_t _pin_cts; + esp_modem_flow_ctrl_t _flow_ctrl; + int8_t _pin_rst; + bool _pin_rst_act_low; + const char* _pin; + const char* _apn; + int _rx_buffer_size; + int _tx_buffer_size; + esp_modem_dce_mode_t _mode; + uint8_t _uart_num; + + static bool pppDetachBus(void* bus_pointer); +}; + +extern PPPClass PPP; + +#endif /* CONFIG_LWIP_PPP_SUPPORT */ diff --git a/libraries/PPP/src/ppp.c b/libraries/PPP/src/ppp.c new file mode 100644 index 00000000000..db8ba0760bd --- /dev/null +++ b/libraries/PPP/src/ppp.c @@ -0,0 +1,28 @@ +#include "sdkconfig.h" +#if CONFIG_LWIP_PPP_SUPPORT +#include "esp_modem_api.h" + +esp_err_t _esp_modem_at(esp_modem_dce_t *dce_wrap, const char *at, char *p_out, int timeout) { + return esp_modem_at(dce_wrap, at, p_out, timeout); +} + +esp_err_t _esp_modem_send_sms(esp_modem_dce_t *dce_wrap, const char *number, const char *message) { + return esp_modem_send_sms(dce_wrap, number, message); +} + +esp_err_t _esp_modem_set_pin(esp_modem_dce_t *dce_wrap, const char *pin) { + return esp_modem_set_pin(dce_wrap, pin); +} + +esp_err_t _esp_modem_at_raw(esp_modem_dce_t *dce_wrap, const char *cmd, char *p_out, const char *pass, const char *fail, int timeout) { + return esp_modem_at_raw(dce_wrap, cmd, p_out, pass, fail, timeout); +} + +esp_err_t _esp_modem_set_operator(esp_modem_dce_t *dce_wrap, int mode, int format, const char *oper) { + return esp_modem_set_operator(dce_wrap, mode, format, oper); +} + +esp_err_t _esp_modem_set_network_bands(esp_modem_dce_t *dce_wrap, const char *mode, const int *bands, int size) { + return esp_modem_set_network_bands(dce_wrap, mode, bands, size); +} +#endif // CONFIG_LWIP_PPP_SUPPORT diff --git a/package/package_esp32_index.template.json b/package/package_esp32_index.template.json index 45b278d9b0a..a1fb157c99e 100644 --- a/package/package_esp32_index.template.json +++ b/package/package_esp32_index.template.json @@ -42,7 +42,7 @@ { "packager": "esp32", "name": "esp32-arduino-libs", - "version": "idf-release_v5.1-c432c692fa" + "version": "idf--c432c692fa" }, { "packager": "esp32", @@ -105,63 +105,63 @@ "tools": [ { "name": "esp32-arduino-libs", - "version": "idf-release_v5.1-c432c692fa", + "version": "idf--c432c692fa", "systems": [ { "host": "i686-mingw32", - "url": "https://codeload.github.com/espressif/esp32-arduino-libs/zip/ad1f97a1623c5c41a0db40a1def6d3fb8548a37d", - "archiveFileName": "esp32-arduino-libs-ad1f97a1623c5c41a0db40a1def6d3fb8548a37d.zip", - "checksum": "SHA-256:08790776b0351d9ef820777b6630514fd96b9ee28e894af527b3bbb8141f38de", - "size": "358586091" + "url": "https://codeload.github.com/espressif/esp32-arduino-libs/zip/fbc464148f35fbcc0e93b17a7a21e25b035efedb", + "archiveFileName": "esp32-arduino-libs-fbc464148f35fbcc0e93b17a7a21e25b035efedb.zip", + "checksum": "SHA-256:bbf2d324c310e8a80e0a4c0c6b2464a7d0ffb2509ae2cc2d06e65a260f3d8bae", + "size": "371625301" }, { "host": "x86_64-mingw32", - "url": "https://codeload.github.com/espressif/esp32-arduino-libs/zip/ad1f97a1623c5c41a0db40a1def6d3fb8548a37d", - "archiveFileName": "esp32-arduino-libs-ad1f97a1623c5c41a0db40a1def6d3fb8548a37d.zip", - "checksum": "SHA-256:08790776b0351d9ef820777b6630514fd96b9ee28e894af527b3bbb8141f38de", - "size": "358586091" + "url": "https://codeload.github.com/espressif/esp32-arduino-libs/zip/fbc464148f35fbcc0e93b17a7a21e25b035efedb", + "archiveFileName": "esp32-arduino-libs-fbc464148f35fbcc0e93b17a7a21e25b035efedb.zip", + "checksum": "SHA-256:bbf2d324c310e8a80e0a4c0c6b2464a7d0ffb2509ae2cc2d06e65a260f3d8bae", + "size": "371625301" }, { "host": "arm64-apple-darwin", - "url": "https://codeload.github.com/espressif/esp32-arduino-libs/zip/ad1f97a1623c5c41a0db40a1def6d3fb8548a37d", - "archiveFileName": "esp32-arduino-libs-ad1f97a1623c5c41a0db40a1def6d3fb8548a37d.zip", - "checksum": "SHA-256:08790776b0351d9ef820777b6630514fd96b9ee28e894af527b3bbb8141f38de", - "size": "358586091" + "url": "https://codeload.github.com/espressif/esp32-arduino-libs/zip/fbc464148f35fbcc0e93b17a7a21e25b035efedb", + "archiveFileName": "esp32-arduino-libs-fbc464148f35fbcc0e93b17a7a21e25b035efedb.zip", + "checksum": "SHA-256:bbf2d324c310e8a80e0a4c0c6b2464a7d0ffb2509ae2cc2d06e65a260f3d8bae", + "size": "371625301" }, { "host": "x86_64-apple-darwin", - "url": "https://codeload.github.com/espressif/esp32-arduino-libs/zip/ad1f97a1623c5c41a0db40a1def6d3fb8548a37d", - "archiveFileName": "esp32-arduino-libs-ad1f97a1623c5c41a0db40a1def6d3fb8548a37d.zip", - "checksum": "SHA-256:08790776b0351d9ef820777b6630514fd96b9ee28e894af527b3bbb8141f38de", - "size": "358586091" + "url": "https://codeload.github.com/espressif/esp32-arduino-libs/zip/fbc464148f35fbcc0e93b17a7a21e25b035efedb", + "archiveFileName": "esp32-arduino-libs-fbc464148f35fbcc0e93b17a7a21e25b035efedb.zip", + "checksum": "SHA-256:bbf2d324c310e8a80e0a4c0c6b2464a7d0ffb2509ae2cc2d06e65a260f3d8bae", + "size": "371625301" }, { "host": "x86_64-pc-linux-gnu", - "url": "https://codeload.github.com/espressif/esp32-arduino-libs/zip/ad1f97a1623c5c41a0db40a1def6d3fb8548a37d", - "archiveFileName": "esp32-arduino-libs-ad1f97a1623c5c41a0db40a1def6d3fb8548a37d.zip", - "checksum": "SHA-256:08790776b0351d9ef820777b6630514fd96b9ee28e894af527b3bbb8141f38de", - "size": "358586091" + "url": "https://codeload.github.com/espressif/esp32-arduino-libs/zip/fbc464148f35fbcc0e93b17a7a21e25b035efedb", + "archiveFileName": "esp32-arduino-libs-fbc464148f35fbcc0e93b17a7a21e25b035efedb.zip", + "checksum": "SHA-256:bbf2d324c310e8a80e0a4c0c6b2464a7d0ffb2509ae2cc2d06e65a260f3d8bae", + "size": "371625301" }, { "host": "i686-pc-linux-gnu", - "url": "https://codeload.github.com/espressif/esp32-arduino-libs/zip/ad1f97a1623c5c41a0db40a1def6d3fb8548a37d", - "archiveFileName": "esp32-arduino-libs-ad1f97a1623c5c41a0db40a1def6d3fb8548a37d.zip", - "checksum": "SHA-256:08790776b0351d9ef820777b6630514fd96b9ee28e894af527b3bbb8141f38de", - "size": "358586091" + "url": "https://codeload.github.com/espressif/esp32-arduino-libs/zip/fbc464148f35fbcc0e93b17a7a21e25b035efedb", + "archiveFileName": "esp32-arduino-libs-fbc464148f35fbcc0e93b17a7a21e25b035efedb.zip", + "checksum": "SHA-256:bbf2d324c310e8a80e0a4c0c6b2464a7d0ffb2509ae2cc2d06e65a260f3d8bae", + "size": "371625301" }, { "host": "aarch64-linux-gnu", - "url": "https://codeload.github.com/espressif/esp32-arduino-libs/zip/ad1f97a1623c5c41a0db40a1def6d3fb8548a37d", - "archiveFileName": "esp32-arduino-libs-ad1f97a1623c5c41a0db40a1def6d3fb8548a37d.zip", - "checksum": "SHA-256:08790776b0351d9ef820777b6630514fd96b9ee28e894af527b3bbb8141f38de", - "size": "358586091" + "url": "https://codeload.github.com/espressif/esp32-arduino-libs/zip/fbc464148f35fbcc0e93b17a7a21e25b035efedb", + "archiveFileName": "esp32-arduino-libs-fbc464148f35fbcc0e93b17a7a21e25b035efedb.zip", + "checksum": "SHA-256:bbf2d324c310e8a80e0a4c0c6b2464a7d0ffb2509ae2cc2d06e65a260f3d8bae", + "size": "371625301" }, { "host": "arm-linux-gnueabihf", - "url": "https://codeload.github.com/espressif/esp32-arduino-libs/zip/ad1f97a1623c5c41a0db40a1def6d3fb8548a37d", - "archiveFileName": "esp32-arduino-libs-ad1f97a1623c5c41a0db40a1def6d3fb8548a37d.zip", - "checksum": "SHA-256:08790776b0351d9ef820777b6630514fd96b9ee28e894af527b3bbb8141f38de", - "size": "358586091" + "url": "https://codeload.github.com/espressif/esp32-arduino-libs/zip/fbc464148f35fbcc0e93b17a7a21e25b035efedb", + "archiveFileName": "esp32-arduino-libs-fbc464148f35fbcc0e93b17a7a21e25b035efedb.zip", + "checksum": "SHA-256:bbf2d324c310e8a80e0a4c0c6b2464a7d0ffb2509ae2cc2d06e65a260f3d8bae", + "size": "371625301" } ] },