add http client from pico example

This commit is contained in:
PoliEcho 2025-09-08 19:57:43 +02:00
parent 5c5d4eb48c
commit 0d672a4313
3 changed files with 127 additions and 46 deletions

View File

@ -28,7 +28,7 @@ pico_sdk_init()
# Add executable. Default name is the project name, version 0.1
add_executable(smart_alarm smart_alarm.cpp )
add_executable(smart_alarm smart_alarm.cpp http_client_util.c)
pico_set_program_name(smart_alarm "smart_alarm")
pico_set_program_version(smart_alarm "0.1")

126
http_client_util.h Normal file
View File

@ -0,0 +1,126 @@
/**
* Copyright (c) 2024 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef EXAMPLE_HTTP_CLIENT_UTIL_H
#define EXAMPLE_HTTP_CLIENT_UTIL_H
#include "lwip/apps/http_client.h"
/*! \brief Parameters used to make HTTP request
* \ingroup pico_lwip
*/
typedef struct HTTP_REQUEST {
/*!
* The name of the host, e.g. www.raspberrypi.com
*/
const char *hostname;
/*!
* The url to request, e.g. /favicon.ico
*/
const char *url;
/*!
* Function to callback with headers, can be null
* @see httpc_headers_done_fn
*/
httpc_headers_done_fn headers_fn;
/*!
* Function to callback with results from the server, can be null
* @see altcp_recv_fn
*/
altcp_recv_fn recv_fn;
/*!
* Function to callback with final results of the request, can be null
* @see httpc_result_fn
*/
httpc_result_fn result_fn;
/*!
* Callback to pass to calback functions
*/
void *callback_arg;
/*!
* The port to use. A default port is chosen if this is set to zero
*/
uint16_t port;
#if LWIP_ALTCP && LWIP_ALTCP_TLS
/*!
* TLS configuration, can be null or set to a correctly configured tls configuration.
* e.g altcp_tls_create_config_client(NULL, 0) would use https without a certificate
*/
struct altcp_tls_config *tls_config;
/*!
* TLS allocator, used internall for setting TLS server name indication
*/
altcp_allocator_t tls_allocator;
#endif
/*!
* LwIP HTTP client settings
*/
httpc_connection_t settings;
/*!
* Flag to indicate when the request is complete
*/
int complete;
/*!
* Overall result of http request, only valid when complete is set
*/
httpc_result_t result;
} HTTP_REQUEST_T;
struct async_context;
/*! \brief Perform a http request asynchronously
* \ingroup pico_lwip
*
* Perform the http request asynchronously
*
* @param context async context
* @param req HTTP request parameters. As a minimum this should be initialised to zero with hostname and url set to valid values
* @return If zero is returned the request has been made and is complete when \em req->complete is true or the result callback has been called.
* A non-zero return value indicates an error.
*
* @see async_context
*/
int http_client_request_async(struct async_context *context, HTTP_REQUEST_T *req);
/*! \brief Perform a http request synchronously
* \ingroup pico_lwip
*
* Perform the http request synchronously
*
* @param context async context
* @param req HTTP request parameters. As a minimum this should be initialised to zero with hostname and url set to valid values
* @param result Returns the overall result of the http request when complete. Zero indicates success.
*/
int http_client_request_sync(struct async_context *context, HTTP_REQUEST_T *req);
/*! \brief A http header callback that can be passed to \em http_client_init or \em http_client_init_secure
* \ingroup pico_http_client
*
* An implementation of the http header callback which just prints headers to stdout
*
* @param arg argument specified on initialisation
* @param hdr header pbuf(s) (may contain data also)
* @param hdr_len length of the headers in 'hdr'
* @param content_len content length as received in the headers (-1 if not received)
* @return if != zero is returned, the connection is aborted
*/
err_t http_client_header_print_fn(httpc_state_t *connection, void *arg, struct pbuf *hdr, u16_t hdr_len, u32_t content_len);
/*! \brief A http recv callback that can be passed to http_client_init or http_client_init_secure
* \ingroup pico_http_client
*
* An implementation of the http recv callback which just prints the http body to stdout
*
* @param arg argument specified on initialisation
* @param conn http client connection
* @param p body pbuf(s)
* @param err Error code in the case of an error
* @return if != zero is returned, the connection is aborted
*/
err_t http_client_receive_print_fn(void *arg, struct altcp_pcb *conn, struct pbuf *p, err_t err);
#endif

View File

@ -27,53 +27,8 @@
#define PIN_SCK 18
#define PIN_MOSI 19
static void result_fn(void *arg, httpc_result_t httpc_result,
u32_t rx_content_len, u32_t srv_res, err_t err) {
if (httpc_result == HTTPC_RESULT_OK && err == ERR_OK) {
printf("Request completed successfully. Received %lu bytes\n", rx_content_len);
} else {
printf("Request failed - HTTP result: %d, lwIP error: %d, HTTP status: %lu\n",
httpc_result, err, srv_res);
}
}
static err_t get_timezone_callback(void *arg, struct altcp_pcb *pcb,
struct pbuf *p, err_t err) {
if (p == NULL) {
// Connection closed
return ERR_OK;
}
// Print the JSON response body
char *json_data = (char *)p->payload;
printf("%.*s\n", p->len, json_data);
// Required: Free memory and acknowledge receipt
uint16_t len = p->tot_len;
pbuf_free(p);
altcp_recved(pcb, len);
return ERR_OK;
}
err_t get_timezone_offset() {
httpc_connection_t settings = {.use_proxy = 0,
.result_fn = result_fn,
.headers_done_fn = NULL};
memset(&settings, 0, sizeof(settings));
settings.use_proxy = 0;
settings.result_fn = result_fn;
settings.headers_done_fn = NULL;
httpc_state_t *connection = NULL;
err_t err = httpc_get_file_dns("worldtimeapi.org", 80, "/api/ip", &settings,
get_timezone_callback, NULL, &connection);
if (err != ERR_OK) {
printf("Failed to start request: %d\n", err);
}
return err;
}
#define TIMEZONE_OFFSET_SEC 7200