working http request

master
Ondřej Hruška 9 years ago
parent 8850f7b094
commit cd93a0891e
  1. 8
      Makefile
  2. 1
      esp_iot_sdk_v1.5.2/include/osapi.h
  3. 41
      esp_meas.pro
  4. 78
      esphttpclient/README.md
  5. 487
      esphttpclient/httpclient.c
  6. 62
      esphttpclient/httpclient.h
  7. 90
      esphttpclient/test/httpclient_test.c
  8. 1
      libesphttpd/include/platform.h
  9. 15
      user/user_main.c

@ -55,11 +55,13 @@ APPGEN ?= $(SDK_BASE)/tools/gen_appbin.py
TARGET = httpd
# which modules (subdirectories) of the project to include in compiling
MODULES = user sbmp/library
EXTRA_INCDIR = include libesphttpd/include sbmp/library user/
MODULES = user sbmp/library esphttpclient
EXTRA_INCDIR = include libesphttpd/include sbmp/library user esphttpclient
# libraries used in this project, mainly provided by the SDK
LIBS = c gcc hal phy pp net80211 wpa main lwip crypto
LIBS = c gcc hal phy pp net80211 wpa main lwip crypto
#ssl
#Add in esphttpd lib
LIBS += esphttpd

@ -32,6 +32,7 @@
#define os_timer_setfn ets_timer_setfn
#define os_sprintf ets_sprintf
#define os_snprintf ets_snprintf
#ifdef USE_OPTIMIZE_PRINTF
#define os_printf(fmt, ...) do { \

@ -9,6 +9,7 @@ INCLUDEPATH = . \
esp_iot_sdk_v1.5.2/include \
include \
user \
esphttpclient \
libesphttpd/include \
libesphttpd/espfs \
libesphttpd/core \
@ -56,14 +57,16 @@ SOURCES += \
sbmp/library/payload_parser.c \
user/sampling.c \
user/ftoa.c \
user/routes.c \
user/page_status.c \
user/page_waveform.c \
user/utils.c \
sbmp/library/payload_builder.c \
user/page_about.c \
user/cgi_reset.c \
user/cgi_ping.c
user/routes.c \
user/page_status.c \
user/page_waveform.c \
user/utils.c \
sbmp/library/payload_builder.c \
user/page_about.c \
user/cgi_reset.c \
user/cgi_ping.c \
esphttpclient/test/httpclient_test.c \
esphttpclient/httpclient.c
HEADERS += \
include/uart_hw.h \
@ -140,16 +143,18 @@ HEADERS += \
user/sbmp_config.h \
sbmp/library/sbmp_config.example.h \
user/ftoa.h \
user/routes.h \
user/page_status.h \
user/page_waveform.h \
libesphttpd/include/espmissingprotos.h \
user/utils.h \
sbmp/library/payload_builder.h \
user/page_about.h \
user/fw_version.h \
user/cgi_reset.h \
user/cgi_ping.h
user/routes.h \
user/page_status.h \
user/page_waveform.h \
libesphttpd/include/espmissingprotos.h \
user/utils.h \
sbmp/library/payload_builder.h \
user/page_about.h \
user/fw_version.h \
user/cgi_reset.h \
user/cgi_ping.h \
esphttpclient/espmissingincludes.h \
esphttpclient/httpclient.h
DISTFILES += \
style.astylerc \

