Skip to content

Concepts First

  • PUT: an HTTP method meaning "replace the resource with the request body" — commonly used to update devices/resources (config, rename).
  • vs POST: PUT usually means "update/overwrite a specific resource", POST usually means "create/submit"; the actual server contract wins.
  • Request body: PUT data goes in the body, sent with Content-Length.
  • URL targets the resource: PUT URLs point to a concrete resource, e.g. http://server:8080/api/device/1.

Example Overview

The SDK's wifi_http example does not demonstrate PUT/DELETE; this self-written example follows the usage in its wifi_http_client.c:

  • after getting an IP, creates http_put_task;
  • builds https_client_request: method = HTTP_PUT, url = HTTP_URL;
  • sends a complete JSON body via req.payload / req.payload_len (no chunked dependency);
  • https_client_request waits synchronously; response_cb prints the server response;
  • repeats every 5 seconds for easy observation.
  • Related reference: GET/POST via the official wifi_http example (GET / POST); DELETE in self-written DELETE; encrypted variant in HTTPS.

Operation Steps

1
Enter the Example Directory

The SDK’s wifi_http example only demonstrates GET/POST; this page is written on its skeleton (marked self-written). First enter the directory:

cd examples/wifi/sta/wifi_http
2
Replace main.c

Overwrite main.c in the example directory with the self-written one below (change HTTP_URL to your test server address):

3
Build the Project

Both Ai-M61 and Ai-M62 use bl616:

make CHIP=bl616 BOARD=bl616dk
4
Flash the Firmware

Hold BOOT, briefly press EN/RST to enter download mode, then flash:

make flash CHIP=bl616 COMX=/dev/ttyUSB0
5
Connect Wi-Fi and Verify

Serial tool at 2000000 baud. After connecting, the program automatically sends a PUT with a JSON body to HTTP_URL and prints the server response. Observe the request body on a server that supports PUT (e.g. a Node/Python API).

wifi_sta_connect Your_SSID 12345678

Code Execution Flow

The complete HTTP PUT flow from boot to response:

APIs Used by the Example

https_client_request(&req, timeout, user_data)

Synchronously issues one HTTP/HTTPS request with req.method = HTTP_PUT.

Parameters:

  • &req: struct https_client_request
  • timeout: timeout in ms (5000 in this example)

Return: >= 0 on success; < 0 on failure

req.payload / req.payload_len()

payload is the body string pointer and payload_len its length; the library computes the Content-Length header automatically. This example sends a JSON body.

Parameters:

  • payload: const char *, request body
  • payload_len: size_t, body size in bytes

Return: none (struct fields)

response_cb(rsp, final_data, user_data)

Response callback, prints the server response to the serial port.

Parameters:

  • rsp: struct http_response
  • final_data: HTTP_DATA_MORE / HTTP_DATA_FINAL

Return: none

Complete Code

The self-written main.c below (written against the SDK wifi_http skeleton and https_client.h; not an SDK file). Collapsed by default; click to expand:

📜 Click to expand self-written http_put main.c full code
c
/*
 * Self-written example: HTTP PUT (based on the SDK's https_client.h)
 * Usage:
 *   1. Overwrite examples/wifi/sta/wifi_http/main.c with this file;
 *   2. Change HTTP_URL to your test server address;
 *   3. make CHIP=bl616 BOARD=bl616dk && make flash CHIP=bl616 COMX=/dev/ttyUSB0;
 *   4. Run wifi_sta_connect <SSID> <password> on the serial shell; the program sends PUT automatically.
 */

#include "FreeRTOS.h"
#include "task.h"
#include "timers.h"

#include <string.h>

#include <lwip/tcpip.h>
#include <lwip/sockets.h>
#include <lwip/netdb.h>

#include "wifi_mgmr_ext.h"
#include "fhost_api.h"
#include "wifi_mgmr.h"

#include "bflb_irq.h"
#include "bflb_uart.h"

#include "rfparam_adapter.h"
#include "async_event.h"
#include "mm.h"
#include "board.h"
#include "shell.h"
#include "https_client.h"

#define DBG_TAG "MAIN"
#include "log.h"

#define HTTP_URL     "http://192.168.1.2:8080/api/device/1"
#define HTTP_PAYLOAD "{\"name\":\"ai-m62\",\"brightness\":80}"

static volatile uint32_t wifi_state = 0;
static struct bflb_device_s *uart0;

extern void shell_init_with_task(struct bflb_device_s *shell);

static int log_output(void *ptr, size_t size)
{
    size_t i;
    for (i = 0; i < size; i++) {
        putchar(((char *)ptr)[i]);
    }
    return (int)i;
}

static void response_cb(struct http_response *rsp,
                        enum http_final_call final_data,
                        void *user_data)
{
    log_output(rsp->recv_buf, rsp->data_len);
    if (final_data == HTTP_DATA_FINAL) {
        LOG_I("\r\n[response finished]\r\n");
    }
}

void wifi_event_handler(async_input_event_t ev, void *priv)
{
    switch (ev->code) {
        case CODE_WIFI_ON_GOT_IP:
            wifi_state = 1;
            LOG_I("Got IP\r\n");
            break;
        case CODE_WIFI_ON_DISCONNECT:
            wifi_state = 0;
            LOG_I("WiFi disconnected\r\n");
            break;
        default:
            break;
    }
}

