Add files via upload

This commit is contained in:
levkovigor 2021-08-18 14:21:08 +03:00 committed by GitHub
commit 8c36ac5b92
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 871 additions and 0 deletions

20
LICENSE.txt Normal file
View file

@ -0,0 +1,20 @@
Copyright (c) 2021 Igor Levkov
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View file

@ -0,0 +1,182 @@
#include <PPPOS.h>
#include <PPPOSClient.h>
#include <PubSubClient.h>
#define SERIAL_BR 115200
#define GSM_SERIAL 1
#define GSM_RX 16
#define GSM_TX 17
#define GSM_BR 115200
char* server = "example.com";
char* ppp_user = "";
char* ppp_pass = "";
String APN = "internet";
#define WEB_SERVER "www.w3.org"
#define WEB_URL "https://www.w3.org/TR/PNG/iso_8859-1.txt"
static const char *REQUEST = "GET " WEB_URL "\ HTTP/1.1\r\n"
"Host: "WEB_SERVER"\r\n"
"Connection: keep-alive\r\n"
"User-Agent: esp/1.0 esp32\r\n"
"\r\n";
String buffer = "";
char *data = (char *) malloc(1024);
bool atMode = true;
void callback(char* topic, byte* payload, unsigned int length) {
Serial.print("Message arrived [");
Serial.print(topic);
Serial.print("] ");
for (int i=0;i<length;i++) {
Serial.print((char)payload[i]);
}
Serial.println();
}
PPPOSClient ppposClient;
PubSubClient client(ppposClient);
bool sendCommandWithAnswer(String cmd, String ans){
PPPOS_write((char *)cmd.c_str());
unsigned long _tg = millis();
while(true){
data = PPPOS_read();
if (data != NULL){
char* command = strtok(data, "\n");
while (command != 0)
{
buffer = String(command);
buffer.replace("\r", "");
command = strtok(0, "\n");
if (buffer != "") { Serial.println(buffer); }
if (buffer == ans) {buffer = ""; return true; }
buffer = "";
}
}
if (millis() > (_tg + 5000)) { buffer = ""; return false; }
}
buffer = "";
return false;
}
bool startPPPOS(){
String apnSet = "AT+CGDCONT=1,\"IP\",\"" + APN + "\"\n";
if (!sendCommandWithAnswer(apnSet, "OK")) { return false; }
if (!sendCommandWithAnswer("AT+CGDATA=\"PPP\",1\n", "CONNECT")) { return false; }
atMode = false;
PPPOS_start();
unsigned long _tg = millis();
while(!PPPOS_isConnected()) {
if (millis() > (_tg + 10000)) { PPPOS_stop(); atMode = true; return false; }
}
Serial.println("PPPOS Started");
return true;
}
bool enterATModePPPOS(){
if (PPPOS_isConnected() && !atMode){
if (sendCommandWithAnswer("+++", "OK")) { atMode = true; return true;}
}
return false;
}
bool cancelATModePPPOS(){
if (PPPOS_isConnected() && atMode){
if (sendCommandWithAnswer("ATO\n", "CONNECT")) { atMode = false; return true;}
}
return false;
}
void simpleGetRequest(){
if (!ppposClient.connected() ) {
Serial.println("Connecting...");
ppposClient.connect(WEB_SERVER, 80);
}
if (ppposClient.connected() ) {
Serial.println("Connected");
Serial.println(ppposClient.write(REQUEST, strlen(REQUEST)));
while(ppposClient.available()){
Serial.print((char)ppposClient.read());
}
}
}
void reconnect() {
// Loop until we're reconnected
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
// Attempt to connect
if (client.connect("arduinoClient")) {
Serial.println("connected");
// Once connected, publish an announcement...
client.publish("outTopic","hello world");
// ... and resubscribe
client.subscribe("inTopic");
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
// Wait 5 seconds before retrying
delay(5000);
}
}
}
void setup()
{
Serial.begin(SERIAL_BR);
PPPOS_init(GSM_TX, GSM_RX, GSM_BR, GSM_SERIAL, ppp_user, ppp_pass);
client.setServer(server, 1883);
client.setCallback(callback);
Serial.println("1) Start GSM Communication: AT\\n");
Serial.println("2) Start PPP Protocol: ppp\\n");
Serial.println("3) Test GET Request: get\\n");
Serial.println("4) Switch to AT Mode: +++\\n");
Serial.println("5) Switch to Data Mode: ATO\\n");
Serial.println("6) Stop PPP Protocol: stop\\n");
}
void loop()
{
if (!PPPOS_isConnected() || atMode){
data = PPPOS_read();
if (data != NULL){
Serial.println(data);
}
}
if (Serial.available()){
char c = Serial.read();
if (c == '\n'){
if (buffer == "ppp") {
Serial.println("Starting PPPOS...");
if (startPPPOS()) { Serial.println("Starting PPPOS... OK"); } else { Serial.println("Starting PPPOS... Failed"); }
} else if (buffer == "stop") {
PPPOS_stop();
} else if (buffer == "+++") {
if (enterATModePPPOS()) { Serial.println("Entering ATMode... OK"); } else { Serial.println("Entering ATMode... Failed"); }
} else if (buffer == "ATO") {
if (cancelATModePPPOS()) { Serial.println("Canceling ATMode... OK"); } else { Serial.println("Canceling ATMode... Failed"); }
} else if (buffer == "get") {
simpleGetRequest();
} else {
buffer += "\n";
PPPOS_write((char *)buffer.c_str());
Serial.println(buffer);
}
buffer = "";
} else {
buffer += c;
}
}
if (PPPOS_isConnected() && !atMode) {
if (!client.connected()) {
reconnect();
}
client.loop();
}
}