@ -0,0 +1,78 @@
# esphttpclient
This is a short library for ESP8266(EX) chips to make HTTP requests.
## Features
* Easy to use.
* Supports multiple requests in parallel.
* Supports GET and POST requests.
* Tested with Espressif SDK v1.0.0
## Building
If you don't have a toolchain yet, install one with <https://github.com/pfalcon/esp-open-sdk> then get Espressif's SDK.
### The submodule way
If your project looks like esphttpd from Sprite_tm:
```bash
git clone http://git.spritesserver.nl/esphttpd.git/
cd esphttpd
git submodule add https://github.com/Caerbannog/esphttpclient.git lib/esphttpclient
git submodule update --init
```
Now append `lib/esphttpclient` to the following `Makefile` line and you should be ready:
```
MODULES = driver user lib/esphttpclient
```
In case you want to use SSL don't forget to add `ssl` to `LIBS` in the `Makefile`
```
LIBS = c gcc hal pp phy net80211 lwip wpa main ssl
```
### The dirty way
Alternatively you could create a simple project:
```bash
git clone https://github.com/esp8266/source-code-examples.git
cd source-code-examples/basic_example
# Set your Wifi credentials in user_config.h
# I could not test this because of the UART baud rate (74880)
```
Then download this library and move the files to `user/`:
```bash
git clone https://github.com/Caerbannog/esphttpclient.git
mv esphttpclient/*.* user/
```
## Usage
Include `httpclient.h` from `user_main.c` then call one of these functions:
```c
void http_get(const char * url, const char * headers, http_callback user_callback);
void http_post(const char * url, const char * post_data, const char * headers, http_callback user_callback);
void http_callback_example(char * response_body, int http_status, char * response_headers, int body_size)
{
os_printf("http_status=%d\n", http_status);
if (http_status != HTTP_STATUS_GENERIC_ERROR) {
os_printf("strlen(headers)=%d\n", strlen(response_headers));
os_printf("body_size=%d\n", body_size);
os_printf("body=%s<EOF>\n", response_body);
}
}
```
## Example
The following code performs a single request, then calls `http_callback_example` to display your public IP address.
```c
http_get("http://wtfismyip.com/text", "", http_callback_example);
```
The output looks like this:
```
http_status=200
strlen(full_response)=244
body_size=15
response_body=208.97.177.124
<EOF>
```