static void http_put_task(void *param)
{
    struct https_client_request req;
    int ret;

    /* Wait for Wi-Fi to get an IP */
    while (!wifi_state) {
        vTaskDelay(pdMS_TO_TICKS(200));
    }

    while (1) {
        memset(&req, 0, sizeof(req));
        req.method = HTTP_PUT;
        req.url = HTTP_URL;
        req.protocol = "HTTP/1.1";
        req.payload = HTTP_PAYLOAD;
        req.payload_len = strlen(HTTP_PAYLOAD);
        req.response = response_cb;

        LOG_I("HTTP PUT to %s\r\n", HTTP_URL);
        ret = https_client_request(&req, 5 * 1000, "HTTP PUT");
        if (ret < 0) {
            LOG_E("http put request fail ret:%d\r\n", ret);
        } else {
            LOG_I("Http PUT request server success\r\n");
        }

        vTaskDelay(pdMS_TO_TICKS(5000));
    }
}

static void wifi_start_firmware_task(void *param)
{
    LOG_I("Starting wifi ...\r\n");
    async_register_event_filter(EV_WIFI, wifi_event_handler, NULL);
    wifi_task_create();
    LOG_I("Starting fhost ...\r\n");
    fhost_init();
    vTaskDelete(NULL);
}

int main(void)
{
    board_init();

    uart0 = bflb_device_get_by_name("uart0");
    shell_init_with_task(uart0);

    if (0 != rfparam_init(0, NULL, 0)) {
        LOG_I("PHY RF init failed!\r\n");
        return 0;
    }

    tcpip_init(NULL, NULL);

    xTaskCreate(wifi_start_firmware_task, "wifi init", 1024, NULL, 10, NULL);
    xTaskCreate(http_put_task, "http put", 2048, NULL, 11, NULL);

    vTaskStartScheduler();

    while (1) {
    }
}

FAQ

Server returns 404 / 405

404 means the URL path is wrong — PUT must target a concrete resource (e.g. /api/device/1); 405 means the server/endpoint does not support PUT — use a RESTful test service (Express, Spring Boot) instead.

Empty response but success is printed

Some endpoints return an empty body or 204 on success; rely on the status code. To see it, print rsp->status_code in response_cb.

Have questions?

For any other questions, visit the unified Q&A and discussion board: Ai-Thinker Discussions

📜 Click to expand wifi_http/wifi_http_client.c full code
c

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/socket.h>
#include <lwip/api.h>
#include <lwip/arch.h>
#include <lwip/opt.h>
#include <lwip/inet.h>
#include <lwip/errno.h>
#include <netdb.h>

#include "shell.h"
#include "utils_getopt.h"
#include "bflb_mtimer.h"
#include "https_client.h"

#ifndef ARRAY_SIZE
#define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0]))
#endif 

static int payload_cb(int sock, struct http_request *req, void *user_data)
{
    const char *content[] = {
        "foobar",
        "chunked",
        "last"
    };
    char tmp[64];
    int i, pos = 0;

    for (i = 0; i < ARRAY_SIZE(content); i++) {
        pos += snprintf(tmp + pos, sizeof(tmp) - pos,
                "%x\r\n%s\r\n",
                (unsigned int)strlen(content[i]),
                content[i]);
    }

    pos += snprintf(tmp + pos, sizeof(tmp) - pos, "0\r\n\r\n");

    (void)zsock_send(sock, tmp, pos, 0);

    return pos;
}

static int log_output(void *ptr, size_t size)
{
    size_t i;
    for (i = 0; i < size; i++) {
        putchar(((char *)ptr)[i]);
    }
    return i;
}

static void response_cb(struct http_response *rsp,
            enum http_final_call final_data,
            void *user_data)
{
    log_output(rsp->recv_buf, rsp->data_len);
    if (final_data == HTTP_DATA_MORE) {
        //printf("Partial data received (%zd bytes)\r\n", rsp->data_len);
    } else if (final_data == HTTP_DATA_FINAL) {
        //printf("All the data received (%zd bytes)\r\n", rsp->data_len);
    }
}

#define PING_USAGE                                \
    "wifi_http_test [url]\r\n"        \
    "\t url: url or dest server ip\r\n" \

static void wifi_test_http_client_init(int argc, char **argv)
{
    int ret;
    char *url;
    struct https_client_request req;

    if (argc < 2) {
        printf("%s", PING_USAGE);
        return;
    }

    /* get address (argv[1] if present) */
    url = argv[1];

    memset(&req, 0, sizeof(req));
    req.method = HTTP_GET;
    req.url = url;
    req.protocol = "HTTP/1.1";
    req.response = response_cb;

    ret = https_client_request(&req, 3*1000, "IPv4 GET");
    if (ret < 0) {
        printf("http_client get request fail ret:%d\r\n", ret);
    } else {
        printf("Http client GET request server success\r\n");
    }

    const char *headers[] = {
        "Transfer-Encoding: chunked\r\n",
        NULL
    };

    memset(&req, 0, sizeof(req));

    req.method = HTTP_POST;
    req.url = url;
    req.protocol = "HTTP/1.1";
    req.payload_cb = payload_cb;
    req.header_fields = headers;
    req.response = response_cb;

    ret = https_client_request(&req, 3*1000, "IPv4 POST");
    if (ret < 0) {
        printf("http_client post request fail ret:%d\r\n", ret);
    } else {
        printf("Http client POST request server success\r\n");
    }
}

#ifdef CONFIG_SHELL
#include <shell.h>

int cmd_wifi_http_client(int argc, char **argv)
{
    wifi_test_http_client_init(argc, argv);

    return 0;
}

SHELL_CMD_EXPORT_ALIAS(cmd_wifi_http_client, wifi_http_test, wifi http client test);
#endif

Released under the MIT License. Build Time 2026-09-11 14:52:23