Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.19)
cmake_minimum_required(VERSION 3.18)

find_package(Perl)
if(NOT PERL_FOUND)
Expand Down
4 changes: 2 additions & 2 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ execute_process(COMMAND
WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}
ECHO_OUTPUT_VARIABLE
ECHO_ERROR_VARIABLE
COMMAND_ERROR_IS_FATAL ANY
# COMMAND_ERROR_IS_FATAL ANY
)
file(RENAME fsdata.c my_fsdata.c)

Expand All @@ -37,7 +37,7 @@ target_link_libraries(${PROGRAM_NAME}
)

pico_enable_stdio_usb(${PROGRAM_NAME} TRUE)
pico_enable_stdio_uart(${PROGRAM_NAME} FALSE)
pico_enable_stdio_uart(${PROGRAM_NAME} TRUE)
suppress_tinyusb_warnings()

pico_add_extra_outputs(${PROGRAM_NAME})
162 changes: 162 additions & 0 deletions src/cgi.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
/*
* Copyright (c) 2023 Gerhard Schiller ([email protected])
* SPDX-License-Identifier: GPL-3.0-or-later
* https://www.gnu.org/licenses/gpl-3.0.txt
*
* This code is based on parts of the file: "LwIP/LwIP_HTTP_Server_Raw/Src/httpd_cg_ssi.c"
*
*
* For details see the copyright notice below.
*
* Note: this STMicroelectronics software component has no LICENSE file
* in its root directory.
*
*/


/**
******************************************************************************
* @file LwIP/LwIP_HTTP_Server_Raw/Src/httpd_cg_ssi.c
* @author MCD Application Team
* @brief Webserver SSI and CGI handlers
******************************************************************************
* @attention
*
* Copyright (c) 2017 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not really in favor of adding the file with a specific author name and a different license. What if me or someone else wants to modify/extend it later? It makes maintenance far more complex. There is a common LICENSE file in the root of this repository (it's MIT though).

If you're worried about the STMicroelectronics copyright, why not derive the example implementation from the lwIP example like the other examples in this repository?
https://github.com/lwip-tcpip/lwip/blob/master/contrib/examples/httpd/cgi_example

#include "lwip/apps/httpd.h"
#include "pico/cyw43_arch.h"
#include "lwipopts.h"


#include <string.h>
#include <stdlib.h>

// GPIOs for Leds
#define LED1 18
#define LED2 19
#define LED3 20
#define LED4 21


/* CGI handler for LED control */
const char * LEDS_CGI_Handler(int iIndex, int iNumParams, char *pcParam[], char *pcValue[]);
/* CGI handler for LED control with feedback*/
const char * LEDS_CGI_Handler2(int iIndex, int iNumParams, char *pcParam[], char *pcValue[]);

/* Html request for "/leds.cgi" will start LEDS_CGI_Handler */
const tCGI LEDS_CGI={"/leds.cgi", LEDS_CGI_Handler};
/* Html request for "/leds2.cgi" will start LEDS_CGI_Handler2 */
const tCGI LEDS_CGI2={"/leds2.cgi", LEDS_CGI_Handler2};

/* Cgi call table, two CGI used */
tCGI CGI_TAB[2];

void LED_On(int led){
printf("GPIO%d on\n", led);
gpio_put(led, 1);
}

void LED_Off(int led){
printf("GPIO%d off\n", led);
gpio_put(led, 0);
}

const char * LEDS_CGI_Handler(int iIndex, int iNumParams, char *pcParam[], char *pcValue[])
{
int i=0;

/* First SSI handler iIndex = 0 (see CGI_TAB[] in cgi_init() )*/
if (iIndex==0)
{
/* All leds off */
LED_Off(LED1);
LED_Off(LED2);
LED_Off(LED3);
LED_Off(LED4);

/* Check cgi parameter : application GET /leds.cgi?led=2&led=4 */
for (i=0; i<iNumParams; i++){
/* check parameter "led" */
if (strcmp(pcParam[i] , "led") == 0){
/* switch led1 ON if 1 */
if(strcmp(pcValue[i], "1") == 0)
LED_On(LED1);

/* switch led2 ON if 2 */
else if(strcmp(pcValue[i], "2") == 0)
LED_On(LED2);

/* switch led3 ON if 3 */
else if(strcmp(pcValue[i], "3") == 0)
LED_On(LED3);

/* switch led4 ON if 4 */
else if(strcmp(pcValue[i], "4") == 0)
LED_On(LED4);
}
}
}
/* uri to send after cgi call*/
return "/cgi.html";
}

