nettoyage
This commit is contained in:
parent
5a33c7d1f7
commit
84f72fa3ef
@ -1,2 +0,0 @@
|
|||||||
idf_component_register(SRCS "http.c"
|
|
||||||
INCLUDE_DIRS "include")
|
|
||||||
@ -1,159 +0,0 @@
|
|||||||
/*
|
|
||||||
http.c - HTTP request routines
|
|
||||||
|
|
||||||
File based on https://github.com/espressif/esp-idf/tree/master/examples/03_http_request
|
|
||||||
|
|
||||||
This file is part of the ESP32 Everest Run project
|
|
||||||
https://github.com/krzychb/esp32-everest-run
|
|
||||||
|
|
||||||
Copyright (c) 2016 Krzysztof Budzynski <krzychb@gazeta.pl>
|
|
||||||
This work is licensed under the Apache License, Version 2.0, January 2004
|
|
||||||
See the file LICENSE for details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "freertos/FreeRTOS.h"
|
|
||||||
#include "freertos/task.h"
|
|
||||||
#include "esp_system.h"
|
|
||||||
#include "esp_log.h"
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
#include "lwip/err.h"
|
|
||||||
#include "lwip/sockets.h"
|
|
||||||
#include "lwip/sys.h"
|
|
||||||
#include "lwip/netdb.h"
|
|
||||||
#include "lwip/dns.h"
|
|
||||||
|
|
||||||
#include "http.h"
|
|
||||||
|
|
||||||
#define RECV_BUFFER_SIZE 64
|
|
||||||
static const char* TAG = "HTTP";
|
|
||||||
|
|
||||||
|
|
||||||
void http_client_on_connected(http_client_data *client, http_callback http_on_connected_cb)
|
|
||||||
{
|
|
||||||
client->http_connected_cb = http_on_connected_cb;
|
|
||||||
}
|
|
||||||
|
|
||||||
void http_client_on_process_chunk(http_client_data *client, http_callback http_process_chunk_cb)
|
|
||||||
{
|
|
||||||
client->http_process_chunk_cb = http_process_chunk_cb;
|
|
||||||
}
|
|
||||||
|
|
||||||
void http_client_on_disconnected(http_client_data *client, http_callback http_disconnected_cb)
|
|
||||||
{
|
|
||||||
client->http_disconnected_cb = http_disconnected_cb;
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_err_t http_client_request(http_client_data *client, const char *web_server, const char *request_string)
|
|
||||||
{
|
|
||||||
const struct addrinfo hints = {
|
|
||||||
.ai_family = AF_INET,
|
|
||||||
.ai_socktype = SOCK_STREAM,
|
|
||||||
};
|
|
||||||
struct addrinfo *res;
|
|
||||||
struct in_addr *addr;
|
|
||||||
int s, r;
|
|
||||||
char recv_buf[RECV_BUFFER_SIZE];
|
|
||||||
|
|
||||||
client->recv_buf = recv_buf;
|
|
||||||
client->recv_buf_size = sizeof(recv_buf);
|
|
||||||
|
|
||||||
int err = getaddrinfo(web_server, "80", &hints, &res);
|
|
||||||
|
|
||||||
if (err != 0 || res == NULL) {
|
|
||||||
ESP_LOGE(TAG, "DNS lookup failed err=%d res=%p", err, res);
|
|
||||||
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
|
||||||
return ESP_ERR_HTTP_DNS_LOOKUP_FAILED;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Code to print the resolved IP.
|
|
||||||
Note: inet_ntoa is non-reentrant, look at ipaddr_ntoa_r for "real" code
|
|
||||||
*/
|
|
||||||
addr = &((struct sockaddr_in *)res->ai_addr)->sin_addr;
|
|
||||||
ESP_LOGI(TAG, "DNS lookup succeeded. IP=%s", inet_ntoa(*addr));
|
|
||||||
|
|
||||||
s = socket(res->ai_family, res->ai_socktype, 0);
|
|
||||||
if (s < 0) {
|
|
||||||
ESP_LOGE(TAG, "... Failed to allocate socket.");
|
|
||||||
freeaddrinfo(res);
|
|
||||||
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
|
||||||
return ESP_ERR_HTTP_FAILED_TO_ALLOCATE_SOCKET;
|
|
||||||
}
|
|
||||||
ESP_LOGI(TAG, "... allocated socket");
|
|
||||||
|
|
||||||
if (connect(s, res->ai_addr, res->ai_addrlen) != 0) {
|
|
||||||
ESP_LOGE(TAG, "... socket connect failed errno=%d", errno);
|
|
||||||
close(s);
|
|
||||||
freeaddrinfo(res);
|
|
||||||
vTaskDelay(4000 / portTICK_PERIOD_MS);
|
|
||||||
return ESP_ERR_HTTP_SOCKET_CONNECT_FAILED;
|
|
||||||
}
|
|
||||||
|
|
||||||
ESP_LOGI(TAG, "... connected");
|
|
||||||
freeaddrinfo(res);
|
|
||||||
if (client->http_connected_cb) {
|
|
||||||
client->http_connected_cb((uint32_t*) client);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (write(s, request_string, strlen(request_string)) < 0) {
|
|
||||||
ESP_LOGE(TAG, "... socket send failed");
|
|
||||||
close(s);
|
|
||||||
vTaskDelay(4000 / portTICK_PERIOD_MS);
|
|
||||||
return ESP_ERR_HTTP_SOCKET_SEND_FAILED;
|
|
||||||
}
|
|
||||||
ESP_LOGI(TAG, "... socket send success");
|
|
||||||
|
|
||||||
/* Read HTTP response */
|
|
||||||
do {
|
|
||||||
bzero(recv_buf, sizeof(recv_buf));
|
|
||||||
r = read(s, recv_buf, sizeof(recv_buf)-1);
|
|
||||||
if (client->http_process_chunk_cb) {
|
|
||||||
client->http_process_chunk_cb((uint32_t*) client);
|
|
||||||
}
|
|
||||||
} while (r > 0);
|
|
||||||
|
|
||||||
ESP_LOGI(TAG, "... done reading from socket. Last read return=%d errno=%d", r, errno);
|
|
||||||
close(s);
|
|
||||||
if (client->http_disconnected_cb) {
|
|
||||||
client->http_disconnected_cb((uint32_t*) client);
|
|
||||||
}
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Out of HTTP response return pointer to response body
|
|
||||||
Function return NULL if end of header cannot be identified
|
|
||||||
*/
|
|
||||||
const char* find_response_body(char * response)
|
|
||||||
{
|
|
||||||
// Identify end of the response headers
|
|
||||||
// http://stackoverflow.com/questions/11254037/how-to-know-when-the-http-headers-part-is-ended
|
|
||||||
char * eol; // end of line
|
|
||||||
char * bol; // beginning of line
|
|
||||||
bool nheaderfound = false; // end of response headers has been found
|
|
||||||
|
|
||||||
bol = response;
|
|
||||||
while ((eol = index(bol, '\n')) != NULL) {
|
|
||||||
// update bol based upon the value of eol
|
|
||||||
bol = eol + 1;
|
|
||||||
// test if end of headers has been reached
|
|
||||||
if ( (!(strncmp(bol, "\r\n", 2))) || (!(strncmp(bol, "\n", 1))) )
|
|
||||||
{
|
|
||||||
// note that end of headers has been found
|
|
||||||
nheaderfound = true;
|
|
||||||
// update the value of bol to reflect the beginning of the line
|
|
||||||
// immediately after the headers
|
|
||||||
if (bol[0] != '\n') {
|
|
||||||
bol += 1;
|
|
||||||
}
|
|
||||||
bol += 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (nheaderfound) {
|
|
||||||
return bol;
|
|
||||||
} else {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@ -1,49 +0,0 @@
|
|||||||
/*
|
|
||||||
http.h - HTTP request routines
|
|
||||||
|
|
||||||
This file is part of the ESP32 Everest Run project
|
|
||||||
https://github.com/krzychb/esp32-everest-run
|
|
||||||
|
|
||||||
Copyright (c) 2016 Krzysztof Budzynski <krzychb@gazeta.pl>
|
|
||||||
This work is licensed under the Apache License, Version 2.0, January 2004
|
|
||||||
See the file LICENSE for details.
|
|
||||||
*/
|
|
||||||
#ifndef HTTP_H
|
|
||||||
#define HTTP_H
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "esp_err.h"
|
|
||||||
|
|
||||||
typedef void (*http_callback)(uint32_t *args);
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
char *recv_buf; /*!< Pointer to a receive buffer, data from the socket are collected here */
|
|
||||||
int recv_buf_size; /*!< Size of the receive buffer */
|
|
||||||
char *proc_buf; /*!< Pointer to processing buffer, chunks of data from receive buffer and collected here. */
|
|
||||||
int proc_buf_size; /*!< Size of processing buffer*/
|
|
||||||
http_callback http_connected_cb; /*!< Pointer to function called once socket connection is established */
|
|
||||||
http_callback http_process_chunk_cb; /*!< Pointer to function called to process contents of receive buffer, once it is filled up */
|
|
||||||
http_callback http_disconnected_cb; /*!< Pointer to function called after disconnecting from the socket */
|
|
||||||
} http_client_data;
|
|
||||||
|
|
||||||
#define ESP_ERR_HTTP_BASE 0x40000
|
|
||||||
#define ESP_ERR_HTTP_DNS_LOOKUP_FAILED (ESP_ERR_HTTP_BASE + 1)
|
|
||||||
#define ESP_ERR_HTTP_FAILED_TO_ALLOCATE_SOCKET (ESP_ERR_HTTP_BASE + 2)
|
|
||||||
#define ESP_ERR_HTTP_SOCKET_CONNECT_FAILED (ESP_ERR_HTTP_BASE + 3)
|
|
||||||
#define ESP_ERR_HTTP_SOCKET_SEND_FAILED (ESP_ERR_HTTP_BASE + 4)
|
|
||||||
|
|
||||||
const char* find_response_body(char * response);
|
|
||||||
void http_client_on_connected(http_client_data *client, http_callback http_connected_cb);
|
|
||||||
void http_client_on_process_chunk(http_client_data *client, http_callback http_process_chunk_cb);
|
|
||||||
void http_client_on_disconnected(http_client_data *client, http_callback http_disconnected_cb);
|
|
||||||
esp_err_t http_client_request(http_client_data *client, const char *web_server, const char *request_string);
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@ -1,2 +0,0 @@
|
|||||||
idf_component_register(SRCS "jsmn.c"
|
|
||||||
INCLUDE_DIRS "include")
|
|
||||||
@ -1,471 +0,0 @@
|
|||||||
/*
|
|
||||||
* MIT License
|
|
||||||
*
|
|
||||||
* Copyright (c) 2010 Serge Zaitsev
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
#ifndef JSMN_H
|
|
||||||
#define JSMN_H
|
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef JSMN_STATIC
|
|
||||||
#define JSMN_API static
|
|
||||||
#else
|
|
||||||
#define JSMN_API extern
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
|
||||||
* JSON type identifier. Basic types are:
|
|
||||||
* o Object
|
|
||||||
* o Array
|
|
||||||
* o String
|
|
||||||
* o Other primitive: number, boolean (true/false) or null
|
|
||||||
*/
|
|
||||||
typedef enum {
|
|
||||||
JSMN_UNDEFINED = 0,
|
|
||||||
JSMN_OBJECT = 1 << 0,
|
|
||||||
JSMN_ARRAY = 1 << 1,
|
|
||||||
JSMN_STRING = 1 << 2,
|
|
||||||
JSMN_PRIMITIVE = 1 << 3
|
|
||||||
} jsmntype_t;
|
|
||||||
|
|
||||||
enum jsmnerr {
|
|
||||||
/* Not enough tokens were provided */
|
|
||||||
JSMN_ERROR_NOMEM = -1,
|
|
||||||
/* Invalid character inside JSON string */
|
|
||||||
JSMN_ERROR_INVAL = -2,
|
|
||||||
/* The string is not a full JSON packet, more bytes expected */
|
|
||||||
JSMN_ERROR_PART = -3
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* JSON token description.
|
|
||||||
* type type (object, array, string etc.)
|
|
||||||
* start start position in JSON data string
|
|
||||||
* end end position in JSON data string
|
|
||||||
*/
|
|
||||||
typedef struct jsmntok {
|
|
||||||
jsmntype_t type;
|
|
||||||
int start;
|
|
||||||
int end;
|
|
||||||
int size;
|
|
||||||
#ifdef JSMN_PARENT_LINKS
|
|
||||||
int parent;
|
|
||||||
#endif
|
|
||||||
} jsmntok_t;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* JSON parser. Contains an array of token blocks available. Also stores
|
|
||||||
* the string being parsed now and current position in that string.
|
|
||||||
*/
|
|
||||||
typedef struct jsmn_parser {
|
|
||||||
unsigned int pos; /* offset in the JSON string */
|
|
||||||
unsigned int toknext; /* next token to allocate */
|
|
||||||
int toksuper; /* superior token node, e.g. parent object or array */
|
|
||||||
} jsmn_parser;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create JSON parser over an array of tokens
|
|
||||||
*/
|
|
||||||
JSMN_API void jsmn_init(jsmn_parser *parser);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Run JSON parser. It parses a JSON data string into and array of tokens, each
|
|
||||||
* describing
|
|
||||||
* a single JSON object.
|
|
||||||
*/
|
|
||||||
JSMN_API int jsmn_parse(jsmn_parser *parser, const char *js, const size_t len,
|
|
||||||
jsmntok_t *tokens, const unsigned int num_tokens);
|
|
||||||
|
|
||||||
#ifndef JSMN_HEADER
|
|
||||||
/**
|
|
||||||
* Allocates a fresh unused token from the token pool.
|
|
||||||
*/
|
|
||||||
static jsmntok_t *jsmn_alloc_token(jsmn_parser *parser, jsmntok_t *tokens,
|
|
||||||
const size_t num_tokens) {
|
|
||||||
jsmntok_t *tok;
|
|
||||||
if (parser->toknext >= num_tokens) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
tok = &tokens[parser->toknext++];
|
|
||||||
tok->start = tok->end = -1;
|
|
||||||
tok->size = 0;
|
|
||||||
#ifdef JSMN_PARENT_LINKS
|
|
||||||
tok->parent = -1;
|
|
||||||
#endif
|
|
||||||
return tok;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fills token type and boundaries.
|
|
||||||
*/
|
|
||||||
static void jsmn_fill_token(jsmntok_t *token, const jsmntype_t type,
|
|
||||||
const int start, const int end) {
|
|
||||||
token->type = type;
|
|
||||||
token->start = start;
|
|
||||||
token->end = end;
|
|
||||||
token->size = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fills next available token with JSON primitive.
|
|
||||||
*/
|
|
||||||
static int jsmn_parse_primitive(jsmn_parser *parser, const char *js,
|
|
||||||
const size_t len, jsmntok_t *tokens,
|
|
||||||
const size_t num_tokens) {
|
|
||||||
jsmntok_t *token;
|
|
||||||
int start;
|
|
||||||
|
|
||||||
start = parser->pos;
|
|
||||||
|
|
||||||
for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) {
|
|
||||||
switch (js[parser->pos]) {
|
|
||||||
#ifndef JSMN_STRICT
|
|
||||||
/* In strict mode primitive must be followed by "," or "}" or "]" */
|
|
||||||
case ':':
|
|
||||||
#endif
|
|
||||||
case '\t':
|
|
||||||
case '\r':
|
|
||||||
case '\n':
|
|
||||||
case ' ':
|
|
||||||
case ',':
|
|
||||||
case ']':
|
|
||||||
case '}':
|
|
||||||
goto found;
|
|
||||||
default:
|
|
||||||
/* to quiet a warning from gcc*/
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (js[parser->pos] < 32 || js[parser->pos] >= 127) {
|
|
||||||
parser->pos = start;
|
|
||||||
return JSMN_ERROR_INVAL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#ifdef JSMN_STRICT
|
|
||||||
/* In strict mode primitive must be followed by a comma/object/array */
|
|
||||||
parser->pos = start;
|
|
||||||
return JSMN_ERROR_PART;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
found:
|
|
||||||
if (tokens == NULL) {
|
|
||||||
parser->pos--;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
token = jsmn_alloc_token(parser, tokens, num_tokens);
|
|
||||||
if (token == NULL) {
|
|
||||||
parser->pos = start;
|
|
||||||
return JSMN_ERROR_NOMEM;
|
|
||||||
}
|
|
||||||
jsmn_fill_token(token, JSMN_PRIMITIVE, start, parser->pos);
|
|
||||||
#ifdef JSMN_PARENT_LINKS
|
|
||||||
token->parent = parser->toksuper;
|
|
||||||
#endif
|
|
||||||
parser->pos--;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fills next token with JSON string.
|
|
||||||
*/
|
|
||||||
static int jsmn_parse_string(jsmn_parser *parser, const char *js,
|
|
||||||
const size_t len, jsmntok_t *tokens,
|
|
||||||
const size_t num_tokens) {
|
|
||||||
jsmntok_t *token;
|
|
||||||
|
|
||||||
int start = parser->pos;
|
|
||||||
|
|
||||||
/* Skip starting quote */
|
|
||||||
parser->pos++;
|
|
||||||
|
|
||||||
for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) {
|
|
||||||
char c = js[parser->pos];
|
|
||||||
|
|
||||||
/* Quote: end of string */
|
|
||||||
if (c == '\"') {
|
|
||||||
if (tokens == NULL) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
token = jsmn_alloc_token(parser, tokens, num_tokens);
|
|
||||||
if (token == NULL) {
|
|
||||||
parser->pos = start;
|
|
||||||
return JSMN_ERROR_NOMEM;
|
|
||||||
}
|
|
||||||
jsmn_fill_token(token, JSMN_STRING, start + 1, parser->pos);
|
|
||||||
#ifdef JSMN_PARENT_LINKS
|
|
||||||
token->parent = parser->toksuper;
|
|
||||||
#endif
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Backslash: Quoted symbol expected */
|
|
||||||
if (c == '\\' && parser->pos + 1 < len) {
|
|
||||||
int i;
|
|
||||||
parser->pos++;
|
|
||||||
switch (js[parser->pos]) {
|
|
||||||
/* Allowed escaped symbols */
|
|
||||||
case '\"':
|
|
||||||
case '/':
|
|
||||||
case '\\':
|
|
||||||
case 'b':
|
|
||||||
case 'f':
|
|
||||||
case 'r':
|
|
||||||
case 'n':
|
|
||||||
case 't':
|
|
||||||
break;
|
|
||||||
/* Allows escaped symbol \uXXXX */
|
|
||||||
case 'u':
|
|
||||||
parser->pos++;
|
|
||||||
for (i = 0; i < 4 && parser->pos < len && js[parser->pos] != '\0';
|
|
||||||
i++) {
|
|
||||||
/* If it isn't a hex character we have an error */
|
|
||||||
if (!((js[parser->pos] >= 48 && js[parser->pos] <= 57) || /* 0-9 */
|
|
||||||
(js[parser->pos] >= 65 && js[parser->pos] <= 70) || /* A-F */
|
|
||||||
(js[parser->pos] >= 97 && js[parser->pos] <= 102))) { /* a-f */
|
|
||||||
parser->pos = start;
|
|
||||||
return JSMN_ERROR_INVAL;
|
|
||||||
}
|
|
||||||
parser->pos++;
|
|
||||||
}
|
|
||||||
parser->pos--;
|
|
||||||
break;
|
|
||||||
/* Unexpected symbol */
|
|
||||||
default:
|
|
||||||
parser->pos = start;
|
|
||||||
return JSMN_ERROR_INVAL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
parser->pos = start;
|
|
||||||
return JSMN_ERROR_PART;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parse JSON string and fill tokens.
|
|
||||||
*/
|
|
||||||
JSMN_API int jsmn_parse(jsmn_parser *parser, const char *js, const size_t len,
|
|
||||||
jsmntok_t *tokens, const unsigned int num_tokens) {
|
|
||||||
int r;
|
|
||||||
int i;
|
|
||||||
jsmntok_t *token;
|
|
||||||
int count = parser->toknext;
|
|
||||||
|
|
||||||
for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) {
|
|
||||||
char c;
|
|
||||||
jsmntype_t type;
|
|
||||||
|
|
||||||
c = js[parser->pos];
|
|
||||||
switch (c) {
|
|
||||||
case '{':
|
|
||||||
case '[':
|
|
||||||
count++;
|
|
||||||
if (tokens == NULL) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
token = jsmn_alloc_token(parser, tokens, num_tokens);
|
|
||||||
if (token == NULL) {
|
|
||||||
return JSMN_ERROR_NOMEM;
|
|
||||||
}
|
|
||||||
if (parser->toksuper != -1) {
|
|
||||||
jsmntok_t *t = &tokens[parser->toksuper];
|
|
||||||
#ifdef JSMN_STRICT
|
|
||||||
/* In strict mode an object or array can't become a key */
|
|
||||||
if (t->type == JSMN_OBJECT) {
|
|
||||||
return JSMN_ERROR_INVAL;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
t->size++;
|
|
||||||
#ifdef JSMN_PARENT_LINKS
|
|
||||||
token->parent = parser->toksuper;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
token->type = (c == '{' ? JSMN_OBJECT : JSMN_ARRAY);
|
|
||||||
token->start = parser->pos;
|
|
||||||
parser->toksuper = parser->toknext - 1;
|
|
||||||
break;
|
|
||||||
case '}':
|
|
||||||
case ']':
|
|
||||||
if (tokens == NULL) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
type = (c == '}' ? JSMN_OBJECT : JSMN_ARRAY);
|
|
||||||
#ifdef JSMN_PARENT_LINKS
|
|
||||||
if (parser->toknext < 1) {
|
|
||||||
return JSMN_ERROR_INVAL;
|
|
||||||
}
|
|
||||||
token = &tokens[parser->toknext - 1];
|
|
||||||
for (;;) {
|
|
||||||
if (token->start != -1 && token->end == -1) {
|
|
||||||
if (token->type != type) {
|
|
||||||
return JSMN_ERROR_INVAL;
|
|
||||||
}
|
|
||||||
token->end = parser->pos + 1;
|
|
||||||
parser->toksuper = token->parent;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (token->parent == -1) {
|
|
||||||
if (token->type != type || parser->toksuper == -1) {
|
|
||||||
return JSMN_ERROR_INVAL;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
token = &tokens[token->parent];
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
for (i = parser->toknext - 1; i >= 0; i--) {
|
|
||||||
token = &tokens[i];
|
|
||||||
if (token->start != -1 && token->end == -1) {
|
|
||||||
if (token->type != type) {
|
|
||||||
return JSMN_ERROR_INVAL;
|
|
||||||
}
|
|
||||||
parser->toksuper = -1;
|
|
||||||
token->end = parser->pos + 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* Error if unmatched closing bracket */
|
|
||||||
if (i == -1) {
|
|
||||||
return JSMN_ERROR_INVAL;
|
|
||||||
}
|
|
||||||
for (; i >= 0; i--) {
|
|
||||||
token = &tokens[i];
|
|
||||||
if (token->start != -1 && token->end == -1) {
|
|
||||||
parser->toksuper = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
break;
|
|
||||||
case '\"':
|
|
||||||
r = jsmn_parse_string(parser, js, len, tokens, num_tokens);
|
|
||||||
if (r < 0) {
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
count++;
|
|
||||||
if (parser->toksuper != -1 && tokens != NULL) {
|
|
||||||
tokens[parser->toksuper].size++;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case '\t':
|
|
||||||
case '\r':
|
|
||||||
case '\n':
|
|
||||||
case ' ':
|
|
||||||
break;
|
|
||||||
case ':':
|
|
||||||
parser->toksuper = parser->toknext - 1;
|
|
||||||
break;
|
|
||||||
case ',':
|
|
||||||
if (tokens != NULL && parser->toksuper != -1 &&
|
|
||||||
tokens[parser->toksuper].type != JSMN_ARRAY &&
|
|
||||||
tokens[parser->toksuper].type != JSMN_OBJECT) {
|
|
||||||
#ifdef JSMN_PARENT_LINKS
|
|
||||||
parser->toksuper = tokens[parser->toksuper].parent;
|
|
||||||
#else
|
|
||||||
for (i = parser->toknext - 1; i >= 0; i--) {
|
|
||||||
if (tokens[i].type == JSMN_ARRAY || tokens[i].type == JSMN_OBJECT) {
|
|
||||||
if (tokens[i].start != -1 && tokens[i].end == -1) {
|
|
||||||
parser->toksuper = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
#ifdef JSMN_STRICT
|
|
||||||
/* In strict mode primitives are: numbers and booleans */
|
|
||||||
case '-':
|
|
||||||
case '0':
|
|
||||||
case '1':
|
|
||||||
case '2':
|
|
||||||
case '3':
|
|
||||||
case '4':
|
|
||||||
case '5':
|
|
||||||
case '6':
|
|
||||||
case '7':
|
|
||||||
case '8':
|
|
||||||
case '9':
|
|
||||||
case 't':
|
|
||||||
case 'f':
|
|
||||||
case 'n':
|
|
||||||
/* And they must not be keys of the object */
|
|
||||||
if (tokens != NULL && parser->toksuper != -1) {
|
|
||||||
const jsmntok_t *t = &tokens[parser->toksuper];
|
|
||||||
if (t->type == JSMN_OBJECT ||
|
|
||||||
(t->type == JSMN_STRING && t->size != 0)) {
|
|
||||||
return JSMN_ERROR_INVAL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
/* In non-strict mode every unquoted value is a primitive */
|
|
||||||
default:
|
|
||||||
#endif
|
|
||||||
r = jsmn_parse_primitive(parser, js, len, tokens, num_tokens);
|
|
||||||
if (r < 0) {
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
count++;
|
|
||||||
if (parser->toksuper != -1 && tokens != NULL) {
|
|
||||||
tokens[parser->toksuper].size++;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
#ifdef JSMN_STRICT
|
|
||||||
/* Unexpected char in strict mode */
|
|
||||||
default:
|
|
||||||
return JSMN_ERROR_INVAL;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tokens != NULL) {
|
|
||||||
for (i = parser->toknext - 1; i >= 0; i--) {
|
|
||||||
/* Unmatched opened object or array */
|
|
||||||
if (tokens[i].start != -1 && tokens[i].end == -1) {
|
|
||||||
return JSMN_ERROR_PART;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new parser based over a given buffer with an array of tokens
|
|
||||||
* available.
|
|
||||||
*/
|
|
||||||
JSMN_API void jsmn_init(jsmn_parser *parser) {
|
|
||||||
parser->pos = 0;
|
|
||||||
parser->toknext = 0;
|
|
||||||
parser->toksuper = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* JSMN_HEADER */
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* JSMN_H */
|
|
||||||
@ -1,7 +0,0 @@
|
|||||||
#include <stdio.h>
|
|
||||||
#include "jsmn.h"
|
|
||||||
|
|
||||||
void func(void)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,3 +1,3 @@
|
|||||||
idf_component_register(SRCS "meteofrance.c"
|
idf_component_register(SRCS "meteofrance.c"
|
||||||
INCLUDE_DIRS "include"
|
INCLUDE_DIRS "include"
|
||||||
REQUIRES http jsmn json esp_http_client esp-tls)
|
REQUIRES json esp_http_client esp-tls)
|
||||||
|
|||||||
@ -24,6 +24,7 @@ struct meteoforecast_data{
|
|||||||
};
|
};
|
||||||
|
|
||||||
typedef void (*weather_data_callback)(struct meteoforecast_data *datas);
|
typedef void (*weather_data_callback)(struct meteoforecast_data *datas);
|
||||||
|
typedef void (*weather_data_start_callback)();
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
unsigned int humidity;
|
unsigned int humidity;
|
||||||
@ -31,11 +32,13 @@ typedef struct {
|
|||||||
float pressure;
|
float pressure;
|
||||||
unsigned long retreival_period;
|
unsigned long retreival_period;
|
||||||
weather_data_callback data_retreived_cb;
|
weather_data_callback data_retreived_cb;
|
||||||
|
weather_data_start_callback data_retreived_cb_start;
|
||||||
} weather_data;
|
} weather_data;
|
||||||
|
|
||||||
void printftemp(struct forecast_temp *tmp);
|
void printftemp(struct forecast_temp *tmp);
|
||||||
void printffd(struct meteoforecast_data *tmp);
|
void printffd(struct meteoforecast_data *tmp);
|
||||||
|
|
||||||
void on_weather_data_retrieval(weather_data_callback data_retreived_cb);
|
void on_weather_data_retrieval(weather_data_callback data_retreived_cb);
|
||||||
|
void on_weather_data_retrieval_start(weather_data_callback data_retreived_cb);
|
||||||
void initialise_weather_data_retrieval(unsigned long retreival_period);
|
void initialise_weather_data_retrieval(unsigned long retreival_period);
|
||||||
|
|
||||||
|
|||||||
@ -18,7 +18,6 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "meteofrance.h"
|
#include "meteofrance.h"
|
||||||
#include "jsmn.h"
|
|
||||||
#include "cJSON.h"
|
#include "cJSON.h"
|
||||||
#include "esp_http_client.h"
|
#include "esp_http_client.h"
|
||||||
#include "esp_tls.h"
|
#include "esp_tls.h"
|
||||||
@ -205,7 +204,9 @@ static bool process_response_body(const char * body)
|
|||||||
|
|
||||||
static void http_request_task(void *pvParameter)
|
static void http_request_task(void *pvParameter)
|
||||||
{
|
{
|
||||||
while(1) {
|
while(1) {
|
||||||
|
ESP_LOGE(TAG,"Début recup méteo --------------------------");
|
||||||
|
weather.data_retreived_cb_start(NULL);
|
||||||
char *local_response_buffer = heap_caps_malloc((MAX_HTTP_OUTPUT_BUFFER + 1)*(sizeof(char)),MALLOC_CAP_SPIRAM);
|
char *local_response_buffer = heap_caps_malloc((MAX_HTTP_OUTPUT_BUFFER + 1)*(sizeof(char)),MALLOC_CAP_SPIRAM);
|
||||||
//char local_response_buffer[MAX_HTTP_OUTPUT_BUFFER + 1] = {0};
|
//char local_response_buffer[MAX_HTTP_OUTPUT_BUFFER + 1] = {0};
|
||||||
/**
|
/**
|
||||||
@ -238,7 +239,7 @@ static void http_request_task(void *pvParameter)
|
|||||||
} else {
|
} else {
|
||||||
ESP_LOGE(TAG, "HTTP GET request failed: %s", esp_err_to_name(err));
|
ESP_LOGE(TAG, "HTTP GET request failed: %s", esp_err_to_name(err));
|
||||||
}
|
}
|
||||||
ESP_LOGE(TAG, "%s",local_response_buffer);
|
//ESP_LOGE(TAG, "%s",local_response_buffer);
|
||||||
|
|
||||||
bool weather_data_phrased = false;
|
bool weather_data_phrased = false;
|
||||||
weather_data_phrased = process_response_body(local_response_buffer);
|
weather_data_phrased = process_response_body(local_response_buffer);
|
||||||
@ -255,13 +256,17 @@ void on_weather_data_retrieval(weather_data_callback data_retreived_cb)
|
|||||||
weather.data_retreived_cb = data_retreived_cb;
|
weather.data_retreived_cb = data_retreived_cb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void on_weather_data_retrieval_start(weather_data_callback data_retreived_cb_start)
|
||||||
|
{
|
||||||
|
weather.data_retreived_cb_start = data_retreived_cb_start;
|
||||||
|
}
|
||||||
|
|
||||||
void initialise_weather_data_retrieval(unsigned long retreival_period)
|
void initialise_weather_data_retrieval(unsigned long retreival_period)
|
||||||
{
|
{
|
||||||
weather.retreival_period = retreival_period;
|
weather.retreival_period = retreival_period;
|
||||||
|
|
||||||
//http_client_on_process_chunk(&http_client, process_chunk);
|
//http_client_on_process_chunk(&http_client, process_chunk);
|
||||||
//http_client_on_disconnected(&http_client, disconnected);
|
//http_client_on_disconnected(&http_client, disconnected);
|
||||||
|
|
||||||
xTaskCreate(&http_request_task, "http_request_task", 10 * 2048, NULL, 5, NULL);
|
xTaskCreate(&http_request_task, "http_request_task", 10 * 2048, NULL, 5, NULL);
|
||||||
ESP_LOGI(TAG, "HTTP request task started");
|
ESP_LOGI(TAG, "HTTP request task started");
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,3 +0,0 @@
|
|||||||
idf_component_register(SRCS "weather.c"
|
|
||||||
INCLUDE_DIRS "include"
|
|
||||||
REQUIRES http jsmn)
|
|
||||||
@ -1,11 +0,0 @@
|
|||||||
menu "Wather data retreival from OpenWeatherMap"
|
|
||||||
|
|
||||||
config OPENWEATHERMAP_API_KEY
|
|
||||||
string "OpenWeatherMap API key"
|
|
||||||
default "12345678901234567890123456789012"
|
|
||||||
help
|
|
||||||
API key obtained from 'https://home.openweathermap.org/' site.
|
|
||||||
|
|
||||||
You need to set up a free account on this site first.
|
|
||||||
|
|
||||||
endmenu
|
|
||||||
@ -1,2 +0,0 @@
|
|||||||
COMPONENT_ADD_INCLUDEDIRS := .
|
|
||||||
|
|
||||||
@ -1,40 +0,0 @@
|
|||||||
/*
|
|
||||||
weather.h - Weather data retrieval from api.openweathermap.org
|
|
||||||
|
|
||||||
This file is part of the ESP32 Everest Run project
|
|
||||||
https://github.com/krzychb/esp32-everest-run
|
|
||||||
|
|
||||||
Copyright (c) 2016 Krzysztof Budzynski <krzychb@gazeta.pl>
|
|
||||||
This work is licensed under the Apache License, Version 2.0, January 2004
|
|
||||||
See the file LICENSE for details.
|
|
||||||
*/
|
|
||||||
#ifndef WEATHER_H
|
|
||||||
#define WEATHER_H
|
|
||||||
|
|
||||||
#include "esp_err.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef void (*weather_data_callback)(uint32_t *args);
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
unsigned int humidity;
|
|
||||||
float temperature;
|
|
||||||
float pressure;
|
|
||||||
unsigned long retreival_period;
|
|
||||||
weather_data_callback data_retreived_cb;
|
|
||||||
} weather_data;
|
|
||||||
|
|
||||||
#define ESP_ERR_WEATHER_BASE 0x50000
|
|
||||||
#define ESP_ERR_WEATHER_RETREIVAL_FAILED (ESP_ERR_WEATHER_BASE + 1)
|
|
||||||
|
|
||||||
void on_weather_data_retrieval(weather_data_callback data_retreived_cb);
|
|
||||||
void initialise_weather_data_retrieval(unsigned long retreival_period);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // WEATHER_H
|
|
||||||
@ -1,183 +0,0 @@
|
|||||||
/*
|
|
||||||
weather.c - Weather data retrieval from api.openweathermap.org
|
|
||||||
|
|
||||||
This file is part of the ESP32 Everest Run project
|
|
||||||
https://github.com/krzychb/esp32-everest-run
|
|
||||||
|
|
||||||
Copyright (c) 2016 Krzysztof Budzynski <krzychb@gazeta.pl>
|
|
||||||
This work is licensed under the Apache License, Version 2.0, January 2004
|
|
||||||
See the file LICENSE for details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "freertos/FreeRTOS.h"
|
|
||||||
#include "freertos/task.h"
|
|
||||||
#include "esp_system.h"
|
|
||||||
#include "esp_log.h"
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "weather.h"
|
|
||||||
#include "http.h"
|
|
||||||
#include "jsmn.h"
|
|
||||||
|
|
||||||
static const char* TAG = "Weather";
|
|
||||||
|
|
||||||
/* Constants that aren't configurable in menuconfig
|
|
||||||
Typically only LOCATION_ID may need to be changed
|
|
||||||
*/
|
|
||||||
#define WEB_SERVER "api.openweathermap.org"
|
|
||||||
#define WEB_URL "http://api.openweathermap.org/data/2.5/weather"
|
|
||||||
// Location ID to get the weather data for
|
|
||||||
//#define LOCATION_ID "756135"
|
|
||||||
#define LATITUDE "49.22017054145735"
|
|
||||||
#define LONGITUDE "3.92188756221628"
|
|
||||||
|
|
||||||
// The API key below is configurable in menuconfig
|
|
||||||
#define OPENWEATHERMAP_API_KEY "24d95e3a2c27a1843590b91bf2cbf37b__"
|
|
||||||
|
|
||||||
static const char *get_request = "GET " WEB_URL"?lat="LATITUDE"&lon="LONGITUDE"&appid="OPENWEATHERMAP_API_KEY" HTTP/1.1\n"
|
|
||||||
"Host: "WEB_SERVER"\n"
|
|
||||||
"Connection: close\n"
|
|
||||||
"User-Agent: esp-idf/1.0 esp32\n"
|
|
||||||
"\n";
|
|
||||||
|
|
||||||
static weather_data weather;
|
|
||||||
static http_client_data http_client = {0};
|
|
||||||
|
|
||||||
/* Collect chunks of data received from server
|
|
||||||
into complete message and save it in proc_buf
|
|
||||||
*/
|
|
||||||
static void process_chunk(uint32_t *args)
|
|
||||||
{
|
|
||||||
http_client_data* client = (http_client_data*)args;
|
|
||||||
|
|
||||||
int proc_buf_new_size = client->proc_buf_size + client->recv_buf_size;
|
|
||||||
char *copy_from;
|
|
||||||
|
|
||||||
if (client->proc_buf == NULL){
|
|
||||||
client->proc_buf = malloc(proc_buf_new_size);
|
|
||||||
copy_from = client->proc_buf;
|
|
||||||
} else {
|
|
||||||
proc_buf_new_size -= 1; // chunks of data are '\0' terminated
|
|
||||||
client->proc_buf = realloc(client->proc_buf, proc_buf_new_size);
|
|
||||||
copy_from = client->proc_buf + proc_buf_new_size - client->recv_buf_size;
|
|
||||||
}
|
|
||||||
if (client->proc_buf == NULL) {
|
|
||||||
ESP_LOGE(TAG, "Failed to allocate memory");
|
|
||||||
}
|
|
||||||
client->proc_buf_size = proc_buf_new_size;
|
|
||||||
memcpy(copy_from, client->recv_buf, client->recv_buf_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int jsoneq(const char *json, jsmntok_t *tok, const char *s) {
|
|
||||||
if (tok->type == JSMN_STRING && (int) strlen(s) == tok->end - tok->start &&
|
|
||||||
strncmp(json + tok->start, s, tok->end - tok->start) == 0) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool process_response_body(const char * body)
|
|
||||||
{
|
|
||||||
/* Using great little JSON parser http://zserge.com/jsmn.html
|
|
||||||
find specific weather information:
|
|
||||||
- Humidity,
|
|
||||||
- Temperature,
|
|
||||||
- Pressure
|
|
||||||
in HTTP response body that happens to be a JSON string
|
|
||||||
|
|
||||||
Return true if phrasing was successful or false if otherwise
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define JSON_MAX_TOKENS 100
|
|
||||||
jsmn_parser parser;
|
|
||||||
jsmntok_t t[JSON_MAX_TOKENS];
|
|
||||||
jsmn_init(&parser);
|
|
||||||
ESP_LOGE(TAG,"%s",body);
|
|
||||||
int r = jsmn_parse(&parser, body, strlen(body), t, JSON_MAX_TOKENS);
|
|
||||||
if (r < 0) {
|
|
||||||
ESP_LOGE(TAG, "JSON parse error %d", r);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (r < 1 || t[0].type != JSMN_OBJECT) {
|
|
||||||
ESP_LOGE(TAG, "JSMN_OBJECT expected");
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
ESP_LOGI(TAG, "Token(s) found %d", r);
|
|
||||||
char subbuff[8];
|
|
||||||
int str_length;
|
|
||||||
for (int i = 1; i < r; i++) {
|
|
||||||
if (jsoneq(body, &t[i], "humidity") == 0) {
|
|
||||||
str_length = t[i+1].end - t[i+1].start;
|
|
||||||
memcpy(subbuff, body + t[i+1].start, str_length);
|
|
||||||
subbuff[str_length] = '\0';
|
|
||||||
weather.humidity = atoi(subbuff);
|
|
||||||
i++;
|
|
||||||
} else if (jsoneq(body, &t[i], "temp") == 0) {
|
|
||||||
str_length = t[i+1].end - t[i+1].start;
|
|
||||||
memcpy(subbuff, body + t[i+1].start, str_length);
|
|
||||||
subbuff[str_length] = '\0';
|
|
||||||
weather.temperature = atof(subbuff);
|
|
||||||
i++;
|
|
||||||
} else if (jsoneq(body, &t[i], "pressure") == 0) {
|
|
||||||
str_length = t[i+1].end - t[i+1].start;
|
|
||||||
memcpy(subbuff, body + t[i+1].start, str_length);
|
|
||||||
subbuff[str_length] = '\0';
|
|
||||||
weather.pressure = atof(subbuff);
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void disconnected(uint32_t *args)
|
|
||||||
{
|
|
||||||
http_client_data* client = (http_client_data*)args;
|
|
||||||
bool weather_data_phrased = false;
|
|
||||||
|
|
||||||
const char * response_body = find_response_body(client->proc_buf);
|
|
||||||
if (response_body) {
|
|
||||||
weather_data_phrased = process_response_body(response_body);
|
|
||||||
} else {
|
|
||||||
ESP_LOGE(TAG, "No HTTP header found");
|
|
||||||
}
|
|
||||||
|
|
||||||
free(client->proc_buf);
|
|
||||||
client->proc_buf = NULL;
|
|
||||||
client->proc_buf_size = 0;
|
|
||||||
|
|
||||||
// execute callback if data was retrieved
|
|
||||||
if (weather_data_phrased) {
|
|
||||||
if (weather.data_retreived_cb) {
|
|
||||||
weather.data_retreived_cb((uint32_t*) &weather);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ESP_LOGD(TAG, "Free heap %u", xPortGetFreeHeapSize());
|
|
||||||
}
|
|
||||||
|
|
||||||
static void http_request_task(void *pvParameter)
|
|
||||||
{
|
|
||||||
while(1) {
|
|
||||||
http_client_request(&http_client, WEB_SERVER, get_request);
|
|
||||||
vTaskDelay(weather.retreival_period / portTICK_PERIOD_MS);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void on_weather_data_retrieval(weather_data_callback data_retreived_cb)
|
|
||||||
{
|
|
||||||
weather.data_retreived_cb = data_retreived_cb;
|
|
||||||
}
|
|
||||||
|
|
||||||
void initialise_weather_data_retrieval(unsigned long retreival_period)
|
|
||||||
{
|
|
||||||
weather.retreival_period = retreival_period;
|
|
||||||
|
|
||||||
http_client_on_process_chunk(&http_client, process_chunk);
|
|
||||||
http_client_on_disconnected(&http_client, disconnected);
|
|
||||||
|
|
||||||
xTaskCreate(&http_request_task, "http_request_task", 2 * 2048, NULL, 5, NULL);
|
|
||||||
ESP_LOGI(TAG, "HTTP request task started");
|
|
||||||
}
|
|
||||||
90
main/main.c
90
main/main.c
@ -270,8 +270,37 @@ static void _app_button_cb(lv_event_t *e)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lv_subject_t wifiStatus;
|
||||||
|
lv_subject_t mqttStatus;
|
||||||
|
lv_subject_t meteoStatus;
|
||||||
|
|
||||||
|
|
||||||
static void app_main_display(void)
|
static void app_main_display(void)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
lv_subject_init_int(&wifiStatus,-1);
|
||||||
|
lv_subject_init_int(&mqttStatus,-1);
|
||||||
|
lv_subject_init_int(&meteoStatus,-1);
|
||||||
|
|
||||||
|
lv_obj_t *cont_status = lv_obj_create(lv_layer_top());
|
||||||
|
lv_obj_align(cont_status,LV_ALIGN_TOP_RIGHT,0,0);
|
||||||
|
lv_obj_set_flex_flow(cont_status, LV_FLEX_FLOW_ROW);
|
||||||
|
lv_obj_set_height(cont_status,LV_SIZE_CONTENT);
|
||||||
|
lv_obj_set_width(cont_status,LV_SIZE_CONTENT);
|
||||||
|
|
||||||
|
lv_obj_t *meteoR = lv_label_create(cont_status);
|
||||||
|
lv_label_set_text(meteoR,"Refresh");
|
||||||
|
lv_label_bind_text(meteoR, &meteoStatus, "Meteo %d");
|
||||||
|
|
||||||
|
lv_obj_t *wifi = lv_label_create(cont_status);
|
||||||
|
lv_label_set_text(wifi,"Wifi Ok");
|
||||||
|
lv_label_bind_text(wifi, &wifiStatus, "Wifi %d");
|
||||||
|
|
||||||
|
|
||||||
|
lv_obj_t *mqtt = lv_label_create(cont_status);
|
||||||
|
lv_label_set_text(mqtt,"Mqtt Ok");
|
||||||
|
lv_label_bind_text(mqtt, &mqttStatus, "Mqtt %d");
|
||||||
|
|
||||||
lv_obj_t *scr = lv_scr_act();
|
lv_obj_t *scr = lv_scr_act();
|
||||||
|
|
||||||
/* Your LVGL objects code here .... */
|
/* Your LVGL objects code here .... */
|
||||||
@ -453,7 +482,7 @@ static lv_obj_t *weatherDay_fragment_create_obj(lv_fragment_t *self, lv_obj_t *p
|
|||||||
lv_image_set_offset_y(img1, -8);
|
lv_image_set_offset_y(img1, -8);
|
||||||
lv_image_set_offset_x(img1, -8);
|
lv_image_set_offset_x(img1, -8);
|
||||||
lv_obj_set_size(img1,40,40);
|
lv_obj_set_size(img1,40,40);
|
||||||
lv_image_set_src(img1, &p1j);
|
lv_image_set_src(img1,LV_SYMBOL_DUMMY);
|
||||||
//lv_obj_set_style_border_width(img1,2,0);
|
//lv_obj_set_style_border_width(img1,2,0);
|
||||||
//lv_obj_set_style_border_color(img1, lv_palette_main(LV_PALETTE_BLUE_GREY), 0);
|
//lv_obj_set_style_border_color(img1, lv_palette_main(LV_PALETTE_BLUE_GREY), 0);
|
||||||
lv_obj_align(img1, LV_ALIGN_CENTER, 0, 0);
|
lv_obj_align(img1, LV_ALIGN_CENTER, 0, 0);
|
||||||
@ -511,6 +540,9 @@ void draw_ihm()
|
|||||||
// keys.clear();
|
// keys.clear();
|
||||||
lv_obj_clean(lv_scr_act());
|
lv_obj_clean(lv_scr_act());
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*Create a Tab view object*/
|
/*Create a Tab view object*/
|
||||||
lv_obj_t * tabview;
|
lv_obj_t * tabview;
|
||||||
tabview = lv_tabview_create(lv_screen_active());
|
tabview = lv_tabview_create(lv_screen_active());
|
||||||
@ -563,17 +595,21 @@ void draw_ihm()
|
|||||||
lv_style_set_align(&style_container, LV_ALIGN_BOTTOM_LEFT);
|
lv_style_set_align(&style_container, LV_ALIGN_BOTTOM_LEFT);
|
||||||
lv_style_set_flex_cross_place(&style_container, LV_FLEX_ALIGN_END);
|
lv_style_set_flex_cross_place(&style_container, LV_FLEX_ALIGN_END);
|
||||||
|
|
||||||
|
static lv_style_t no_padding;
|
||||||
|
lv_style_init(&no_padding);
|
||||||
|
lv_style_set_pad_all(&no_padding, 0);
|
||||||
|
|
||||||
static lv_style_t style_lbvValue;
|
static lv_style_t style_lbvValue;
|
||||||
lv_style_init(&style_lbvValue);
|
lv_style_init(&style_lbvValue);
|
||||||
lv_obj_t *main = tab1;
|
lv_obj_t *main = tab1;
|
||||||
|
lv_obj_add_style(main,&no_padding,0);
|
||||||
lv_style_set_text_font(&style_lbvValue, &lv_font_montserrat_40);
|
lv_style_set_text_font(&style_lbvValue, &lv_font_montserrat_40);
|
||||||
|
|
||||||
lv_obj_set_flex_flow(tab1, LV_FLEX_FLOW_ROW);
|
lv_obj_set_flex_flow(main, LV_FLEX_FLOW_ROW);
|
||||||
lv_obj_set_style_pad_column(tab1, 1, 0);
|
lv_obj_set_style_pad_column(main, 1, 0);
|
||||||
|
|
||||||
/*Create a container with COLUMN flex direction*/
|
/*Create a container with COLUMN flex direction*/
|
||||||
lv_obj_t *cont_col = lv_obj_create(tab1);
|
lv_obj_t *cont_col = lv_obj_create(main);
|
||||||
lv_obj_set_style_pad_all(cont_col, 5, 0);
|
lv_obj_set_style_pad_all(cont_col, 5, 0);
|
||||||
lv_obj_set_size(cont_col, 250, 480);
|
lv_obj_set_size(cont_col, 250, 480);
|
||||||
lv_obj_align(cont_col, LV_ALIGN_TOP_LEFT, 0, 0);
|
lv_obj_align(cont_col, LV_ALIGN_TOP_LEFT, 0, 0);
|
||||||
@ -581,7 +617,7 @@ void draw_ihm()
|
|||||||
lv_obj_set_flex_align(cont_col,LV_FLEX_ALIGN_CENTER,LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
|
lv_obj_set_flex_align(cont_col,LV_FLEX_ALIGN_CENTER,LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
|
||||||
|
|
||||||
/*Create a container with COLUMN flex direction*/
|
/*Create a container with COLUMN flex direction*/
|
||||||
lv_obj_t *cont_col2 = lv_obj_create(tab1);
|
lv_obj_t *cont_col2 = lv_obj_create(main);
|
||||||
lv_obj_set_style_pad_all(cont_col2, 5, 0);
|
lv_obj_set_style_pad_all(cont_col2, 5, 0);
|
||||||
lv_obj_set_flex_align(cont_col2, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
|
lv_obj_set_flex_align(cont_col2, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
|
||||||
|
|
||||||
@ -760,6 +796,10 @@ static void wifi_event_handler(void *arg, esp_event_base_t event_base,
|
|||||||
}
|
}
|
||||||
else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED)
|
else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED)
|
||||||
{
|
{
|
||||||
|
if(lvgl_port_lock(0)){
|
||||||
|
lv_subject_set_int(&wifiStatus,0);
|
||||||
|
lvgl_port_unlock();
|
||||||
|
}
|
||||||
if (s_retry_num < EXAMPLE_ESP_MAXIMUM_RETRY)
|
if (s_retry_num < EXAMPLE_ESP_MAXIMUM_RETRY)
|
||||||
{
|
{
|
||||||
esp_wifi_connect();
|
esp_wifi_connect();
|
||||||
@ -774,6 +814,10 @@ static void wifi_event_handler(void *arg, esp_event_base_t event_base,
|
|||||||
}
|
}
|
||||||
else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP)
|
else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP)
|
||||||
{
|
{
|
||||||
|
if(lvgl_port_lock(0)){
|
||||||
|
lv_subject_set_int(&wifiStatus,1);
|
||||||
|
lvgl_port_unlock();
|
||||||
|
}
|
||||||
ip_event_got_ip_t *event = (ip_event_got_ip_t *)event_data;
|
ip_event_got_ip_t *event = (ip_event_got_ip_t *)event_data;
|
||||||
ESP_LOGI(TAG, "got ip:" IPSTR, IP2STR(&event->ip_info.ip));
|
ESP_LOGI(TAG, "got ip:" IPSTR, IP2STR(&event->ip_info.ip));
|
||||||
s_retry_num = 0;
|
s_retry_num = 0;
|
||||||
@ -839,15 +883,28 @@ void wifi_init_sta(void)
|
|||||||
{
|
{
|
||||||
ESP_LOGI(TAG, "connected to ap SSID:%s password:%s",
|
ESP_LOGI(TAG, "connected to ap SSID:%s password:%s",
|
||||||
EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS);
|
EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS);
|
||||||
|
if(lvgl_port_lock(0)){
|
||||||
|
lv_subject_set_int(&wifiStatus,1);
|
||||||
|
lvgl_port_unlock();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (bits & WIFI_FAIL_BIT)
|
else if (bits & WIFI_FAIL_BIT)
|
||||||
{
|
{
|
||||||
ESP_LOGI(TAG, "Failed to connect to SSID:%s, password:%s",
|
ESP_LOGI(TAG, "Failed to connect to SSID:%s, password:%s",
|
||||||
EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS);
|
EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS);
|
||||||
|
if(lvgl_port_lock(0)){
|
||||||
|
lv_subject_set_int(&wifiStatus,0);
|
||||||
|
lvgl_port_unlock();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ESP_LOGE(TAG, "UNEXPECTED EVENT");
|
ESP_LOGE(TAG, "UNEXPECTED EVENT");
|
||||||
|
if(lvgl_port_lock(0)){
|
||||||
|
lv_subject_set_int(&wifiStatus,0);
|
||||||
|
lvgl_port_unlock();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -901,6 +958,10 @@ static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_
|
|||||||
switch ((esp_mqtt_event_id_t)event_id)
|
switch ((esp_mqtt_event_id_t)event_id)
|
||||||
{
|
{
|
||||||
case MQTT_EVENT_CONNECTED:
|
case MQTT_EVENT_CONNECTED:
|
||||||
|
if(lvgl_port_lock(0)){
|
||||||
|
lv_subject_set_int(&mqttStatus,1);
|
||||||
|
lvgl_port_unlock();
|
||||||
|
}
|
||||||
ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED");
|
ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED");
|
||||||
msg_id = esp_mqtt_client_publish(client, "/topic/qos1", "data_3", 0, 1, 0);
|
msg_id = esp_mqtt_client_publish(client, "/topic/qos1", "data_3", 0, 1, 0);
|
||||||
ESP_LOGI(TAG, "sent publish successful, msg_id=%d", msg_id);
|
ESP_LOGI(TAG, "sent publish successful, msg_id=%d", msg_id);
|
||||||
@ -924,6 +985,10 @@ static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_
|
|||||||
ESP_LOGI(TAG, "sent unsubscribe successful, msg_id=%d", msg_id);
|
ESP_LOGI(TAG, "sent unsubscribe successful, msg_id=%d", msg_id);
|
||||||
break;
|
break;
|
||||||
case MQTT_EVENT_DISCONNECTED:
|
case MQTT_EVENT_DISCONNECTED:
|
||||||
|
if(lvgl_port_lock(0)){
|
||||||
|
lv_subject_set_int(&mqttStatus,0);
|
||||||
|
lvgl_port_unlock();
|
||||||
|
}
|
||||||
ESP_LOGI(TAG, "MQTT_EVENT_DISCONNECTED");
|
ESP_LOGI(TAG, "MQTT_EVENT_DISCONNECTED");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -1043,6 +1108,15 @@ static void mqtt_app_start(void)
|
|||||||
esp_mqtt_client_start(client);
|
esp_mqtt_client_start(client);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void weather_data_retreived_start()
|
||||||
|
{
|
||||||
|
ESP_LOGE(TAG,"Début recup méteo");
|
||||||
|
if(lvgl_port_lock(0)){
|
||||||
|
lv_subject_set_int(&meteoStatus,1);
|
||||||
|
lvgl_port_unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void weather_data_retreived(struct meteoforecast_data datas[3])
|
void weather_data_retreived(struct meteoforecast_data datas[3])
|
||||||
{
|
{
|
||||||
// struct meteoforecast_data* weather = (meteoforecast_data*) args;
|
// struct meteoforecast_data* weather = (meteoforecast_data*) args;
|
||||||
@ -1065,6 +1139,7 @@ void weather_data_retreived(struct meteoforecast_data datas[3])
|
|||||||
lv_subject_set_pointer(&tempD1Subj, &datas[0]);
|
lv_subject_set_pointer(&tempD1Subj, &datas[0]);
|
||||||
lv_subject_set_pointer(&tempD2Subj, &datas[1]);
|
lv_subject_set_pointer(&tempD2Subj, &datas[1]);
|
||||||
lv_subject_set_pointer(&tempD3Subj, &datas[2]);
|
lv_subject_set_pointer(&tempD3Subj, &datas[2]);
|
||||||
|
lv_subject_set_int(&meteoStatus,0);
|
||||||
lvgl_port_unlock();
|
lvgl_port_unlock();
|
||||||
ESP_LOGE(TAG, "------------------------------------- Fin Set des subjects --------------------------------");
|
ESP_LOGE(TAG, "------------------------------------- Fin Set des subjects --------------------------------");
|
||||||
}
|
}
|
||||||
@ -1099,8 +1174,9 @@ void app_main(void)
|
|||||||
wifi_init_sta();
|
wifi_init_sta();
|
||||||
mqtt_app_start();
|
mqtt_app_start();
|
||||||
|
|
||||||
initialise_weather_data_retrieval(60000);
|
|
||||||
on_weather_data_retrieval(weather_data_retreived);
|
on_weather_data_retrieval(weather_data_retreived);
|
||||||
|
on_weather_data_retrieval_start(weather_data_retreived_start);
|
||||||
|
initialise_weather_data_retrieval(60000);
|
||||||
ESP_LOGW(TAG, "Weather data retrieval initialized");
|
ESP_LOGW(TAG, "Weather data retrieval initialized");
|
||||||
|
|
||||||
/* Show LVGL objects */
|
/* Show LVGL objects */
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user