@ -0,0 +1,487 @@
/*
* ----------------------------------------------------------------------------
* "THE BEER-WARE LICENSE" (Revision 42):
* Martin d'Allens <martin.dallens@gmail.com> wrote this file. As long as you retain
* this notice you can do whatever you want with this stuff. If we meet some day,
* and you think this stuff is worth it, you can buy me a beer in return.
* ----------------------------------------------------------------------------
*/
// FIXME: sprintf->snprintf everywhere.
#include <esp8266.h>
#include "httpclient.h"
#include <limits.h>
// Internal state.
typedef struct {
char *path;
int port;
char *post_data;
char *headers;
char *hostname;
char *buffer;
int buffer_size;
bool secure;
httpclient_cb user_callback;
} request_args;
static char *FLASH_FN esp_strdup(const char *str)
{
if (str == NULL) {
return NULL;
}
char *new_str = (char *)malloc(strlen(str) + 1); // 1 for null character
if (new_str == NULL) {
error("esp_strdup: malloc error");
return NULL;
}
strcpy(new_str, str);
return new_str;
}
static int FLASH_FN esp_isupper(char c)
{
return (c >= 'A' && c <= 'Z');
}
static int FLASH_FN esp_isalpha(char c)
{
return ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'));
}
static int FLASH_FN esp_isspace(char c)
{
return (c == ' ' || c == '\t' || c == '\n' || c == '\r');
}
static int FLASH_FN esp_isdigit(char c)
{
return (c >= '0' && c <= '9');
}
/*
* Convert a string to a long integer.
*
* Ignores `locale' stuff. Assumes that the upper and lower case
* alphabets and digits are each contiguous.
*/
static long FLASH_FN esp_strtol(const char *nptr, char **endptr, int base)
{
const char *s = nptr;
unsigned long acc;
int c;
unsigned long cutoff;
int neg = 0, any, cutlim;
/*
* Skip white space and pick up leading +/- sign if any.
* If base is 0, allow 0x for hex and 0 for octal, else
* assume decimal; if base is already 16, allow 0x.
*/
do {
c = *s++;
} while (esp_isspace((char)c));
if (c == '-') {
neg = 1;
c = *s++;
} else if (c == '+')
c = *s++;
if ((base == 0 || base == 16) &&
c == '0' && (*s == 'x' || *s == 'X')) {
c = s[1];
s += 2;
base = 16;
} else if ((base == 0 || base == 2) &&
c == '0' && (*s == 'b' || *s == 'B')) {
c = s[1];
s += 2;
base = 2;
}
if (base == 0)
base = c == '0' ? 8 : 10;
/*
* Compute the cutoff value between legal numbers and illegal
* numbers. That is the largest legal value, divided by the
* base. An input number that is greater than this value, if
* followed by a legal input character, is too big. One that
* is equal to this value may be valid or not; the limit
* between valid and invalid numbers is then based on the last
* digit. For instance, if the range for longs is
* [-2147483648..2147483647] and the input base is 10,
* cutoff will be set to 214748364 and cutlim to either
* 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
* a value > 214748364, or equal but the next digit is > 7 (or 8),
* the number is too big, and we will return a range error.
*
* Set any if any `digits' consumed; make it negative to indicate
* overflow.
*/
cutoff = neg ? -(unsigned long)LONG_MIN : LONG_MAX;
cutlim = cutoff % (unsigned long)base;
cutoff /= (unsigned long)base;
for (acc = 0, any = 0;; c = *s++) {
if (esp_isdigit((char)c))
c -= '0';
else if (esp_isalpha((char)c))
c -= esp_isupper((char)c) ? 'A' - 10 : 'a' - 10;
else
break;
if (c >= base)
break;
if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
any = -1;
else {
any = 1;
acc *= base;
acc += c;
}
}
if (any < 0) {
acc = neg ? LONG_MIN : LONG_MAX;
// errno = ERANGE;
} else if (neg)
acc = -acc;
if (endptr != 0)
*endptr = (char *)(any ? s - 1 : nptr);
return (acc);
}
static int FLASH_FN chunked_decode(char *chunked, int size)
{
char *src = chunked;
char *end = chunked + size;
int i, dst = 0;
do {
char *endstr = NULL;
//[chunk-size]
i = esp_strtol(src, &endstr, 16);
dbg("Chunk Size:%d\r\n", i);
if (i <= 0)
break;
//[chunk-size-end-ptr]
src = (char *)strstr(src, "\r\n") + 2;
//[chunk-data]
memmove(&chunked[dst], src, (size_t)i);
src += i + 2; /* CRLF */
dst += i;
} while (src < end);
//
//footer CRLF
//
/* decoded size */
return dst;
}
static void FLASH_FN receive_callback(void * arg, char *buf, unsigned short len)
{
struct espconn * conn = (struct espconn *)arg;
request_args * req = (request_args *)conn->reserve;
if (req->buffer == NULL) {
return;
}
// Let's do the equivalent of a realloc().
const int new_size = req->buffer_size + len;
char *new_buffer;
if (new_size > BUFFER_SIZE_MAX || NULL == (new_buffer = (char *)malloc(new_size))) {
error("Response too long (%d)", new_size);
req->buffer[0] = '\0'; // Discard the buffer to avoid using an incomplete response.
if (req->secure) {
#ifdef USE_SECURE
espconn_secure_disconnect(conn);
#endif
} else {
espconn_disconnect(conn);
}
return; // The disconnect callback will be called.
}
memcpy(new_buffer, req->buffer, req->buffer_size);
memcpy(new_buffer + req->buffer_size - 1 /*overwrite the null character*/, buf, len); // Append new data.
new_buffer[new_size - 1] = '\0'; // Make sure there is an end of string.
free(req->buffer);
req->buffer = new_buffer;
req->buffer_size = new_size;
}
static void FLASH_FN sent_callback(void * arg)
{
struct espconn * conn = (struct espconn *)arg;
request_args * req = (request_args *)conn->reserve;
if (req->post_data == NULL) {
//dbg("All sent");
} else {
// The headers were sent, now send the contents.
//dbg("Sending request body");
if (req->secure){
#ifdef USE_SECURE
espconn_secure_sent(conn, (uint8_t *)req->post_data, strlen(req->post_data));
#endif
} else {
espconn_sent(conn, (uint8_t *)req->post_data, strlen(req->post_data));
}
free(req->post_data);
req->post_data = NULL;
}
}
static void FLASH_FN connect_callback(void * arg)
{
info("Connected!");
struct espconn * conn = (struct espconn *)arg;
request_args * req = (request_args *)conn->reserve;
espconn_regist_recvcb(conn, receive_callback);
espconn_regist_sentcb(conn, sent_callback);
const char *method = "GET";
char post_headers[32] = "";
if (req->post_data != NULL) { // If there is data this is a POST request.
method = "POST";
sprintf(post_headers, "Content-Length: %d\r\n", strlen(req->post_data));
}
char buf[69 + strlen(method) + strlen(req->path) + strlen(req->hostname) + strlen(req->headers) + strlen(post_headers)];
int len = sprintf(buf,
"%s %s HTTP/1.1\r\n"
"Host: %s:%d\r\n"
"Connection: close\r\n"
"User-Agent: ESP8266\r\n"
"%s"
"%s"
"\r\n",
method, req->path, req->hostname, req->port, req->headers, post_headers);
dbg("Sending request");
if (req->secure) {
#ifdef USE_SECURE
espconn_secure_sent(conn, (uint8_t *)buf, len);
#endif
} else {
espconn_sent(conn, (uint8_t *)buf, len);
}
free(req->headers);
req->headers = NULL;
}
static void FLASH_FN disconnect_callback(void * arg)
{
dbg("Disconnected");
struct espconn *conn = (struct espconn *)arg;
if (conn == NULL) {
return;
}
if (conn->reserve != NULL) {
request_args * req = (request_args *)conn->reserve;
int http_status = -1;
int body_size = 0;
char *body = "";
if (req->buffer == NULL) {
error("Buffer shouldn't be NULL");
} else if (req->buffer[0] != '\0') {
// FIXME: make sure this is not a partial response, using the Content-Length header.
const char *version10 = "HTTP/1.0 ";
const char *version11 = "HTTP/1.1 ";
if (!strstarts(req->buffer, version10) && !strstarts(req->buffer, version11)) {
error("Invalid version in %s", req->buffer);
} else {
http_status = atoi(req->buffer + strlen(version10));
/* find body and zero terminate headers */
body = (char *)strstr(req->buffer, "\r\n\r\n") + 2;
*body++ = '\0';
*body++ = '\0';
body_size = req->buffer_size - (body - req->buffer);
if (strstr(req->buffer, "Transfer-Encoding: chunked")) {
body_size = chunked_decode(body, body_size);
}
}
}
info("Request completed.");
if (req->user_callback != NULL) { // Callback is optional.
req->user_callback(body, http_status, req->buffer, body_size);
}
free(req->buffer);
free(req->hostname);
free(req->path);
free(req);
}
espconn_delete(conn);
if (conn->proto.tcp != NULL) {
free(conn->proto.tcp);
}
free(conn);
}
static void FLASH_FN error_callback(void *arg, sint8 errType)
{
error("Disconnected with error, type %d", errType);
disconnect_callback(arg);
}
static void FLASH_FN dns_callback(const char *hostname, ip_addr_t *addr, void *arg)
{
request_args * req = (request_args *)arg;
if (addr == NULL) {
error("DNS failed for %s", hostname);
if (req->user_callback != NULL) {
req->user_callback("", -1, "", 0);
}
free(req);
} else {
info("DNS found %s " IPSTR, hostname, IP2STR(addr));
struct espconn * conn = (struct espconn *)malloc(sizeof(struct espconn));
conn->type = ESPCONN_TCP;
conn->state = ESPCONN_NONE;
conn->proto.tcp = (esp_tcp *)malloc(sizeof(esp_tcp));
conn->proto.tcp->local_port = espconn_port();
conn->proto.tcp->remote_port = req->port;
conn->reserve = req;
memcpy(conn->proto.tcp->remote_ip, addr, 4);
espconn_regist_connectcb(conn, connect_callback);
espconn_regist_disconcb(conn, disconnect_callback);
espconn_regist_reconcb(conn, error_callback);
if (req->secure) {
#ifdef USE_SECURE
espconn_secure_set_size(ESPCONN_CLIENT, 5120); // set SSL buffer size
espconn_secure_connect(conn);
#endif
} else {
espconn_connect(conn);
}
}
}
void FLASH_FN http_raw_request(const char *hostname, int port, bool secure, const char *path, const char *post_data, const char *headers, httpclient_cb user_callback)
{
info("HTTP request: %s:%d%s", hostname, port, path);
request_args * req = (request_args *)malloc(sizeof(request_args));
req->hostname = esp_strdup(hostname);
req->path = esp_strdup(path);
req->port = port;
req->secure = secure;
req->headers = esp_strdup(headers);
req->post_data = esp_strdup(post_data);
req->buffer_size = 1;
req->buffer = (char *)malloc(1);
req->buffer[0] = '\0'; // Empty string.
req->user_callback = user_callback;
ip_addr_t addr;
err_t error = espconn_gethostbyname((struct espconn *)req, // It seems we don't need a real espconn pointer here.
hostname, &addr, dns_callback);
if (error == ESPCONN_INPROGRESS) {
dbg("DNS pending");
} else if (error == ESPCONN_OK) {
// Already in the local names table (or hostname was an IP address), execute the callback ourselves.
dns_callback(hostname, &addr, req);
} else {
if (error == ESPCONN_ARG) {
error("DNS arg error %s", hostname);
} else {
error("DNS error code %d", error);
}
dns_callback(hostname, NULL, req); // Handle all DNS errors the same way.
}
}
/*
* Parse an URL of the form http://host:port/path
* <host> can be a hostname or an IP address
* <port> is optional
*/
void FLASH_FN http_post(const char *url, const char *post_data, const char *headers, httpclient_cb user_callback)
{
// FIXME: handle HTTP auth with http://user:pass@host/
// FIXME: get rid of the #anchor part if present.
char hostname[128] = "";
int port = 80;
bool secure = false;
bool is_http = strstarts(url, "http://");
bool is_https = strstarts(url, "https://");
if (is_http)
url += strlen("http://"); // Get rid of the protocol.
else if (is_https) {
port = 443;
secure = true;
url += strlen("https://"); // Get rid of the protocol.
} else {
error("URL is not HTTP or HTTPS %s", url);
return;
}
char *path = strchr(url, '/');
if (path == NULL) {
path = strchr(url, '\0'); // Pointer to end of string.
}
char *colon = strchr(url, ':');
if (colon > path) {
colon = NULL; // Limit the search to characters before the path.
}
if (colon == NULL) { // The port is not present.
memcpy(hostname, url, path - url);
hostname[path - url] = '\0';
} else {
port = atoi(colon + 1);
if (port == 0) {
error("Port error %s\n", url);
return;
}
memcpy(hostname, url, colon - url);
hostname[colon - url] = '\0';
}
if (path[0] == '\0') { // Empty path is not allowed.
path = "/";
}
http_raw_request(hostname, port, secure, path, post_data, headers, user_callback);
}
void FLASH_FN http_get(const char *url, const char *headers, httpclient_cb user_callback)
{
http_post(url, NULL, headers, user_callback);
}
void FLASH_FN http_callback_example(char *response_body, int http_status, char *response_headers, int body_size)
{
dbg("[HTTPCLIENT] http_status=%d", http_status);
if (http_status != HTTP_STATUS_GENERIC_ERROR) {
dbg("strlen(headers)=%d", (int)strlen(response_headers));
dbg("body_size=%d", body_size);
dbg("body=%s<EOF>", response_body); // FIXME: this does not handle binary data.
}
}

