Задать вопрос
@Denys192

Почему не приходит ответ на HTTP запрос с STM32?

Использую плату STM32F446RE, ENC28J60, LWIP, FreeRTOS. Когда отправляю запрос к удаленному серверу с помощью httpc_get_file_dns, то не получаю ответа. Но стоит исковеркать запрос, то получаю ответ от cloudflare о неправильном запросе. IP по DHCP получается корректно, IP сервера по DNS также получается.

Пока тестирую на первом попавшемся APi времени.

Задача:
void Poll_Task() {
    lwip_init();
    ip4_addr_t ipaddr, netmask, gw;
    IP4_ADDR(&ipaddr, 0, 0, 0, 0);
    IP4_ADDR(&netmask, 0, 0, 0, 0);
    IP4_ADDR(&gw, 0, 0, 0, 0);

    netif_add(&netif_data, &ipaddr, &netmask, &gw, NULL, enc28j60_netif_init, ethernet_input);
    netif_set_default(&netif_data);
    netif_set_up(&netif_data);
    dhcp_start(&netif_data);

    //Настройка DNS серверов
    ip_addr_t dnsserver;
    IP4_ADDR(&dnsserver, 8, 8, 8, 8);  // Google DNS
    dns_setserver(0, &dnsserver);
    IP4_ADDR(&dnsserver, 8, 8, 4, 4);  // Google DNS
    dns_setserver(1, &dnsserver);

    for (;;) {
    	for(uint8_t i = 0; i < 60; i++) {
    		sys_check_timeouts();  // Обработка таймеров LwIP
    		enc28j60_handle_received_packets(&netif_data);  // Обработка входящих пакетов
    		enc28j60_check_link_status(&netif_data);  // Проверка статуса соединения
    		vTaskDelay(pdMS_TO_TICKS(250));  // Добавим задержку, чтобы избежать излишней загрузки процессора
    	}
    	http_get_request();
    }
}


Запрос и обработка ответа
#include <net.h>

extern struct netif netif_data;
extern UART_HandleTypeDef huart2;

httpc_state_t *connection = NULL;

// Функция для обработки результатов HTTP запроса
err_t httpc_result_callback(void *arg, httpc_result_t result, u32_t response_len, void *userdata) {
    char result_msg[50];
    snprintf(result_msg, sizeof(result_msg), "HTTP result: %d, len: %lu\r\n", result, response_len);
    HAL_UART_Transmit(&huart2, (uint8_t*)result_msg, strlen(result_msg), 0x1000);
    return ERR_OK;
}

// Функция для обработки полученных заголовков HTTP
err_t httpc_headers_callback(httpc_state_t *connection, void *arg, struct pbuf *hdr, u16_t hdr_len, u8_t flags) {
    char headers_msg[100];
    snprintf(headers_msg, sizeof(headers_msg), "HTTP headers received: %.*s\r\n", hdr_len, (char*)hdr->payload);
    HAL_UART_Transmit(&huart2, (uint8_t*)headers_msg, strlen(headers_msg), 0x1000);
    pbuf_free(hdr);
    return ERR_OK;
}

// Функция для обработки полученных данных HTTP
err_t httpc_body_callback(void *arg, struct altcp_pcb *conn, struct pbuf *p, err_t err) {
    if (p != NULL) {
        char body_msg[500];
        snprintf(body_msg, sizeof(body_msg), "HTTP body received: %.*s\r\n", p->tot_len, (char*)p->payload);
        HAL_UART_Transmit(&huart2, (uint8_t*)body_msg, strlen(body_msg), 0x1000);
        pbuf_free(p);
    } else {
        HAL_UART_Transmit(&huart2, "HTTP body received: null\r\n", 26, 0x1000);
    }
    return ERR_OK;
}

void http_get_request() {
	const char* server_name = "worldtimeapi.org";
	const char* request_url = "/api/timezone/America/Argentina/Salta";
    u16_t port = 80;
    httpc_connection_t settings;

    memset(&settings, 0, sizeof(settings));
    //settings.result_fn = httpc_result_callback;
    //settings.headers_done_fn = httpc_headers_callback;

    err_t result = httpc_get_file_dns(server_name, port, request_url, &settings, httpc_body_callback, NULL, &connection);

    if (result != ERR_OK) {
        char error_msg[50];
        snprintf(error_msg, sizeof(error_msg), "HTTP request error: %d\r\n", result);
        HAL_UART_Transmit(&huart2, (uint8_t*)error_msg, strlen(error_msg), 0x1000);
    } else {
        HAL_UART_Transmit(&huart2, "HTTP request sent\r\n", 19, 0x1000);
    }
}


Реализация функций для lwip
#include "enc28j60_netif.h"
#include "enc28j60.h"
#include "netif/etharp.h"
#include "lwip/dhcp.h"


#include <stm32f4xx_hal.h>
extern UART_HandleTypeDef huart2;

err_t enc28j60_netif_init(struct netif *netif) {
    uint8_t mac_address[6] = {0x00, 0x26, 0x62, 0x01, 0x02, 0x03};
    netif->hwaddr_len = ETHARP_HWADDR_LEN;
    memcpy(netif->hwaddr, mac_address, ETHARP_HWADDR_LEN);
    netif->mtu = 1500;
    netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP;
    netif->linkoutput = enc28j60_link_output;
    netif->output = etharp_output;
    enc28j60_init(mac_address);
    return ERR_OK;
}
err_t enc28j60_link_output(struct netif *netif, struct pbuf *p) {
    struct pbuf *q;
    uint8_t buffer[1514];  // максимальный размер Ethernet-фрейма
    int len = 0;
    for (q = p; q != NULL; q = q->next) {
        memcpy(buffer + len, q->payload, q->len);
        len += q->len;
        if (len > sizeof(buffer)) break;  // предотвращаем переполнение буфера
    }
    enc28j60_send_packet(buffer, len);
    return ERR_OK;
}
void enc28j60_handle_received_packets(struct netif *netif) {
    uint8_t buf[1514];
    uint16_t len;
    len = enc28j60_recv_packet(buf, sizeof(buf));
    if (len > 0) {
        struct pbuf *p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
        if (p != NULL) {
            pbuf_take(p, buf, len);
            if (netif->input(p, netif) != ERR_OK) {
                pbuf_free(p);
            }
        }
    }
}

void enc28j60_check_link_status(struct netif *netif) {
    uint16_t phstat1 = enc28j60_read_phy(PHSTAT1);
    if (phstat1 & PHSTAT1_LLSTAT) {
        if (!netif_is_link_up(netif)) {
            netif_set_link_up(netif);
            dhcp_start(netif);  // Запустить DHCP, если ссылка только что поднялась
        }
    } else {
        if (netif_is_link_up(netif)) {
            netif_set_link_down(netif);
            dhcp_release(netif);  // Освободить DHCP
            dhcp_stop(netif);     // Остановить DHCP, если ссылка опущена
        }
    }
}
  • Вопрос задан
  • 87 просмотров
Подписаться 1 Средний 1 комментарий
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы