diff --git a/.gitignore b/.gitignore
index e7516f7..360dd94 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,3 @@
**/build/*
**/secret.h
-**/htmldata.c
\ No newline at end of file
+**/wwwdata.c
\ No newline at end of file
diff --git a/Makefile b/Makefile
index dec91a7..75e4bca 100644
--- a/Makefile
+++ b/Makefile
@@ -1,16 +1,13 @@
-#TOPTARGETS := all clean
+.PHONY: all clean build makefsdata
-SUBDIRS := build
+all: clean makefsdata build
-all: makefsdata $(SUBDIRS)
+clean:
+ $(MAKE) -C build/ clean
+ rm -rf wwwdata.c
makefsdata:
python3 makefsdata.py
-clean: $(SUBDIRS)
- rm -rf htmldata.c
-
-$(SUBDIRS):
- $(MAKE) -C $@ $(MAKECMDGOALS)
-
-.PHONY: all makefsdata clean $(SUBDIRS)
\ No newline at end of file
+build:
+ $(MAKE) -C build/
\ No newline at end of file
diff --git a/cgi.h b/cgi.h
index 3608d98..8d9dddc 100644
--- a/cgi.h
+++ b/cgi.h
@@ -1,32 +1,40 @@
+#ifndef CGI_H
+#define CGI_H
+
#include "lwip/apps/httpd.h"
#include "pico/cyw43_arch.h"
+#include "handlers.h"
-// CGI handler which is run when a request for /led.cgi is detected
-const char * cgi_led_handler(int iIndex, int iNumParams, char *pcParam[], char *pcValue[])
-{
- // Check if an request for LED has been made (/led.cgi?led=x)
- if (strcmp(pcParam[0] , "led") == 0){
- // Look at the argument to check if LED is to be turned on (x=1) or off (x=0)
- if(strcmp(pcValue[0], "0") == 0)
- cyw43_arch_gpio_put(CYW43_WL_GPIO_LED_PIN, 0);
- else if(strcmp(pcValue[0], "1") == 0)
- cyw43_arch_gpio_put(CYW43_WL_GPIO_LED_PIN, 1);
- }
-
- // Send the index page back to the user
- return "/index.shtml";
+const char * cgi_power_handler (int iIndex, int iNumParams, char *pcParam[], char *pcValue[]) {
+ // Check if an request for power has been made (/power?requested_state=x)
+ if (strcmp(pcParam[0] , "requested_state") == 0){
+ // Look at the argument to check if LED is to be turned on (x=1) or off (x=0)
+ if(strcmp(pcValue[0], "0") == 0) {
+ bmc_power_handler(false);
+ }
+ else if(strcmp(pcValue[0], "1") == 0) {
+ bmc_power_handler(true);
+ }
+ }
+ // Send the index page back to the user
+ return "/power.ssi";
+}
+
+const char * cgi_status_handler (int iIndex, int iNumParams, char *pcParam[], char *pcValue[]) {
+ return "/status.ssi";
}
-// tCGI Struct
-// Fill this with all of the CGI requests and their respective handlers
static const tCGI cgi_handlers[] = {
- {
- // Html request for "/led.cgi" triggers cgi_handler
- "/led.cgi", cgi_led_handler
- },
+ {
+ "/power", cgi_power_handler
+ },
+ {
+ "/status", cgi_status_handler
+ }
};
-void cgi_init(void)
-{
- http_set_cgi_handlers(cgi_handlers, 1);
-}
\ No newline at end of file
+void cgi_init(void) {
+ http_set_cgi_handlers(cgi_handlers, 2);
+}
+
+#endif
\ No newline at end of file
diff --git a/handlers.h b/handlers.h
new file mode 100644
index 0000000..e384aca
--- /dev/null
+++ b/handlers.h
@@ -0,0 +1,38 @@
+#ifndef HANDLERS_H
+#define HANDLERS_H
+
+#include "pico/stdlib.h"
+
+#define PW_SW_DELAY_MS 100
+#define STATE_UPDATE_REPEAT_DELAY_MS 100
+
+bool current_state = false;
+
+int64_t pw_sw_on_async (alarm_id_t id, void * user_data) {
+ cyw43_arch_gpio_put(CYW43_WL_GPIO_LED_PIN, 1);
+ return 0; // do not reschedule alarm
+}
+
+int64_t pw_sw_off_async (alarm_id_t id, void * user_data) {
+ cyw43_arch_gpio_put(CYW43_WL_GPIO_LED_PIN, 0);
+ return 0; // do not reschedule alarm
+}
+
+bool update_current_state_async (repeating_timer_t * rt) {
+ return true; // continue repeating alarm
+}
+
+bool bmc_power_handler (bool requested_state) {
+ if (requested_state != current_state) {
+ add_alarm_in_ms(0, pw_sw_on_async, NULL, true);
+ add_alarm_in_ms(PW_SW_DELAY_MS, pw_sw_off_async, NULL, true);
+ }
+}
+
+struct repeating_timer * bmc_handler_init () {
+ struct repeating_timer * timer = malloc(sizeof(struct repeating_timer));
+ add_repeating_timer_ms(STATE_UPDATE_REPEAT_DELAY_MS, update_current_state_async, NULL, timer);
+ return timer;
+}
+
+#endif
\ No newline at end of file
diff --git a/html_files/index.shtml b/html_files/index.shtml
deleted file mode 100644
index 1ce5ee8..0000000
--- a/html_files/index.shtml
+++ /dev/null
@@ -1,20 +0,0 @@
-
-
-
- PicoW Webserver
-
- PicoW Webserver Tutorial
-
- This bit is SSI:
- Voltage:
- Temp: C
- LED is:
-
- This bit is CGI:
-
-
-
-
- Refresh
-
-
\ No newline at end of file
diff --git a/lwipopts.h b/lwipopts.h
index b4ea9a3..4ac3fd8 100644
--- a/lwipopts.h
+++ b/lwipopts.h
@@ -90,4 +90,4 @@
#define LWIP_HTTPD_CGI 1
#define LWIP_HTTPD_SSI_INCLUDE_TAG 0
#define HTTPD_SERVER_PORT 80
-#define HTTPD_FSDATA_FILE "htmldata.c"
\ No newline at end of file
+#define HTTPD_FSDATA_FILE "wwwdata.c"
\ No newline at end of file
diff --git a/makefsdata.py b/makefsdata.py
index d9bba5a..7a734af 100644
--- a/makefsdata.py
+++ b/makefsdata.py
@@ -8,13 +8,13 @@ import os
import binascii
#Create file to write output into
-output = open('htmldata.c', 'w')
+output = open('wwwdata.c', 'w')
#Traverse directory, generate list of files
files = list()
-os.chdir('./html_files')
+os.chdir('./www')
for(dirpath, dirnames, filenames) in os.walk('.'):
- files += [os.path.join(dirpath, file) for file in filenames]
+ files += [os.path.join(dirpath, file) for file in filenames]
filenames = list()
varnames = list()
@@ -22,85 +22,87 @@ varnames = list()
#Generate appropriate HTTP headers
for file in files:
- if '404' in file:
- header = "HTTP/1.0 404 File not found\r\n"
- else:
- header = "HTTP/1.0 200 OK\r\n"
+ if '404' in file:
+ header = "HTTP/1.0 404 File not found\r\n"
+ else:
+ header = "HTTP/1.0 200 OK\r\n"
- header += "Server: lwIP/pre-0.6 (http://www.sics.se/~adam/lwip/)\r\n"
+ header += "Server: lwIP/pre-0.6 (http://www.sics.se/~adam/lwip/)\r\n"
- if '.html' in file:
- header += "Content-type: text/html\r\n"
- elif '.shtml' in file:
- header += "Content-type: text/html\r\n"
- elif '.jpg' in file:
- header += "Content-type: image/jpeg\r\n"
- elif '.gif' in file:
- header += "Content-type: image/gif\r\n"
- elif '.png' in file:
- header += "Content-type: image/png\r\n"
- elif '.class' in file:
- header += "Content-type: application/octet-stream\r\n"
- elif '.js' in file:
- header += "Content-type: text/javascript\r\n"
- elif '.css' in file:
- header += "Content-type: text/css\r\n"
- elif '.svg' in file:
- header += "Content-type: image/svg+xml\r\n"
- else:
- header += "Content-type: text/plain\r\n"
+ if '.html' in file:
+ header += "Content-type: text/html\r\n"
+ elif '.shtml' in file:
+ header += "Content-type: text/html\r\n"
+ elif '.jpg' in file:
+ header += "Content-type: image/jpeg\r\n"
+ elif '.gif' in file:
+ header += "Content-type: image/gif\r\n"
+ elif '.png' in file:
+ header += "Content-type: image/png\r\n"
+ elif '.class' in file:
+ header += "Content-type: application/octet-stream\r\n"
+ elif '.js' in file:
+ header += "Content-type: text/javascript\r\n"
+ elif '.css' in file:
+ header += "Content-type: text/css\r\n"
+ elif '.svg' in file:
+ header += "Content-type: image/svg+xml\r\n"
+ elif ".ssi" in file:
+ header += "Content-type: application/json\r\n"
+ else:
+ header += "Content-type: text/plain\r\n"
- header += "\r\n"
+ header += "\r\n"
- fvar = file[1:] #remove leading dot in filename
- fvar = fvar.replace('/', '_') #replace *nix path separator with underscore
- fvar = fvar.replace('\\', '_') #replace DOS path separator with underscore
- fvar = fvar.replace('.', '_') #replace file extension dot with underscore
+ fvar = file[1:] #remove leading dot in filename
+ fvar = fvar.replace('/', '_') #replace *nix path separator with underscore
+ fvar = fvar.replace('\\', '_') #replace DOS path separator with underscore
+ fvar = fvar.replace('.', '_') #replace file extension dot with underscore
- output.write("static const unsigned char data{}[] = {{\n".format(fvar))
- output.write("\t/* {} */\n\t".format(file))
+ output.write("static const unsigned char data{}[] = {{\n".format(fvar))
+ output.write("\t/* {} */\n\t".format(file))
- #first set of hex data encodes the filename
- b = bytes(file[1:].replace('\\', '/'), 'utf-8') #change DOS path separator to forward slash
- for byte in binascii.hexlify(b, b' ', 1).split():
- output.write("0x{}, ".format(byte.decode()))
- output.write("0,\n\t")
+ #first set of hex data encodes the filename
+ b = bytes(file[1:].replace('\\', '/'), 'utf-8') #change DOS path separator to forward slash
+ for byte in binascii.hexlify(b, b' ', 1).split():
+ output.write("0x{}, ".format(byte.decode()))
+ output.write("0,\n\t")
- #second set of hex data is the HTTP header/mime type we generated above
- b = bytes(header, 'utf-8')
- count = 0
- for byte in binascii.hexlify(b, b' ', 1).split():
- output.write("0x{}, ".format(byte.decode()))
- count = count + 1
- if(count == 10):
- output.write("\n\t")
- count = 0
- output.write("\n\t")
+ #second set of hex data is the HTTP header/mime type we generated above
+ b = bytes(header, 'utf-8')
+ count = 0
+ for byte in binascii.hexlify(b, b' ', 1).split():
+ output.write("0x{}, ".format(byte.decode()))
+ count = count + 1
+ if(count == 10):
+ output.write("\n\t")
+ count = 0
+ output.write("\n\t")
- #finally, dump raw hex data from files
- with open(file, 'rb') as f:
- count = 0
- while(byte := f.read(1)):
- byte = binascii.hexlify(byte)
- output.write("0x{}, ".format(byte.decode()))
- count = count + 1
- if(count == 10):
- output.write("\n\t")
- count = 0
- output.write("};\n\n")
+ #finally, dump raw hex data from files
+ with open(file, 'rb') as f:
+ count = 0
+ while(byte := f.read(1)):
+ byte = binascii.hexlify(byte)
+ output.write("0x{}, ".format(byte.decode()))
+ count = count + 1
+ if(count == 10):
+ output.write("\n\t")
+ count = 0
+ output.write("};\n\n")
- filenames.append(file[1:])
- varnames.append(fvar)
+ filenames.append(file[1:])
+ varnames.append(fvar)
for i in range(len(filenames)):
- prevfile = "NULL"
- if(i > 0):
- prevfile = "file" + varnames[i-1]
+ prevfile = "NULL"
+ if(i > 0):
+ prevfile = "file" + varnames[i-1]
- output.write("const struct fsdata_file file{0}[] = {{{{ {1}, data{2}, ".format(varnames[i], prevfile, varnames[i]))
- output.write("data{} + {}, ".format(varnames[i], len(filenames[i]) + 1))
- output.write("sizeof(data{}) - {}, ".format(varnames[i], len(filenames[i]) + 1))
- output.write("FS_FILE_FLAGS_HEADER_INCLUDED | FS_FILE_FLAGS_HEADER_PERSISTENT}};\n")
+ output.write("const struct fsdata_file file{0}[] = {{{{ {1}, data{2}, ".format(varnames[i], prevfile, varnames[i]))
+ output.write("data{} + {}, ".format(varnames[i], len(filenames[i]) + 1))
+ output.write("sizeof(data{}) - {}, ".format(varnames[i], len(filenames[i]) + 1))
+ output.write("FS_FILE_FLAGS_HEADER_INCLUDED | FS_FILE_FLAGS_HEADER_PERSISTENT}};\n")
output.write("\n#define FS_ROOT file{}\n".format(varnames[-1]))
output.write("#define FS_NUMFILES {}\n".format(len(filenames)))
\ No newline at end of file
diff --git a/ssi.h b/ssi.h
index 9d9b472..0af385d 100644
--- a/ssi.h
+++ b/ssi.h
@@ -1,51 +1,49 @@
+#ifndef SSI_H
+#define SSI_H
+
#include "lwip/apps/httpd.h"
#include "pico/cyw43_arch.h"
#include "hardware/adc.h"
+#include "handlers.h"
-// SSI tags - tag length limited to 8 bytes by default
-const char * ssi_tags[] = {"volt","temp","led"};
+const char * ssi_tags[] = {"volt", "temp", "power"};
u16_t ssi_handler(int iIndex, char *pcInsert, int iInsertLen) {
size_t printed;
switch (iIndex) {
case 0: // volt
{
- const float voltage = adc_read() * 3.3f / (1 << 12);
- printed = snprintf(pcInsert, iInsertLen, "%f", voltage);
+ const float voltage = adc_read() * 3.3f / (1 << 12);
+ printed = snprintf(pcInsert, iInsertLen, "%f", voltage);
}
break;
case 1: // temp
{
- const float voltage = adc_read() * 3.3f / (1 << 12);
- const float tempC = 27.0f - (voltage - 0.706f) / 0.001721f;
- printed = snprintf(pcInsert, iInsertLen, "%f", tempC);
+ const float voltage = adc_read() * 3.3f / (1 << 12);
+ const float tempC = 27.0f - (voltage - 0.706f) / 0.001721f;
+ printed = snprintf(pcInsert, iInsertLen, "%f", tempC);
}
break;
- case 2: // led
+ case 2: // power
{
- bool led_status = cyw43_arch_gpio_get(CYW43_WL_GPIO_LED_PIN);
- if(led_status == true){
- printed = snprintf(pcInsert, iInsertLen, "ON");
- }
- else{
- printed = snprintf(pcInsert, iInsertLen, "OFF");
- }
+ printed = snprintf(pcInsert, iInsertLen, "%d", current_state);
}
break;
default:
- printed = 0;
+ {
+ printed = 0;
+ }
break;
}
- return (u16_t)printed;
+ return (u16_t) printed;
}
-// Initialise the SSI handler
void ssi_init() {
- // Initialise ADC (internal pin)
adc_init();
adc_set_temp_sensor_enabled(true);
adc_select_input(4);
-
http_set_ssi_handler(ssi_handler, ssi_tags, LWIP_ARRAYSIZE(ssi_tags));
-}
\ No newline at end of file
+}
+
+#endif
\ No newline at end of file
diff --git a/www/power.ssi b/www/power.ssi
new file mode 100644
index 0000000..9e26dfe
--- /dev/null
+++ b/www/power.ssi
@@ -0,0 +1 @@
+{}
\ No newline at end of file
diff --git a/www/status.ssi b/www/status.ssi
new file mode 100644
index 0000000..aa05888
--- /dev/null
+++ b/www/status.ssi
@@ -0,0 +1,5 @@
+{
+ "volt": ,
+ "temp": ,
+ "power":
+}
\ No newline at end of file