]> gitweb.ps.run Git - matrix_esp_thesis/blobdiff - src/matrix_http_esp32.c
working examples for esp
[matrix_esp_thesis] / src / matrix_http_esp32.c
diff --git a/src/matrix_http_esp32.c b/src/matrix_http_esp32.c
new file mode 100644 (file)
index 0000000..3faf9f5
--- /dev/null
@@ -0,0 +1,315 @@
+#include <string.h>
+#include <sys/param.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include "esp_log.h"
+#include "nvs_flash.h"
+#include "esp_event.h"
+#include "esp_netif.h"
+// #include "protocol_examples_common.h"
+// #include "protocol_examples_utils.h"
+#include "esp_tls.h"
+#if CONFIG_MBEDTLS_CERTIFICATE_BUNDLE
+#include "esp_crt_bundle.h"
+#endif
+
+#if !CONFIG_IDF_TARGET_LINUX
+#include "freertos/FreeRTOS.h"
+#include "freertos/task.h"
+#include "esp_system.h"
+#endif
+
+#include "esp_http_client.h"
+
+/* Root cert for howsmyssl.com, taken from howsmyssl_com_root_cert.pem
+
+   The PEM file was extracted from the output of this command:
+   openssl s_client -showcerts -connect www.howsmyssl.com:443 </dev/null
+
+   The CA root cert is the last cert given in the chain of certs.
+
+   To embed it in the app binary, the PEM file is named
+   in the component.mk COMPONENT_EMBED_TXTFILES variable.
+*/
+// extern const char howsmyssl_com_root_cert_pem_start[] asm("_binary_howsmyssl_com_root_cert_pem_start");
+// extern const char howsmyssl_com_root_cert_pem_end[]   asm("_binary_howsmyssl_com_root_cert_pem_end");
+
+// extern const char postman_root_cert_pem_start[] asm("_binary_postman_root_cert_pem_start");
+// extern const char postman_root_cert_pem_end[]   asm("_binary_postman_root_cert_pem_end");
+
+#include "matrix.h"
+
+#define HTTP_CONNECTION_DATA_SIZE 1024*64
+#define AUTHORIZATION_HEADER_LEN 64
+
+struct MatrixHttpConnection {
+    esp_http_client_handle_t client;
+
+    const char * host;
+    const char * accessToken;
+
+    // char data[HTTP_CONNECTION_DATA_SIZE];
+    char * data;
+    int dataCap;
+    int dataLen;
+};
+
+
+static const char *TAG = "HTTP_CLIENT";
+
+esp_err_t _http_event_handler(esp_http_client_event_t *evt)
+{
+    vTaskDelay(10/portTICK_PERIOD_MS);
+
+    MatrixHttpConnection * hc = (MatrixHttpConnection *)evt->user_data;
+    switch(evt->event_id) {
+        case HTTP_EVENT_ERROR:
+            ESP_LOGD(TAG, "HTTP_EVENT_ERROR");
+            break;
+        case HTTP_EVENT_ON_CONNECTED:
+            ESP_LOGD(TAG, "HTTP_EVENT_ON_CONNECTED");
+            break;
+        case HTTP_EVENT_HEADER_SENT:
+            ESP_LOGD(TAG, "HTTP_EVENT_HEADER_SENT");
+            break;
+        case HTTP_EVENT_ON_HEADER:
+            ESP_LOGD(TAG, "HTTP_EVENT_ON_HEADER, key=%s, value=%s", evt->header_key, evt->header_value);
+            break;
+        case HTTP_EVENT_ON_DATA:
+            ESP_LOGD(TAG, "HTTP_EVENT_ON_DATA, len=%d", evt->data_len);
+            /*
+             *  Check for chunked encoding is added as the URL for chunked encoding used in this example returns binary data.
+             *  However, event handler can also be used in case chunked encoding is used.
+             */
+            if (!esp_http_client_is_chunked_response(evt->client)) {
+                ESP_LOGD(TAG, "Non-Chunked Encoding");
+            }
+            else {
+                ESP_LOGD(TAG, "Chunked Encoding");
+            }
+
+            int copy_len = 0;
+
+            // const int64_t buffer_len = esp_http_client_get_content_length(evt->client);
+            // if (buffer_len < hc->dataCap) {
+            //     ESP_LOGE(TAG, "Output buffer too small: %" PRIu64 ", data_len: %d", buffer_len, evt->data_len);
+            //     return ESP_FAIL;
+            // }
+            copy_len = MIN(evt->data_len, (hc->dataCap - hc->dataLen));
+            if (copy_len) {
+                memcpy(hc->data + hc->dataLen, evt->data, copy_len);
+            }
+
+            hc->dataLen += copy_len;
+
+            break;
+        case HTTP_EVENT_ON_FINISH:
+            ESP_LOGD(TAG, "HTTP_EVENT_ON_FINISH");
+            break;
+        case HTTP_EVENT_DISCONNECTED:
+            ESP_LOGI(TAG, "HTTP_EVENT_DISCONNECTED");
+            int mbedtls_err = 0;
+            esp_err_t err = esp_tls_get_and_clear_last_error((esp_tls_error_handle_t)evt->data, &mbedtls_err, NULL);
+            if (err != 0) {
+                ESP_LOGI(TAG, "Last esp error code: 0x%x", err);
+                ESP_LOGI(TAG, "Last mbedtls failure: 0x%x", mbedtls_err);
+            }
+            break;
+        case HTTP_EVENT_REDIRECT:
+            ESP_LOGD(TAG, "HTTP_EVENT_REDIRECT");
+            // esp_http_client_set_header(evt->client, "From", "user@example.com");
+            // esp_http_client_set_header(evt->client, "Accept", "text/html");
+            // esp_http_client_set_redirection(evt->client);
+            break;
+    }
+    return ESP_OK;
+}
+
+void
+MatrixHttpConnect(
+    MatrixHttpConnection * hc)
+{
+    esp_http_client_config_t config = {
+        .url = hc->host,
+        // .query = "esp",
+        .event_handler = _http_event_handler,
+        .user_data = hc,
+        .disable_auto_redirect = true,
+        .crt_bundle_attach = esp_crt_bundle_attach,
+    };
+
+    hc->client = esp_http_client_init(&config);
+
+    esp_http_client_set_timeout_ms(hc->client, 10000);
+}
+
+void
+MatrixHttpDisconnect(
+    MatrixHttpConnection * hc)
+{
+    esp_http_client_cleanup(hc->client);
+    hc->client = NULL;
+}
+
+bool
+MatrixHttpInit(
+    MatrixHttpConnection ** hc,
+    const char * host)
+{
+    *hc = (MatrixHttpConnection *)calloc(1, sizeof(MatrixHttpConnection));
+    
+    (*hc)->host = host;
+    (*hc)->dataLen = 0;
+
+    MatrixHttpConnect(*hc);
+
+    return true;
+}
+
+bool
+MatrixHttpDeinit(
+    MatrixHttpConnection ** hc)
+{
+    MatrixHttpDisconnect(*hc);
+
+    free(*hc);
+    *hc = NULL;
+
+    return true;
+}
+
+bool
+MatrixHttpSetAccessToken(
+    MatrixHttpConnection * hc,
+    const char * accessToken)
+{
+    hc->accessToken = accessToken;
+
+    return true;
+}
+
+bool
+MatrixHttpGet(
+    MatrixHttpConnection * hc,
+    const char * url,
+    char * outResponseBuffer, int outResponseCap,
+    bool authenticated)
+{
+    static char authorizationHeader[AUTHORIZATION_HEADER_LEN];
+    if (authenticated)
+        snprintf(authorizationHeader, AUTHORIZATION_HEADER_LEN,
+            "Bearer %s", hc->accessToken);
+    else
+        authorizationHeader[0] = '\0';
+
+    printf("GET %s%s\n", hc->host, url);
+
+    hc->data = outResponseBuffer;
+    hc->dataCap = outResponseCap;
+    hc->dataLen = 0;
+
+    static char hostAndUrl[MAX_URL_LEN];
+    snprintf(hostAndUrl, MAX_URL_LEN, "%s%s", hc->host, url);
+    
+    esp_http_client_set_url(hc->client, hostAndUrl);
+    esp_http_client_set_method(hc->client, HTTP_METHOD_GET);
+    if (authenticated)
+        esp_http_client_set_header(hc->client, "Authorization", authorizationHeader);
+    esp_err_t err = esp_http_client_perform(hc->client);
+    if (err == ESP_OK) {
+        ESP_LOGI(TAG, "HTTP GET Status = %d, content_length = %"PRIu64,
+                esp_http_client_get_status_code(hc->client),
+                esp_http_client_get_content_length(hc->client));
+    } else {
+        ESP_LOGE(TAG, "HTTP GET request failed: %s", esp_err_to_name(err));
+    }
+    // ESP_LOG_BUFFER_HEX(TAG, hc->data, hc->dataLen);
+
+    return true;
+}
+
+bool
+MatrixHttpPost(
+    MatrixHttpConnection * hc,
+    const char * url,
+    const char * requestBuffer,
+    char * outResponseBuffer, int outResponseCap,
+    bool authenticated)
+{
+    static char authorizationHeader[AUTHORIZATION_HEADER_LEN];
+    if (authenticated)
+        snprintf(authorizationHeader, AUTHORIZATION_HEADER_LEN,
+            "Bearer %s", hc->accessToken);
+    else
+        authorizationHeader[0] = '\0';
+
+    printf("POST %s%s\n%s\n", hc->host, url, requestBuffer);
+
+    hc->data = outResponseBuffer;
+    hc->dataCap = outResponseCap;
+    hc->dataLen = 0;
+
+    static char hostAndUrl[MAX_URL_LEN];
+    snprintf(hostAndUrl, MAX_URL_LEN, "%s%s", hc->host, url);
+    
+    esp_http_client_set_url(hc->client, hostAndUrl);
+    esp_http_client_set_method(hc->client, HTTP_METHOD_POST);
+    if (authenticated)
+        esp_http_client_set_header(hc->client, "Authorization", authorizationHeader);
+    esp_http_client_set_header(hc->client, "Content-Type", "application/json");
+    esp_http_client_set_post_field(hc->client, requestBuffer, strlen(requestBuffer));
+    esp_err_t err = esp_http_client_perform(hc->client);
+    if (err == ESP_OK) {
+        ESP_LOGI(TAG, "HTTP POST Status = %d, content_length = %"PRIu64,
+                esp_http_client_get_status_code(hc->client),
+                esp_http_client_get_content_length(hc->client));
+    } else {
+        ESP_LOGE(TAG, "HTTP POST request failed: %s", esp_err_to_name(err));
+    }
+    // ESP_LOG_BUFFER_HEX(TAG, hc->data, hc->dataLen);
+
+    return true;
+}
+
+bool
+MatrixHttpPut(
+    MatrixHttpConnection * hc,
+    const char * url,
+    const char * requestBuffer,
+    char * outResponseBuffer, int outResponseCap,
+    bool authenticated)
+{
+    static char authorizationHeader[AUTHORIZATION_HEADER_LEN];
+    if (authenticated)
+        snprintf(authorizationHeader, AUTHORIZATION_HEADER_LEN,
+            "Bearer %s", hc->accessToken);
+    else
+        authorizationHeader[0] = '\0';
+
+    printf("PUT %s%s\n%s\n", hc->host, url, requestBuffer);
+
+    hc->data = outResponseBuffer;
+    hc->dataCap = outResponseCap;
+    hc->dataLen = 0;
+
+    static char hostAndUrl[MAX_URL_LEN];
+    snprintf(hostAndUrl, MAX_URL_LEN, "%s%s", hc->host, url);
+    
+    esp_http_client_set_url(hc->client, hostAndUrl);
+    esp_http_client_set_method(hc->client, HTTP_METHOD_PUT);
+    if (authenticated)
+        esp_http_client_set_header(hc->client, "Authorization", authorizationHeader);
+    esp_http_client_set_header(hc->client, "Content-Type", "application/json");
+    esp_http_client_set_post_field(hc->client, requestBuffer, strlen(requestBuffer));
+    esp_err_t err = esp_http_client_perform(hc->client);
+    if (err == ESP_OK) {
+        ESP_LOGI(TAG, "HTTP PUT Status = %d, content_length = %"PRIu64,
+                esp_http_client_get_status_code(hc->client),
+                esp_http_client_get_content_length(hc->client));
+    } else {
+        ESP_LOGE(TAG, "HTTP PUT request failed: %s", esp_err_to_name(err));
+    }
+    // ESP_LOG_BUFFER_HEX(TAG, hc->data, hc->dataLen);
+
+    return true;
+}