34
keywords.txt Normal file
View file

@ -0,0 +1,34 @@
#######################################
# Syntax Coloring Map For PPPOSClient
#######################################
#######################################
# Datatypes (KEYWORD1)
#######################################
PPPOSClient KEYWORD1
PPPOS KEYWORD1
#######################################
# Methods and Functions (KEYWORD2)
#######################################
connect KEYWORD2
PPPOS_write KEYWORD2
available KEYWORD2
read KEYWORD2
peek KEYWORD2
flush KEYWORD2
stop KEYWORD2
connected KEYWORD2
PPPOS_init KEYWORD2
PPPOS_isConnected KEYWORD2
PPPOS_start KEYWORD2
PPPOS_status KEYWORD2
PPPOS_stop KEYWORD2
PPPOS_write KEYWORD2
PPPOS_read KEYWORD2
#######################################
# Constants (LITERAL1)
#######################################

15
library.json Normal file
View file

@ -0,0 +1,15 @@
{
"name": "PPPOSClient",
"keywords": "gsm, sim800, internet, ppp, iot, mqtt",
"description": "A client library for gsm ppp protocol. This library can be used to make GET and POST requests and to connect mqtt with PubSubClient. It supports ESP32.",
"repository": {
"type": "git",
"url": "https://github.com/levkovigor/ppposclient.git"
},
"version": "1.0",
"examples": "examples/*/*.ino",
"frameworks": "arduino",
"platforms": [
"espressif32"
]
}

9
library.properties Normal file
View file

@ -0,0 +1,9 @@
name=PPPOSClient
version=1.0
author=Igor Levkov <levkov.igor@gmail.com>
maintainer=Igor Levkov <levkov.igor@gmail.com>
sentence=A client library for gsm ppp protocol.
paragraph=This library can be used to make GET and POST requests and to connect mqtt with PubSubClient. It supports ESP32.
category=Communication
url=https://github.com/levkovigor/ppposclient.git
architectures=*

265
src/PPPOS.c Normal file
View file

