Quantcast
Channel: Raspberry Pi Forums
Viewing all articles
Browse latest Browse all 4890

General • Need advice on what to read to understand httpd server.

$
0
0
I modified the Pico C SDK example, and I read a bit about LwIP, as well as browsing the source code as it is in the SDK. I kind of understand the structs and functions used, but I need to distill what I need to create a web page with buttons that can control motors (I have the motor control code already). Reading this a bit: https://savannah.nongnu.org/projects/lwip/

The httpd example lights an LED but it goes to a new page where one has to hit a button to go back to the index.shtml.

I would like to have buttons that don't leave the main index.shtml, how?

I'm currently reading about SSI on the Apache site.

Here is the example httpd server, slighltly modified from the pico-examples (I don't need mDNS):

Code:

/** * Copyright (c) 2022 Raspberry Pi (Trading) Ltd. * * SPDX-License-Identifier: BSD-3-Clause */#ifndef __unused#define __unused __attribute__((unused))#endif#include "pico/cyw43_arch.h"#include "pico/stdlib.h"#include "lwip/ip4_addr.h"#include "lwip/init.h"#include "lwip/apps/httpd.h"//#include "motor_control.h"// breaker added for testingvoid decode_country_code(uint32_t code);// LwIP: Initialize the httpd: set up a listening PCB and bind it to the defined portvoid httpd_init(void);static const char *cgi_handler_test(int iIndex, int iNumParams, char *pcParam[], char *pcValue[]);// Note that the buffer size is limited by LWIP_HTTPD_MAX_TAG_INSERT_LEN, so use LWIP_HTTPD_SSI_MULTIPART to return larger amounts of datau16_t ssi_example_ssi_handler(int iIndex, char *pcInsert, int iInsertLen#if LWIP_HTTPD_SSI_MULTIPART    , uint16_t current_tag_part, uint16_t *next_tag_part#endif);err_t httpd_post_begin(void *connection, const char *uri, const char *http_request,        u16_t http_request_len, int content_len, char *response_uri,        u16_t response_uri_len, u8_t *post_auto_wnd);// Return a value for a parameterchar *httpd_param_value(struct pbuf *p, const char *param_name, char *value_buf, size_t value_buf_len);err_t httpd_post_receive_data(void *connection, struct pbuf *p);void httpd_post_finished(void *connection, char *response_uri, u16_t response_uri_len);static absolute_time_t wifi_connected_time;static bool led_on = false;static tCGI cgi_handlers[] = {    { "/", cgi_handler_test },    { "/index.shtml", cgi_handler_test },};// Be aware of LWIP_HTTPD_MAX_TAG_NAME_LENstatic const char *ssi_tags[] = {    "status",   // case 0    "welcome",  // case 1    "uptime",   // case 2    "ledstate", // case 3    "ledinv",   // case 4    "table",    // case 5};int main(void) {    stdio_init_all();    if (cyw43_arch_init_with_country(CYW43_COUNTRY_UK)) {        printf("failed to initialise\n");        return 1;    }    cyw43_arch_enable_sta_mode();    printf("\nConnecting to WiFi...\n");    if (cyw43_arch_wifi_connect_timeout_ms(WIFI_SSID, WIFI_PASSWORD, CYW43_AUTH_WPA2_AES_PSK, 30000)) {        printf("failed to connect.\n");        exit(1);    } else {        printf("Connected\n");        // Decode and print the country code        decode_country_code(cyw43_arch_get_country_code());    }    printf("Ready, running httpd at %s\n", ip4addr_ntoa(netif_ip4_addr(netif_list)));    // start http server    wifi_connected_time = get_absolute_time();    // setup http server    cyw43_arch_lwip_begin();    httpd_init();    http_set_cgi_handlers(cgi_handlers, LWIP_ARRAYSIZE(cgi_handlers));    http_set_ssi_handler(ssi_example_ssi_handler, ssi_tags, LWIP_ARRAYSIZE(ssi_tags));    cyw43_arch_lwip_end();    while(true) {#if PICO_CYW43_ARCH_POLL        cyw43_arch_poll();        cyw43_arch_wait_for_work_until(led_time);#else        sleep_ms(1000);#endif    }    cyw43_arch_deinit();} // end main()// Function to decode the country codevoid decode_country_code(uint32_t code) {    char a = (char)(code & 0xFF);        // Extract the first character    char b = (char)((code >> 8) & 0xFF); // Extract the second character    int rev = (code >> 16) & 0xFF;       // Extract the revision number    printf("country code: %c%c, Revision: %d\n", a, b, rev); // Print the decoded characters and revision}static const char *cgi_handler_test(int iIndex, int iNumParams, char *pcParam[], char *pcValue[]) {    if (iNumParams > 0) {        if (strcmp(pcParam[0], "test") == 0) {            return "/test.shtml";        }    }    return "/index.shtml";}// Note that the buffer size is limited by LWIP_HTTPD_MAX_TAG_INSERT_LEN, so use LWIP_HTTPD_SSI_MULTIPART to return larger amounts of datau16_t ssi_example_ssi_handler(int iIndex, char *pcInsert, int iInsertLen#if LWIP_HTTPD_SSI_MULTIPART    , uint16_t current_tag_part, uint16_t *next_tag_part#endif) {    size_t printed;    switch (iIndex) {        case 0: { // "status"            printed = snprintf(pcInsert, iInsertLen, "Pass");            break;        }        case 1: { // "welcome"            printed = snprintf(pcInsert, iInsertLen, "Hello from Pico");            break;        }        case 2: { // "uptime"            uint64_t uptime_s = absolute_time_diff_us(wifi_connected_time, get_absolute_time()) / 1e6;            printed = snprintf(pcInsert, iInsertLen, "%"PRIu64, uptime_s);            break;        }        case 3: { // "ledstate"            printed = snprintf(pcInsert, iInsertLen, "%s", led_on ? "ON" : "OFF");            break;        }        case 4: { // "ledinv"            printed = snprintf(pcInsert, iInsertLen, "%s", led_on ? "OFF" : "ON");            break;        }#if LWIP_HTTPD_SSI_MULTIPART        case 5: { /* "table" */            printed = snprintf(pcInsert, iInsertLen, "<tr><td>This is table row number %d</td></tr>", current_tag_part + 1);            // Leave "next_tag_part" unchanged to indicate that all data has been returned for this tag            if (current_tag_part < 9) {                *next_tag_part = current_tag_part + 1;            }            break;        }#endif        default: { // unknown tag            printed = 0;            break;        }    }  return (u16_t)printed;}#if LWIP_HTTPD_SUPPORT_POST#define LED_STATE_BUFSIZE 4static void *current_connection;err_t httpd_post_begin(void *connection, const char *uri, const char *http_request,        u16_t http_request_len, int content_len, char *response_uri,        u16_t response_uri_len, u8_t *post_auto_wnd) {    if (memcmp(uri, "/led.cgi", 8) == 0 && current_connection != connection) {        current_connection = connection;        snprintf(response_uri, response_uri_len, "/ledfail.shtml");        *post_auto_wnd = 1;        return ERR_OK;    }    return ERR_VAL;}// Return a value for a parameterchar *httpd_param_value(struct pbuf *p, const char *param_name, char *value_buf, size_t value_buf_len) {    size_t param_len = strlen(param_name);    u16_t param_pos = pbuf_memfind(p, param_name, param_len, 0);    if (param_pos != 0xFFFF) {        u16_t param_value_pos = param_pos + param_len;        u16_t param_value_len = 0;        u16_t tmp = pbuf_memfind(p, "&", 1, param_value_pos);        if (tmp != 0xFFFF) {            param_value_len = tmp - param_value_pos;        } else {            param_value_len = p->tot_len - param_value_pos;        }        if (param_value_len > 0 && param_value_len < value_buf_len) {            char *result = (char *)pbuf_get_contiguous(p, value_buf, value_buf_len, param_value_len, param_value_pos);            if (result) {                result[param_value_len] = 0;                return result;            }        }    }    return NULL;}err_t httpd_post_receive_data(void *connection, struct pbuf *p) {    err_t ret = ERR_VAL;    LWIP_ASSERT("NULL pbuf", p != NULL);    if (current_connection == connection) {        char buf[LED_STATE_BUFSIZE];        char *val = httpd_param_value(p, "led_state=", buf, sizeof(buf));        if (val) {            led_on = (strcmp(val, "ON") == 0) ? true : false;            cyw43_gpio_set(&cyw43_state, 0, led_on);            ret = ERR_OK;        }    }    pbuf_free(p);    return ret;}void httpd_post_finished(void *connection, char *response_uri, u16_t response_uri_len) {    snprintf(response_uri, response_uri_len, "/ledfail.shtml");    if (current_connection == connection) {        snprintf(response_uri, response_uri_len, "/ledpass.shtml");    }    current_connection = NULL;}#endif

Statistics: Posted by breaker — Thu Feb 13, 2025 8:09 pm — Replies 1 — Views 55



Viewing all articles
Browse latest Browse all 4890

Trending Articles