@ -0,0 +1,62 @@
/*
* ----------------------------------------------------------------------------
* "THE BEER-WARE LICENSE" (Revision 42):
* Martin d'Allens <martin.dallens@gmail.com> wrote this file. As long as you retain
* this notice you can do whatever you want with this stuff. If we meet some day,
* and you think this stuff is worth it, you can buy me a beer in return.
* ----------------------------------------------------------------------------
*/
#ifndef HTTPCLIENT_H
#define HTTPCLIENT_H
#include <esp8266.h>
#define HTTP_STATUS_GENERIC_ERROR -1 // In case of TCP or DNS error the callback is called with this status.
#define BUFFER_SIZE_MAX 5000 // Size of http responses that will cause an error.
/* Define this if ssl is needed. Also link the ssl lib */
//#define USE_SECURE
/**
* "full_response" is a string containing all response headers and the response body.
* "response_body and "http_status" are extracted from "full_response" for convenience.
*
* A successful request corresponds to an HTTP status code of 200 (OK).
* More info at http://en.wikipedia.org/wiki/List_of_HTTP_status_codes
*/
typedef void (* httpclient_cb)(char * response_body, int http_status, char * response_headers, int body_size);
/**
* Download a web page from its URL.
* Try:
* http_get("http://wtfismyip.com/text", http_callback_example);
*/
void http_get(const char * url, const char *headers, httpclient_cb user_callback);
/**
* Post data to a web form.
* The data should be encoded as application/x-www-form-urlencoded.
* Try:
* http_post("http://httpbin.org/post", "first_word=hello&second_word=world", http_callback_example);
*/
void http_post(const char *url, const char *post_data, const char *headers, httpclient_cb user_callback);
/**
* Call this function to skip URL parsing if the arguments are already in separate variables.
*/
void http_raw_request(
const char * hostname,
int port,
bool secure,
const char *path,
const char *post_data,
const char *headers,
httpclient_cb user_callback);
/**
* Output on the UART.
*/
void http_callback_example(char *response_body, int http_status, char *response_headers, int body_size);
#endif