@ -0,0 +1,265 @@
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_system.h"
#include "esp_wifi.h"
#include "esp_event_loop.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include "driver/uart.h"
#include "driver/gpio.h"
#include "tcpip_adapter.h"
#include "netif/ppp/pppos.h"
#include "lwip/err.h"
#include "lwip/sockets.h"
#include "lwip/sys.h"
#include "lwip/netdb.h"
#include "lwip/dns.h"
#include "netif/ppp/pppapi.h"
#include "PPPOS.h"
#ifdef __cplusplus
extern "C" {
#endif
bool PPPOS_firststart = false;
bool PPPOS_connected = false;
bool PPPOS_started = false;
char *PPP_User = "";
char *PPP_Pass = "";
char PPPOS_out[BUF_SIZE];
/* UART */
int PPPOS_uart_num;
static const char *TAG = "status";
/* The PPP control block */
ppp_pcb *ppp;
/* The PPP IP interface */
struct netif ppp_netif;
/* PPP status callback example */
static void ppp_status_cb(ppp_pcb *pcb, int err_code, void *ctx)
{
struct netif *pppif = ppp_netif(pcb);
LWIP_UNUSED_ARG(ctx);
switch (err_code) {
case PPPERR_NONE: {
ESP_LOGE(TAG, "status_cb: Connected\n");
#if PPP_IPV4_SUPPORT
ESP_LOGE(TAG, " ipaddr_v4 = %s\n", ipaddr_ntoa(&pppif->ip_addr));
ESP_LOGE(TAG, " gateway = %s\n", ipaddr_ntoa(&pppif->gw));
ESP_LOGE(TAG, " netmask = %s\n", ipaddr_ntoa(&pppif->netmask));
#endif /* PPP_IPV4_SUPPORT */
#if PPP_IPV6_SUPPORT
ESP_LOGE(TAG, " ipaddr_v6 = %s\n", ip6addr_ntoa(netif_ip6_addr(pppif, 0)));
#endif /* PPP_IPV6_SUPPORT */
PPPOS_connected = true;
break;
}
case PPPERR_PARAM: {
ESP_LOGE(TAG, "status_cb: Invalid parameter\n");
break;
}
case PPPERR_OPEN: {
ESP_LOGE(TAG, "status_cb: Unable to open PPP session\n");
break;
}
case PPPERR_DEVICE: {
ESP_LOGE(TAG, "status_cb: Invalid I/O device for PPP\n");
break;
}
case PPPERR_ALLOC: {
ESP_LOGE(TAG, "status_cb: Unable to allocate resources\n");
break;
}
case PPPERR_USER: {
ESP_LOGE(TAG, "status_cb: User interrupt\n");
PPPOS_started = false;
PPPOS_connected = false;
break;
}
case PPPERR_CONNECT: {
ESP_LOGE(TAG, "status_cb: Connection lost\n");
PPPOS_started = false;
PPPOS_connected = false;
break;
}
case PPPERR_AUTHFAIL: {
ESP_LOGE(TAG, "status_cb: Failed authentication challenge\n");
PPPOS_started = false;
PPPOS_connected = false;
break;
}
case PPPERR_PROTOCOL: {
ESP_LOGE(TAG, "status_cb: Failed to meet protocol\n");
PPPOS_started = false;
PPPOS_connected = false;
break;
}
case PPPERR_PEERDEAD: {
ESP_LOGE(TAG, "status_cb: Connection timeout\n");
PPPOS_started = false;
PPPOS_connected = false;
break;
}
case PPPERR_IDLETIMEOUT: {
ESP_LOGE(TAG, "status_cb: Idle Timeout\n");
PPPOS_started = false;
PPPOS_connected = false;
break;
}
case PPPERR_CONNECTTIME: {
ESP_LOGE(TAG, "status_cb: Max connect time reached\n");
PPPOS_started = false;
PPPOS_connected = false;
break;
}
case PPPERR_LOOPBACK: {
ESP_LOGE(TAG, "status_cb: Loopback detected\n");
PPPOS_started = false;
PPPOS_connected = false;
break;
}
default: {
ESP_LOGE(TAG, "status_cb: Unknown error code %d\n", err_code);
PPPOS_started = false;
PPPOS_connected = false;
break;
}
}
if (err_code == PPPERR_NONE) {
return;
}
if (err_code == PPPERR_USER) {
return;
}
}
static u32_t ppp_output_callback(ppp_pcb *pcb, u8_t *data, u32_t len, void *ctx)
{
return uart_write_bytes(PPPOS_uart_num, (const char *)data, len);
}
static void pppos_client_task(void *pvParameters)
{
char* data = (char*)malloc(BUF_SIZE);
while (1) {
while (PPPOS_started) {
memset(data, 0, BUF_SIZE);
int len = uart_read_bytes(PPPOS_uart_num, (uint8_t *)data, BUF_SIZE, 10 / portTICK_RATE_MS);
if (len > 0) {
pppos_input_tcpip(ppp, (u8_t *)data, len);
}
vTaskDelay(100 / portTICK_PERIOD_MS);
}
vTaskDelay(100 / portTICK_PERIOD_MS);
}
}
void PPPOS_init(int txPin, int rxPin, int baudrate, int uart_number, char* user, char* pass){
PPPOS_uart_num = uart_number;
gpio_set_direction(txPin, GPIO_MODE_OUTPUT);
gpio_set_direction(rxPin, GPIO_MODE_INPUT);
gpio_set_pull_mode(rxPin, GPIO_PULLUP_ONLY);
uart_config_t uart_config = {
.baud_rate = baudrate,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE
};
uart_param_config(PPPOS_uart_num, &uart_config) ;
uart_set_pin(PPPOS_uart_num, txPin, rxPin, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
uart_driver_install(PPPOS_uart_num, BUF_SIZE * 2, BUF_SIZE * 2, 0, NULL, 0);
tcpip_adapter_init();
PPP_User = user;
PPP_Pass = pass;
xTaskCreate(&pppos_client_task, "pppos_client_task", 10048, NULL, 5, NULL);
}
bool PPPOS_isConnected(){
return PPPOS_connected;
}
void PPPOS_start(){
if (!PPPOS_firststart){
ppp = pppapi_pppos_create(&ppp_netif, ppp_output_callback, ppp_status_cb, NULL);
if (ppp == NULL) {
return;
}
pppapi_set_default(ppp);
pppapi_set_auth(ppp, PPPAUTHTYPE_PAP, PPP_User, PPP_Pass);
ppp_set_usepeerdns(ppp, 1);}
pppapi_connect(ppp, 0);
PPPOS_started = true;
PPPOS_firststart = true;
}
bool PPPOS_status(){
return PPPOS_started;
}
void PPPOS_stop(){
pppapi_close(ppp, 0);
}
/*void gsmInit(int txPin, int rxPin, int baudrate, int uart_number){
PPPOS_uart_num = uart_number;
gpio_set_direction(txPin, GPIO_MODE_OUTPUT);
gpio_set_direction(rxPin, GPIO_MODE_INPUT);
gpio_set_pull_mode(rxPin, GPIO_PULLUP_ONLY);
uart_config_t uart_config = {
.baud_rate = baudrate,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE
};
uart_param_config(PPPOS_uart_num, &uart_config) ;
uart_set_pin(PPPOS_uart_num, txPin, rxPin, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
uart_driver_install(PPPOS_uart_num, BUF_SIZE * 2, BUF_SIZE * 2, 0, NULL, 0);
}*/
char* PPPOS_read(){
memset(PPPOS_out, 0, BUF_SIZE);
int len = uart_read_bytes(PPPOS_uart_num, (uint8_t *)PPPOS_out, BUF_SIZE, 10 / portTICK_RATE_MS);
if (len > 0) {
return PPPOS_out;
} else {
return NULL;
}
}
void PPPOS_write(char* cmd){
uart_flush(PPPOS_uart_num);
if (cmd != NULL) {
int cmdSize = strlen(cmd);
uart_write_bytes(PPPOS_uart_num, (const char*)cmd, cmdSize);
uart_wait_tx_done(PPPOS_uart_num, 100 / portTICK_RATE_MS);
}
}
#ifdef __cplusplus
}
#endif

28
src/PPPOS.h Normal file
View file

@ -0,0 +1,28 @@
#ifndef _GSM_H_
#define _GSM_H_
#ifdef __cplusplus
extern "C" {
#endif
#define BUF_SIZE (1024)
void PPPOS_init(int txPin, int rxPin, int baudrate, int uart_number, char* user, char* pass);
bool PPPOS_isConnected();
void PPPOS_start();
bool PPPOS_status();
void PPPOS_stop();
void PPPOS_write(char* cmd);
char* PPPOS_read();
#ifdef __cplusplus
}
#endif
#endif

266
src/PPPOSClient.cpp Normal file
View file

@ -0,0 +1,266 @@
#include "PPPOSClient.h"
void PPPOSClient::stop()
{
lwip_close(_socket);
_startPos = 0;
_endPos = 0;
bzero(RxBuffer, sizeof(RxBuffer));
_connected = false;
}
int PPPOSClient::connect(IPAddress ip, uint16_t port)
{
int32_t timeout = PPPOS_CLIENT_DEF_CONN_TIMEOUT_MS;
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
log_e("socket: %d", errno);
return 0;
}
fcntl( sockfd, F_SETFL, fcntl( sockfd, F_GETFL, 0 ) | O_NONBLOCK );
uint32_t ip_addr = ip;
struct sockaddr_in serveraddr;
memset((char *) &serveraddr, 0, sizeof(serveraddr));
serveraddr.sin_family = AF_INET;
memcpy((void *)&serveraddr.sin_addr.s_addr, (const void *)(&ip_addr), 4);
serveraddr.sin_port = htons(port);
fd_set fdset;
struct timeval tv;
FD_ZERO(&fdset);
FD_SET(sockfd, &fdset);
tv.tv_sec = 0;
tv.tv_usec = timeout * 1000;
#ifdef ESP_IDF_VERSION_MAJOR
int res = lwip_connect(sockfd, (struct sockaddr*)&serveraddr, sizeof(serveraddr));
#else
int res = lwip_connect_r(sockfd, (struct sockaddr*)&serveraddr, sizeof(serveraddr));
#endif
if (res < 0 && errno != EINPROGRESS) {
log_e("connect on fd %d, errno: %d, \"%s\"", sockfd, errno, strerror(errno));
close(sockfd);
return 0;
}
res = select(sockfd + 1, nullptr, &fdset, nullptr, timeout<0 ? nullptr : &tv);
if (res < 0) {
log_e("select on fd %d, errno: %d, \"%s\"", sockfd, errno, strerror(errno));
close(sockfd);
return 0;
} else if (res == 0) {
log_i("select returned due to timeout %d ms for fd %d", timeout, sockfd);
close(sockfd);
return 0;
} else {
int sockerr;
socklen_t len = (socklen_t)sizeof(int);
res = getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &sockerr, &len);
if (res < 0) {
log_e("getsockopt on fd %d, errno: %d, \"%s\"", sockfd, errno, strerror(errno));
close(sockfd);
return 0;
}
if (sockerr != 0) {
log_e("socket error on fd %d, errno: %d, \"%s\"", sockfd, sockerr, strerror(sockerr));
close(sockfd);
return 0;
}
}
fcntl( sockfd, F_SETFL, fcntl( sockfd, F_GETFL, 0 ) & (~O_NONBLOCK) );
_connected = true;
_socket = sockfd;
return 1;
}
int PPPOSClient::connect(const char *host, uint16_t port)
{
ip_addr_t ip_addr;
IPAddress aResult = static_cast<uint32_t>(0);
struct in_addr retAddr;
struct hostent* he = gethostbyname(host);
if (he == nullptr) {
retAddr.s_addr = 0;
return 0;
} else {
retAddr = *(struct in_addr*) (he->h_addr_list[0]);
}
inet_aton(inet_ntoa(retAddr), &ip_addr);
aResult = ip_addr.u_addr.ip4.addr;
return connect(aResult, port);
}
size_t PPPOSClient::write(uint8_t data)
{
return write(&data, 1);
}
int PPPOSClient::read()
{
if (!_connected) return -1;
if (_startPos >= (_endPos - 1)) {
_startPos = 0;
_endPos = 0;
bzero(RxBuffer, sizeof(RxBuffer));
int _r = lwip_recv(_socket, RxBuffer, sizeof(RxBuffer)-1, MSG_DONTWAIT);
if (_r > 0) {
_endPos = _r + 1;
} else {
return -1;
}
}
_startPos++;
return RxBuffer[_startPos-1];
}
size_t PPPOSClient::write(const uint8_t *buf, size_t size)
{
int res =0;
int retry = PPPOS_CLIENT_MAX_WRITE_RETRY;
int socketFileDescriptor = _socket;
size_t totalBytesSent = 0;
size_t bytesRemaining = size;
if(!_connected || (socketFileDescriptor < 0)) {
return 0;
}
while(retry) {
fd_set set;
struct timeval tv;
FD_ZERO(&set);
FD_SET(socketFileDescriptor, &set);
tv.tv_sec = 0;
tv.tv_usec = PPPOS_CLIENT_SELECT_TIMEOUT_US;
retry--;
if(select(socketFileDescriptor + 1, NULL, &set, NULL, &tv) < 0) {
return 0;
}
if(FD_ISSET(socketFileDescriptor, &set)) {
res = lwip_send(socketFileDescriptor, (void*) buf, bytesRemaining, MSG_DONTWAIT);
if(res > 0) {
totalBytesSent += res;
if (totalBytesSent >= size) {
retry = 0;
} else {
buf += res;
bytesRemaining -= res;
retry = PPPOS_CLIENT_MAX_WRITE_RETRY;
}
}
else if(res < 0) {
log_e("fail on fd %d, errno: %d, \"%s\"", fd(), errno, strerror(errno));
if(errno != EAGAIN) {
stop();
res = 0;
retry = 0;
}
}
else {
}
}
}
return totalBytesSent;
}
int PPPOSClient::available()
{
if (!_connected) return false;
if (_startPos >= (_endPos - 1)) {
_startPos = 0;
_endPos = 0;
bzero(RxBuffer, sizeof(RxBuffer));
int _r = lwip_recv(_socket, RxBuffer, sizeof(RxBuffer)-1, MSG_DONTWAIT);
if (_r > 0) {
_endPos = _r + 1;
} else {
return false;
}
}
return true;
}
void PPPOSClient::flush() {
char recv_buf[5000];
int r = 0;
do {
bzero(recv_buf, sizeof(recv_buf));
r = lwip_recv(_socket, recv_buf, sizeof(recv_buf)-1, MSG_DONTWAIT);
}while(r > 0);
_startPos = 0;
_endPos = 0;
bzero(RxBuffer, sizeof(RxBuffer));
}
uint8_t PPPOSClient::connected() {
if (_connected) {
uint8_t dummy;
int res = lwip_recv(_socket, &dummy, 0, MSG_DONTWAIT);
(void)res;
if (res <= 0){
switch (errno) {
case EWOULDBLOCK:
case ENOENT:
_connected = true;
break;
case ENOTCONN:
case EPIPE:
case ECONNRESET:
case ECONNREFUSED:
case ECONNABORTED:
_connected = false;
log_e("Disconnected: RES: %d, ERR: %d", res, errno);
break;
default:
log_e("Unexpected: RES: %d, ERR: %d", res, errno);
_connected = true;
break;
}
} else {
_connected = true;
}
}
return _connected;
}
int PPPOSClient::read(uint8_t *buf, size_t size) {
if (!_connected) return -1;
int res = -1;
if (available()){
int j = 0;
for (int i = _startPos; i < _endPos; i++) {
if (j < size) {
buf[j] = RxBuffer[i];
} else {
res = j;
_startPos += j;
}
j++;
}
}
return res;
}
int PPPOSClient::peek() {
if (!_connected) return -1;
if (_startPos >= (_endPos - 1)) {
_startPos = 0;
_endPos = 0;
bzero(RxBuffer, sizeof(RxBuffer));
int _r = lwip_recv(_socket, RxBuffer, sizeof(RxBuffer)-1, MSG_DONTWAIT);
if (_r > 0) {
_endPos = _r + 1;
} else {
_connected = false;
return -1;
}
}
return RxBuffer[_startPos];
}

