Vamos agora acessar uma API REST com a Raspberry Pi Pico, usando o SDK C/C++.
![]() |
| Exemplo de chamada a uma API REST usando o Postman |
Simplificando bastante, uma API REST é (tipicamente) o uso dos métodos HTTP (como GET e POST) para o acesso e manipulação de "recursos". Como exemplo vamos usar uma API de consulta a CEPs. O método que vamos chamar permite obter informações sobre um CEP:
GET http:viacep.com.br/ws/{cep}/json/
onde {cep} é o cep a consultar (oito digitos sem separadores).
A biblioteca lwIP possui um módulo HTTP client para realizar acessos HTTP. Este módulo possui dois métodos: httpc_get_file() e httpc_get_file_dns(). Pode trazer um pouco de confusão o fato dos métodos se chamarem "get file", originalmente o objetivo do HTTP era acessar arquivos de um servidor web.De resto temos a velha brincadeira de callbacks. A assinatura de httpc_get_file_dns() é:
err_t httpc_get_file_dns ( const char *server_name, u16_t port, const char *uri, const httpc_connection_t *settings, altcp_recv_fn recv_fn, void *callback_arg, httpc_state_t **connection)
Onde httpc_connection_t contém
typedef struct _httpc_connection {
ip_addr_t proxy_addr;
u16_t proxy_port;
u8_t use_proxy;
/* this callback is called when the transfer is finished (or aborted) */
httpc_result_fn result_fn;
/* this callback is called after receiving the http headers
It can abort the connection by returning != ERR_OK */
httpc_headers_done_fn headers_done_fn;
} httpc_connection_t;
Temos, portanto, três callbacks envolvidos:
- recv_fn é onde recebemos os dados
- result_fn é onde se recebe somente o resultado final (sem os dados)
- headers_done_fn é onde se recebe os cabeçalhos da resposta
Visto tudo isso podemos fazer um exemplo simples, consultando o CEP 01001000 e enviando o resultado para stdio:
#include <stdio.h>
#include <string.h>
#include <time.h>
#include "pico/stdlib.h"
#include "pico/cyw43_arch.h"
#include "hardware/i2c.h"
#include "lwip/pbuf.h"
#include "lwip/tcp.h"
#include "lwip/apps/http_client.h"
#include "secret.h"
char myBuff[2000];
// chamada quando termina a transferência
void recebeu_resultado(void *arg, httpc_result_t httpc_result,
u32_t rx_content_len, u32_t srv_res, err_t err)
{
printf("\nTransferencia finalizada\n");
printf("resultado=%d\n", httpc_result);
printf("código http=%d\n", srv_res);
}
// chamada quando recebeu os cabeçalhos
err_t recebeu_headers(httpc_state_t *connection, void *arg,
struct pbuf *hdr, u16_t hdr_len, u32_t content_len)
{
printf("\nRecebeu cabecalhos\n");
printf("Tamanho dos dados=%d\n", content_len);
printf("Tamanho dos cabeçalhos %d\n", hdr_len);
pbuf_copy_partial(hdr, myBuff, hdr_len, 0);
myBuff[hdr_len] = 0;
printf("Cabeçalhos: \n");
printf("%s", myBuff);
printf("\nCorpo da resposta:\n");
return ERR_OK;
}
// chamada quando recebeu dados
err_t recebeu_dados(void *arg, struct altcp_pcb *conn,
struct pbuf *p, err_t err)
{
pbuf_copy_partial(p, myBuff, p->tot_len, 0);
myBuff[p->tot_len] = 0;
printf("%s", myBuff);
return ERR_OK;
}
// Programa Principal
int main() {
// Inicia stdio e aguarda conectar USB
stdio_init_all();
while (!stdio_usb_connected()) {
sleep_ms(100);
}
printf("\nTeste API REST\n");
// Inicia CYW43 e defeine o pais
if (cyw43_arch_init_with_country(CYW43_COUNTRY_BRAZIL)) {
printf("failed to initialise\n");
return 1;
}
// Inicia WiFi no modo Station
cyw43_arch_enable_sta_mode();
// Tenta conectar
if (cyw43_arch_wifi_connect_timeout_ms(WIFI_SSID, WIFI_PASSWORD,
CYW43_AUTH_WPA2_AES_PSK, 10000)) {
printf("Erro ao conectar WiFi\n");
return 1;
}
char sIP[] = "xxx.xxx.xxx.xxx";
strcpy (sIP, ip4addr_ntoa(netif_ip4_addr(netif_list)));
printf ("Conectado, IP %s\n", sIP);
// Acessa a API
httpc_connection_t settings;
settings.result_fn = recebeu_resultado;
settings.headers_done_fn = recebeu_headers;
cyw43_arch_lwip_begin();
err_t err = httpc_get_file_dns(
"viacep.com.br", 80, "/ws/01001000/json/",
&settings, recebeu_dados, NULL, NULL
);
cyw43_arch_lwip_end();
printf("Status imediato: %d \n", err);
while (true){
#if PICO_CYW43_ARCH_POLL
cyw43_arch_poll();
sleep_ms(1);
#else
sleep_ms(10);
#endif
}
cyw43_arch_deinit();
return 0;
}
O resultado obtido é:
Teste API REST
Conectado, IP 192.168.15.60
Status imediato: 0
Recebeu cabecalhos
Tamanho dos dados=-1
Tamanho dos cabeçalhos 494
Cabeçalhos:
HTTP/1.1 200 OK
Server: nginx/1.22.0
Date: Tue, 08 Nov 2022 23:16:17 GMT
Content-Type: application/json; charset=utf-8
Transfer-Encoding: chunked
Connection: close
Expires: Wed, 09 Nov 2022 00:16:17 GMT
Cache-Control: max-age=3600
Pragma: public
Cache-Control: public
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET
Access-Control-Allow-Headers: Content-Type, X-Request-With, X-Requested-By
Access-Control-Allow-Credentials: true
Access-Control-Max-Age: 86400
Corpo da resposta:
e0
{
"cep": "01001-000",
"logradouro": "Praça da Sé",
"complemento": "lado ímpar",
"bairro": "Sé",
"localidade": "São Paulo",
"uf": "SP",
"ibge": "3550308",
"gia": "1004",
"ddd": "11",
"siafi": "7107"
}
0
Transferencia finalizada
resultado=0
código http=200
O código acima é bastante grosseiro e limitado. A maioria das APIs utilizam https, o que requer o estabelecimento de uma conexão criptografada (o que ainda preciso estudar como fazer). O módulo HTTP Client não suporta redirecionamento (o que quebrou o primeiro exemplo que eu tentei).
Quem estiver curioso com como é acessar uma API REST usando MicroPython, fique de olho no blog Maker Hero onde vai ser publicado um artigo meu sobre os primeiros passos com a Pi Pico. De um modo geral é bem mais simples (inclusive usar https, porém tive problemas com a acentuação na resposta da API que estou usando aqui);
No próximo (e talvez último) post desta série vamos ver como fazer um webserver rudimentar, permitindo interagir com a Pico W através de um browser.

Um comentário:
Daniel, gostei dos seus projetos em raspberry. Estou fazendo um curso no IFCE, aqui em Fortaleza-Ce., de sistemas embarcados, utilizando a Raspberry Pi Pico W, em linguagem de programação C (visual code). Estou pensando em fazer um projeto para entregar no final do curso que: vou utilizar um mEedidor de temperatura DH22, medir a temperatura, a aumidade, me conectar na internet via Wifi da placa, conectar no e-mail e enviar menssagem para os responsáveis, quando a temperarura e a umidade estiverem fora dos padrões de normalidade. Pergunto você tem alguma coisa que poderia me ajudar a implementar tal projeto?
Menu nome é: Raimu do Eumazio Rocha
E-mail: rocharaimun@gmail.com
Postar um comentário