@ -0,0 +1,90 @@
/*
* ----------------------------------------------------------------------------
* "THE BEER-WARE LICENSE" (Revision 42):
* Martin d'Allens <martin.dallens@gmail.com> wrote this file. As long as you retain
* this notice you can do whatever you want with this stuff. If we meet some day,
* and you think this stuff is worth it, you can buy me a beer in return.
* ----------------------------------------------------------------------------
*/
#include <esp8266.h>
#include "httpclient.h"
static int test_count = 0;
static ETSTimer test_timer;
static void ICACHE_FLASH_ATTR test_timer_cb()
{
dbg("\nTEST %d ", test_count);
switch(test_count) {
case 0:
dbg("=> IP address before network ready\n");
http_get("http://173.194.45.65", "", http_callback_example);
// This test will fail. The DHCP request returns directly, but the TCP connection hangs.
// FIXME: wait for network to be ready before connecting?
break;
case 1:
dbg("=> Simple GET\n");
http_get("http://wtfismyip.com/text", "", http_callback_example);
break;
case 2:
dbg("=> Response too long\n");
http_get("http://www.wikipedia.org/", "", http_callback_example);
break;
case 3:
dbg("=> Connection refused\n");
http_get("http://att.com:1234/", "", http_callback_example);
break;
case 4:
dbg("=> Empty response, wrong protocol\n");
http_get("http://google.com:443/", "", http_callback_example);
break;
case 5:
dbg("=> Invalid DNS\n");
http_get("http://invalid.dns/", "", http_callback_example);
break;
case 6:
dbg("=> Connection time out\n");
http_get("http://google.com:1234/", "", http_callback_example);
break;
case 7:
dbg("=> Simple POST\n");
http_post("http://httpbin.org/post", "first_word=hello&second_word=world", "Content-Type: application/x-www-form-urlencoded\r\n", http_callback_example);
break;
case 8:
dbg("=> Moved\n");
http_get("http://wikipedia.org/", "", http_callback_example);
break;
case 9:
dbg("=> IP address, 404\n");
http_get("http://54.200.182.206/", "", http_callback_example);
break;
case 10:
dbg("=> Concurrent requests\n");
http_get("http://wtfismyip.com/text", "", http_callback_example);
http_post("http://httpbin.org/post", "first_word=hello&second_word=world", "Content-Type: application/x-www-form-urlencoded\r\n", http_callback_example);
http_get("http://wtfismyip.com/text", "", http_callback_example);
http_post("http://httpbin.org/post", "first_word=hello&second_word=world", "Content-Type: application/x-www-form-urlencoded\r\n", http_callback_example);
http_get("http://wtfismyip.com/text", "", http_callback_example);
http_post("http://httpbin.org/post", "first_word=hello&second_word=world", "Content-Type: application/x-www-form-urlencoded\r\n", http_callback_example);
http_get("http://wtfismyip.com/text", "", http_callback_example);
// FIXME: this test sometimes fails with "DNS error code -1"
break;
default:
dbg("=> DONE\n");
return;
}
test_count++;
os_timer_arm(&test_timer, 3000, 0);
}
void ICACHE_FLASH_ATTR http_test()
{
// FIXME: what happens when no Wifi network is available?
os_timer_disarm(&test_timer);
os_timer_setfn(&test_timer, test_timer_cb, NULL);
os_timer_arm(&test_timer, 0, 0); // Start immediately.
}