52
src/PPPOSClient.h Normal file
View file

@ -0,0 +1,52 @@
#ifndef _PPPOSCLIENT_H_
#define _PPPOSCLIENT_H_
#define PPPOS_RXBUFFER_LENGTH 1024
#define PPPOS_CLIENT_DEF_CONN_TIMEOUT_MS (3000)
#define PPPOS_CLIENT_MAX_WRITE_RETRY (10)
#define PPPOS_CLIENT_SELECT_TIMEOUT_US (1000000)
#define PPPOS_CLIENT_FLUSH_BUFFER_SIZE (1024)
#include <Arduino.h>
#include "Client.h"
#include "lwip/dns.h"
#include "lwip/inet.h"
#include "esp_system.h"
#include "esp_wifi.h"
#include "lwip/err.h"
#include "lwip/sockets.h"
#include "lwip/sys.h"
#include "lwip/netdb.h"
#include <errno.h>
class PPPOSClient : public Client
{
public:
PPPOSClient() : _connected(false), _socket(0) {}
virtual int connect(IPAddress ip, uint16_t port);
virtual int connect(const char *host, uint16_t port);
virtual size_t write(uint8_t data);
virtual size_t write(const uint8_t *buf, size_t size);
virtual int available();
virtual int read();
virtual int read(uint8_t *buf, size_t size);
virtual operator bool() { return 0; }
virtual int peek();
virtual void flush();
virtual void stop();
virtual uint8_t connected();
using Print::write;
protected:
bool _connected;
int _socket;
uint8_t RxBuffer[PPPOS_RXBUFFER_LENGTH];
int _startPos = 0;
int _endPos = 0;
};
#endif /* _PPPOSCLIENT_H_ */