const char * LEDS_CGI_Handler2(int iIndex, int iNumParams, char *pcParam[], char *pcValue[])
{
int i=0;

/* Second SSI handler iIndex = 1 (see CGI_TAB[] in cgi_init() )*/
if (iIndex==1)
{
/* All leds off */
LED_Off(LED1);
LED_Off(LED2);
LED_Off(LED3);
LED_Off(LED4);

/* Check cgi parameter : application GET /leds.cgi?led=2&led=4 */
for (i=0; i<iNumParams; i++){
/* check parameter "led" */
if (strcmp(pcParam[i] , "led") == 0){
/* switch led1 ON if 1 */
if(strcmp(pcValue[i], "1") == 0)
LED_On(LED1);

/* switch led2 ON if 2 */
else if(strcmp(pcValue[i], "2") == 0)
LED_On(LED2);

/* switch led3 ON if 3 */
else if(strcmp(pcValue[i], "3") == 0)
LED_On(LED3);

/* switch led4 ON if 4 */
else if(strcmp(pcValue[i], "4") == 0)
LED_On(LED4);
}
}
}
/* uri to send after cgi call*/
return "/ssi_cgi.shtml";
}

void cgi_init(void)
{
/* configure CGI handler */
CGI_TAB[0] = LEDS_CGI;
CGI_TAB[1] = LEDS_CGI2;
http_set_cgi_handlers(CGI_TAB, 2);

for(int i = LED1; i <= LED4; i++){
gpio_init(i);
gpio_set_dir(i, GPIO_OUT);
gpio_put(i, 0);
}
}
25 changes: 25 additions & 0 deletions src/fs/cgi.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<!DOCTYPE html>
<html>
<head> <title>Pico W CGI-PAGE</title> </head>
<body> <h1>Pico W</h1>
<h3>CGI-PAGE</h3>

<span>
This page allows you to control four leds: LED1, LED2, LED3 and LED4 connected to GPIO18 - 21<br><br>
To turn a led on/off check/uncheck its corresponding checkbox.<br>
Then click on the "Send" button to submit the changes.<br>
</span>
<br>
<form method="get" action="/leds.cgi">
<input value="1" name="led" type="checkbox">LED1<br>
<input value="2" name="led" type="checkbox">LED2<br>
<input value="3" name="led" type="checkbox">LED3<br>
<input value="4" name="led" type="checkbox">LED4<br>
<br>
<input value="Send" type="submit">
</form>
<br>
<br>
<a href="/index.html">Back</a>
</body>
</html>
10 changes: 8 additions & 2 deletions src/fs/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,11 @@
<head> <title>Pico W</title> </head>
<body> <h1>Pico W</h1>
<p>Hello World</p>
</body>
</html>
<br>
<br>
<br>
<a href="/ssi.shtml">&nbsp;ssi-page: Counter and Voltage</a><br>
<a href="/cgi.html">&nbsp;cgi-page: Ledcontrol</span></a><br>
<a href="/ssi_cgi.shtml">&nbsp;cgi-page: Ledcontrol with feedback</span></a><br>
</body>
</html>
11 changes: 8 additions & 3 deletions src/fs/ssi.shtml
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
<!DOCTYPE html>
<html>
<head> <title>Pico W</title> </head>
<body> <h1>Pico W</h1>
<head> <title>Pico W SSI-PAGE</title> </head>
<body>
<h1>Pico W</h1>
<h3>SSI-PAGE</h3>
<p><!--#Hello--> Times <!--#counter-->!</p>
<p>GPIO26 voltage is: <!--#GPIO-->!</p>
<br>
<br>
<a href="/index.html">Back</a>
</body>
</html>
</html>
29 changes: 29 additions & 0 deletions src/fs/ssi_cgi.shtml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<!DOCTYPE html>
<html>
<head> <title>Pico W CGI-SSI-PAGE</title> </head>
<body> <h1>Pico W</h1>
<h3>CGI with Feedback (ssi) PAGE</h3>