@ -22,6 +22,7 @@ typedef RtosConnType* ConnTypePtr;
#define streq(a, b) (strcmp(a, b) == 0)
#define strneq(a, b, n) (strncmp(a, b, n) == 0)
#define strstarts(a, b) (strncmp(a, b, (int)strlen(b)) == 0)
#define malloc(x) os_malloc(x)
#define free(x) os_free(x)

@ -23,6 +23,8 @@
#include "routes.h"
#include "fw_version.h"
#include "httpclient.h"
extern HttpdBuiltInUrl builtInUrls[];
static ETSTimer prSecondTimer;
@ -35,6 +37,8 @@ static void ICACHE_FLASH_ATTR prSecondTimerCb(void *arg)
static u8 cnt = 0;
static u32 last = 0;
static u8 cnt2 = 0;
if (++cnt == 3) {
cnt = 0;
u32 heap = system_get_free_heap_size();
@ -42,6 +46,17 @@ static void ICACHE_FLASH_ATTR prSecondTimerCb(void *arg)
last = heap;
}
if (++cnt2 == 15) {
cnt2 = 0;
dbg("=> Simple GET");
error("=> Simple GET");
warn("=> Simple GET");
info("=> Simple GET");
http_get("http://data.ondrovo.com/f/hello.txt", "", http_callback_example);
}
// we will also try to set up a SBMP connection
if (sbmp_ep_handshake_status(dlnk_ep) != SBMP_HSK_SUCCESS) {
sbmp_ep_start_handshake(dlnk_ep);

Loading…
Cancel
Save