<span>
This page allows you to control four leds: LED1, LED2, LED3 and LED4 connected to GPIO18 - 21<br><br>
To turn a led on/off check/uncheck its corresponding checkbox.<br>
Then click on the "Send" button to submit the changes.<br>
</span>
<br>
<form method="get" action="/leds2.cgi">
<input value="1" name="led" type="checkbox" <!--#state1-->>
<span style=<!--#bg1-->>LED1</span><br>
<input value="2" name="led" type="checkbox" <!--#state2-->>
<span style=<!--#bg2-->>LED2</span><br>
<input value="3" name="led" type="checkbox" <!--#state3-->>
<span style=<!--#bg3-->>LED3</span><br>
<input value="4" name="led" type="checkbox" <!--#state4-->>
<span style=<!--#bg4-->>LED4</span><br>
<input value="Send" type="submit">
</form>
<br>
<br>
<a href="/index.html">Back</a>
</body>
</html>

1 change: 1 addition & 0 deletions src/lwipopts.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@

#define LWIP_HTTPD 1
#define LWIP_HTTPD_SSI 1
#define LWIP_HTTPD_CGI 1
// don't include the tag comment - less work for the CPU, but may be harder to debug
#define LWIP_HTTPD_SSI_INCLUDE_TAG 0
// use generated fsdata
Expand Down
12 changes: 7 additions & 5 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@
#include "pico/cyw43_arch.h"

#include "lwipopts.h"
#include "cgi.h"
#include "ssi.h"

void run_server() {
httpd_init();
ssi_init();
cgi_init();
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit-pick: please fix the indent here

Suggested change
cgi_init();
cgi_init();

printf("Http server initialized.\n");
// infinite loop for now
for (;;) {}
Expand All @@ -23,9 +25,6 @@ int main() {
printf("failed to initialise\n");
return 1;
}
// turn on LED to distinguish from BOOTSEL mode
cyw43_arch_gpio_put(CYW43_WL_GPIO_LED_PIN, 1);

cyw43_arch_enable_sta_mode();
// this seems to be the best be can do using the predefined `cyw43_pm_value` macro:
// cyw43_wifi_pm(&cyw43_state, CYW43_PERFORMANCE_PM);
Expand All @@ -43,6 +42,9 @@ int main() {
auto ip_addr = cyw43_state.netif[CYW43_ITF_STA].ip_addr.addr;
printf("IP Address: %lu.%lu.%lu.%lu\n", ip_addr & 0xFF, (ip_addr >> 8) & 0xFF, (ip_addr >> 16) & 0xFF, ip_addr >> 24);
}

// turn on LED to signal connected
cyw43_arch_gpio_put(CYW43_WL_GPIO_LED_PIN, 1);


run_server();
}
}
58 changes: 55 additions & 3 deletions src/ssi.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,19 @@
// max length of the tags defaults to be 8 chars
// LWIP_HTTPD_MAX_TAG_NAME_LEN
const char * __not_in_flash("httpd") ssi_example_tags[] = {
"Hello",
"counter",
"GPIO"
"Hello", // 0
"counter", // 1
"GPIO", // 2
"state1", // 3
"state2", // 4
"state3", // 5
"state4", // 6
"bg1", // 7
"bg2", // 8
"bg3", // 9
"bg4" // 10
};

u16_t __time_critical_func(ssi_handler)(int iIndex, char *pcInsert, int iInsertLen) {
size_t printed;
switch (iIndex) {
Expand All @@ -32,6 +41,49 @@ u16_t __time_critical_func(ssi_handler)(int iIndex, char *pcInsert, int iInsertL
printed = snprintf(pcInsert, iInsertLen, "%f", voltage);
}
break;
case 3: /* "state1" */
case 4: /* "state2" */
case 5: /* "state3" */
case 6: /* "state4" */
{
bool state;
if(iIndex == 3)
state = gpio_get(LED1);
else if(iIndex == 4)
state = gpio_get(LED2);
else if(iIndex == 5)
state = gpio_get(LED3);
else if(iIndex == 6)
state = gpio_get(LED4);

if(state)
printed = snprintf(pcInsert, iInsertLen, "checked");
else
printed = snprintf(pcInsert, iInsertLen, " ");
}
break;

case 7: /* "bg1" */
case 8: /* "bg2" */
case 9: /* "bg3" */
case 10: /* "bg4" */
{
bool state;
if(iIndex == 7)
state = gpio_get(LED1);
else if(iIndex == 8)
state = gpio_get(LED2);
else if(iIndex == 9)
state = gpio_get(LED3);
else if(iIndex == 10)
state = gpio_get(LED4);

if(state)
printed = snprintf(pcInsert, iInsertLen, "\"background-color:green;\"");
else
printed = snprintf(pcInsert, iInsertLen, "\"background-color:red;\"");
}
break;
default: /* unknown tag */
printed = 0;
break;
Expand Down