77 |
78 | Current WiFi mode: %WiFiMode%
79 |
80 |
81 | Note: %WiFiapwarn%
82 |
83 |
93 |
94 |
95 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # esp-httpd README #
2 |
3 | This is the demonstration project for the small but powerful libesphttpd webserver
4 | for ESP8266(EX) chips. It is an example of how to make a module that can have
5 | the AP it connects to configured over a webbrowser. It also illustrates multiple
6 | flash layouts and some OTA update functionality.
7 |
8 | ## ABOUT THE WEBSERVER ##
9 |
10 | The Good (aka: what's awesome)
11 | - Supports multiple connections, for eg simultaneous html/css/js/images downloading
12 | - Static files stored in flash, in an (optionally compressed) RO filesystem
13 | - Pluggable using external cgi routines
14 | - Simple template engine for mixed c and html things
15 | - Usable as an embedded library - should be easy to drop into your existing projects
16 | - Includes websocket support
17 |
18 | The Bad (aka: what can be improved)
19 | - Not built for speediness, although it's reasonable fast.
20 | - Built according to what I remember of the HTTP protocol, not according to the
21 | RFCs. Should work with most modern browsers, though.
22 | - No support for https.
23 |
24 | The Ugly (aka: bugs, misbehaviour)
25 | - Possible buffer overflows (usually not remotely exploitable) due to no os_snprintf
26 | This can be theoretically remedied by either Espressif including an os_snprintf in
27 | their libs or by using some alternate printf lib, like elm-chans xprintf
28 |
29 | ## SOURCE OF THIS CODE ##
30 | The official esphttpd repo lives at http://git.spritesserver.nl/esphttpd.git/ and
31 | http://git.spritesserver.nl/libesphttpd.git/ . If you're a fan of Github, you can also
32 | peruse the official mirror at https://github.com/Spritetm/esphttpd and https://github.com/Spritetm/libesphttpd . If
33 | you want to discuss this code, there is a subforum at esp8266.com: http://www.esp8266.com/viewforum.php?f=34 .
34 |
35 |
36 | ## ABOUT THE EXAMPLE ##
37 |
38 | When you flash the example into an ESP8266(EX) module, you get a small webserver with a few example
39 | pages. If you've already connected your module to your WLAN before, it'll keep those settings. When
40 | you haven't or the settings are wrong, keep GPIO0 for >5 seconds. The module will reboot into
41 | its STA+AP mode. Connect a computer to the newly formed access point and browse to
42 | http://192.168.4.1/wifi in order to connect the module to your WiFi network. The example also
43 | allows you to control a LED that's connected to GPIO2.
44 |
45 | ## BUILDING EVERYTHING ##
46 |
47 | For this, you need an environment that can compile ESP8266 firmware. Environments for this still
48 | are in flux at the moment, but I'm using esp-open-sdk: https://github.com/pfalcon/esp-open-sdk .
49 | You probably also need an UNIX-like system; I'm working on Debian Linux myself.
50 |
51 | To manage the paths to all this, you can source a small shell fragment into your current session. For
52 | example, I source a file with these contents:
53 |
54 | export PATH=${PWD}/esp-open-sdk/xtensa-lx106-elf/bin:$PATH
55 | export SDK_BASE=${PWD}/esp-open-sdk/sdk
56 | export ESPTOOL=${PWD}/esptool/esptool.py
57 | export ESPPORT=/dev/ttyUSB0
58 | export ESPBAUD=460800
59 |
60 | Actual setup of the SDK and toolchain is out of the scope of this document, so I hope this helps you
61 | enough to set up your own if you haven't already.
62 |
63 | If you have that, you can clone out the source code:
64 | git clone http://git.spritesserver.nl/esphttpd.git/
65 |
66 | This project makes use of heatshrink, which is a git submodule. To fetch the code:
67 |
68 | cd esphttpd
69 | git submodule init
70 | git submodule update
71 |
72 | Now, build the code:
73 |
74 | make
75 |
76 | Depending on the way you built it, esp-open-sdk sometimes patches Espressifs SDK, needing a slightly different
77 | compiling process. If this is needed, you will get errors during compiling complaining about uint8_t being
78 | undeclared. If this happens, try building like this:
79 |
80 | make USE_OPENSDK=yes
81 |
82 | You can also edit the Makefile to change this more permanently.
83 |
84 | After the compile process, flash the code happens in 2 steps. First the code itself gets flashed. Reset the module into bootloader
85 | mode and enter 'make flash'.
86 |
87 | The 2nd step is to pack the static files the webserver will serve and flash that. Reset the module into
88 | bootloader mode again and enter `make htmlflash`.
89 |
90 | You should have a working webserver now.
91 |
92 | ## WRITING CODE FOR THE WEBSERVER ##
93 |
94 | Please see the README.md of the libesphttpd project for the programming manual.
95 |
96 |
97 |
--------------------------------------------------------------------------------
/Makefile.ota:
--------------------------------------------------------------------------------
1 | #Makefile with the options specific to the build of a non-upgradable firmware with
2 | #the espfs combined into the flash binary.
3 |
4 | # Change tagname to some identifier that's unique for your project. 27 chars max.
5 | TAGNAME ?= "generic"
6 |
7 | # linker script used for the linker step
8 |
9 | LD_MAP_1:=512:eagle.app.v6.new.512.app1.ld 1024:eagle.app.v6.new.1024.app1.ld 2048:eagle.app.v6.new.2048.ld 4096:eagle.app.v6.new.2048.ld
10 | LD_MAP_2:=512:eagle.app.v6.new.512.app2.ld 1024:eagle.app.v6.new.1024.app2.ld 2048:eagle.app.v6.new.2048.ld 4096:eagle.app.v6.new.2048.ld
11 | LD_SCRIPT_USR1 := $(call maplookup,$(ESP_SPI_FLASH_SIZE_K),$(LD_MAP_1))
12 | LD_SCRIPT_USR2 := $(call maplookup,$(ESP_SPI_FLASH_SIZE_K),$(LD_MAP_2))
13 |
14 | TARGET_OUT_USR1 := $(addprefix $(BUILD_BASE)/,$(TARGET).user1.out)
15 | TARGET_OUT_USR2 := $(addprefix $(BUILD_BASE)/,$(TARGET).user2.out)
16 | TARGET_OUT := $(TARGET_OUT_USR1) $(TARGET_OUT_USR2)
17 |
18 | TARGET_BIN_USR1 := $(addprefix $(BUILD_BASE)/,$(TARGET).user1.bin)
19 | TARGET_BIN_USR2 := $(addprefix $(BUILD_BASE)/,$(TARGET).user2.bin)
20 | TARGET_BIN := $(TARGET_BIN_USR1) $(TARGET_BIN_USR2)
21 | TARGET_OTAFILE := $(addprefix $(BUILD_BASE)/,$(TARGET).ota)
22 |
23 |
24 | BLANKPOS="$$(printf "0x%X" $$(($(ESP_SPI_FLASH_SIZE_K)*512-0x2000)))"
25 | INITDATAPOS="$$(printf "0x%X" $$(($(ESP_SPI_FLASH_SIZE_K)*512-0x4000)))"
26 |
27 | #Convert SPI size into arg for appgen. Format: no=size
28 | FLASH_MAP_CONV:=0:512 2:1024 5:2048 6:4096
29 | ESP_FLASH_SIZE_IX:=$(maplookup $(ESP_SPI_FLASH_SIZE_K),,$(FLASH_MAP_CONV))
30 |
31 | CFLAGS += -DOTA_TAGNAME=\"$(TAGNAME)\"
32 |
33 | define genappbin
34 | $(1): $$(APP_AR)
35 | $$(vecho) LD $$@
36 | $$(Q) $$(LD) -Llibesphttpd -L$$(SDK_LIBDIR) $(2) $$(LDFLAGS) -Wl,--start-group $$(LIBS) $$(APP_AR) -Wl,--end-group -o $$@
37 |
38 | $(3): $(1)
39 | $$(vecho) APPGEN $$@
40 | $$(Q) $$(OBJCOPY) --only-section .text -O binary $1 build/eagle.app.v6.text.bin
41 | $$(Q) $$(OBJCOPY) --only-section .data -O binary $1 build/eagle.app.v6.data.bin
42 | $$(Q) $$(OBJCOPY) --only-section .rodata -O binary $1 build/eagle.app.v6.rodata.bin
43 | $$(Q) $$(OBJCOPY) --only-section .irom0.text -O binary $1 build/eagle.app.v6.irom0text.bin
44 | $$(Q) cd build; COMPILE=gcc PATH=$$(XTENSA_TOOLS_ROOT):$$(PATH) python $$(APPGEN) $(1:build/%=%) 2 $$(ESP_FLASH_MODE) $$(ESP_FLASH_FREQ_DIV) $$(ESP_FLASH_SIZE_IX) $(4)
45 | $$(Q) rm -f eagle.app.v6.*.bin
46 | $$(Q) mv build/eagle.app.flash.bin $$@
47 | @echo "** user1.bin uses $$$$(stat -c '%s' $$@) bytes of" $$(ESP_FLASH_MAX) "available"
48 | endef
49 |
50 | $(eval $(call genappbin,$(TARGET_OUT_USR1),$$(LD_SCRIPT_USR1),$$(TARGET_BIN_USR1),1))
51 | $(eval $(call genappbin,$(TARGET_OUT_USR2),$$(LD_SCRIPT_USR2),$$(TARGET_BIN_USR2),2))
52 |
53 | .PHONY: ldscript_memspecific.ld
54 |
55 | ldscript_memspecific.ld:
56 | $(vecho) "GEN $@"
57 | $(Q) echo "MEMORY { irom0_0_seg : org = 0x40240000, len = "$$(printf "0x%X" $$(($(ESP_SPI_FLASH_SIZE_K)*1024-0x4000)))" }"> ldscript_memspecific.ld
58 |
59 |
60 | #define makeuser
61 | #$1: $(APP_AR)
62 | # $(vecho) "LD $@"
63 | # $(Q) $(LD) -Llibesphttpd -L$(SDK_LIBDIR) $(LD_SCRIPT) $(EXTRA_LD_SCRIPTS) $(LDFLAGS) -Wl,--start-group $(LIBS) $(APP_AR) -Wl,--end-group -o $@
64 | # $(Q) $(OBJCP) --only-section .text -O binary $2 build/eagle.app.v6.text.bin
65 | # $(Q) $(OBJCP) --only-section .data -O binary $2 build/eagle.app.v6.data.bin
66 | # $(Q) $(OBJCP) --only-section .rodata -O binary $2 build/eagle.app.v6.rodata.bin
67 | # $(Q) $(OBJCP) --only-section .irom0.text -O binary $2 build/eagle.app.v6.irom0text.bin
68 | # ls -ls build/eagle*bin
69 | # $(Q) COMPILE=gcc PATH=$(XTENSA_TOOLS_ROOT):$(PATH) python $(APPGEN_TOOL) $(USER1_OUT) 2 $(ESP_FLASH_MODE) $(ESP_FLASH_FREQ_DIV) $(ESP_SPI_SIZE)
70 | # $(Q) rm -f eagle.app.v6.*.bin
71 | # $(Q) mv eagle.app.flash.bin $@
72 | # @echo "** user1.bin uses $$(stat -c '%s' $@) bytes of" $(ESP_FLASH_MAX) "available"
73 | # $(Q) if [ $$(stat -c '%s' $@) -gt $$(( $(ESP_FLASH_MAX) )) ]; then echo "$@ too big!"; false; fi
74 | #endef
75 |
76 |
77 | #user1.bin:
78 | # $(call makeuser,user1.bin,1)
79 |
80 | libesphttpd/mkupgimg/mkupgimg: libesphttpd/mkupgimg/
81 | make -C libesphttpd/mkupgimg/
82 |
83 | $(FW_BASE): $(TARGET_BIN) libesphttpd/mkupgimg/mkupgimg
84 | $(Q) libesphttpd/mkupgimg/mkupgimg $(TARGET_BIN_USR1) $(TARGET_BIN_USR2) $(TAGNAME) $(TARGET_OTAFILE)
85 |
86 | flash: $(TARGET_OUT) $(FW_BASE)
87 | $(Q) $(ESPTOOL) $(ESPTOOL_OPTS) write_flash $(ESPTOOL_FLASHDEF) 0x00000 "$(SDK_BASE)/bin/boot_v1.7.bin" 0x1000 $(TARGET_BIN_USR1)
88 |
89 | blankflash:
90 | $(Q) $(ESPTOOL) $(ESPTOOL_OPTS) write_flash $(ESPTOOL_FLASHDEF) $(BLANKPOS) $(SDK_BASE)/bin/blank.bin $(INITDATAPOS) $(SDK_BASE)/bin/esp_init_data_default.bin
91 |
92 | httpflash: $(FW_BASE)
93 | $(Q) curl -X POST --data-binary '@build/httpd.ota' $(ESPIP)/flash/upload > /dev/null
94 | $(Q) curl $(ESPIP)/flash/reboot
95 | $(Q) echo -e '\nDone'
96 |
97 |
--------------------------------------------------------------------------------
/include/uart_hw.h:
--------------------------------------------------------------------------------
1 | //Generated at 2012-07-03 18:44:06
2 | /*
3 | * Copyright (c) 2010 - 2011 Espressif System
4 | *
5 | */
6 |
7 | #ifndef UART_REGISTER_H_INCLUDED
8 | #define UART_REGISTER_H_INCLUDED
9 | #define REG_UART_BASE( i ) (0x60000000+(i)*0xf00)
10 | //version value:32'h062000
11 |
12 | #define UART_FIFO( i ) (REG_UART_BASE( i ) + 0x0)
13 | #define UART_RXFIFO_RD_BYTE 0x000000FF
14 | #define UART_RXFIFO_RD_BYTE_S 0
15 |
16 | #define UART_INT_RAW( i ) (REG_UART_BASE( i ) + 0x4)
17 | #define UART_RXFIFO_TOUT_INT_RAW (BIT(8))
18 | #define UART_BRK_DET_INT_RAW (BIT(7))
19 | #define UART_CTS_CHG_INT_RAW (BIT(6))
20 | #define UART_DSR_CHG_INT_RAW (BIT(5))
21 | #define UART_RXFIFO_OVF_INT_RAW (BIT(4))
22 | #define UART_FRM_ERR_INT_RAW (BIT(3))
23 | #define UART_PARITY_ERR_INT_RAW (BIT(2))
24 | #define UART_TXFIFO_EMPTY_INT_RAW (BIT(1))
25 | #define UART_RXFIFO_FULL_INT_RAW (BIT(0))
26 |
27 | #define UART_INT_ST( i ) (REG_UART_BASE( i ) + 0x8)
28 | #define UART_RXFIFO_TOUT_INT_ST (BIT(8))
29 | #define UART_BRK_DET_INT_ST (BIT(7))
30 | #define UART_CTS_CHG_INT_ST (BIT(6))
31 | #define UART_DSR_CHG_INT_ST (BIT(5))
32 | #define UART_RXFIFO_OVF_INT_ST (BIT(4))
33 | #define UART_FRM_ERR_INT_ST (BIT(3))
34 | #define UART_PARITY_ERR_INT_ST (BIT(2))
35 | #define UART_TXFIFO_EMPTY_INT_ST (BIT(1))
36 | #define UART_RXFIFO_FULL_INT_ST (BIT(0))
37 |
38 | #define UART_INT_ENA( i ) (REG_UART_BASE( i ) + 0xC)
39 | #define UART_RXFIFO_TOUT_INT_ENA (BIT(8))
40 | #define UART_BRK_DET_INT_ENA (BIT(7))
41 | #define UART_CTS_CHG_INT_ENA (BIT(6))
42 | #define UART_DSR_CHG_INT_ENA (BIT(5))
43 | #define UART_RXFIFO_OVF_INT_ENA (BIT(4))
44 | #define UART_FRM_ERR_INT_ENA (BIT(3))
45 | #define UART_PARITY_ERR_INT_ENA (BIT(2))
46 | #define UART_TXFIFO_EMPTY_INT_ENA (BIT(1))
47 | #define UART_RXFIFO_FULL_INT_ENA (BIT(0))
48 |
49 | #define UART_INT_CLR( i ) (REG_UART_BASE( i ) + 0x10)
50 | #define UART_RXFIFO_TOUT_INT_CLR (BIT(8))
51 | #define UART_BRK_DET_INT_CLR (BIT(7))
52 | #define UART_CTS_CHG_INT_CLR (BIT(6))
53 | #define UART_DSR_CHG_INT_CLR (BIT(5))
54 | #define UART_RXFIFO_OVF_INT_CLR (BIT(4))
55 | #define UART_FRM_ERR_INT_CLR (BIT(3))
56 | #define UART_PARITY_ERR_INT_CLR (BIT(2))
57 | #define UART_TXFIFO_EMPTY_INT_CLR (BIT(1))
58 | #define UART_RXFIFO_FULL_INT_CLR (BIT(0))
59 |
60 | #define UART_CLKDIV( i ) (REG_UART_BASE( i ) + 0x14)
61 | #define UART_CLKDIV_CNT 0x000FFFFF
62 | #define UART_CLKDIV_S 0
63 |
64 | #define UART_AUTOBAUD( i ) (REG_UART_BASE( i ) + 0x18)
65 | #define UART_GLITCH_FILT 0x000000FF
66 | #define UART_GLITCH_FILT_S 8
67 | #define UART_AUTOBAUD_EN (BIT(0))
68 |
69 | #define UART_STATUS( i ) (REG_UART_BASE( i ) + 0x1C)
70 | #define UART_TXD (BIT(31))
71 | #define UART_RTSN (BIT(30))
72 | #define UART_DTRN (BIT(29))
73 | #define UART_TXFIFO_CNT 0x000000FF
74 | #define UART_TXFIFO_CNT_S 16
75 | #define UART_RXD (BIT(15))
76 | #define UART_CTSN (BIT(14))
77 | #define UART_DSRN (BIT(13))
78 | #define UART_RXFIFO_CNT 0x000000FF
79 | #define UART_RXFIFO_CNT_S 0
80 |
81 | #define UART_CONF0( i ) (REG_UART_BASE( i ) + 0x20)
82 | #define UART_TXFIFO_RST (BIT(18))
83 | #define UART_RXFIFO_RST (BIT(17))
84 | #define UART_IRDA_EN (BIT(16))
85 | #define UART_TX_FLOW_EN (BIT(15))
86 | #define UART_LOOPBACK (BIT(14))
87 | #define UART_IRDA_RX_INV (BIT(13))
88 | #define UART_IRDA_TX_INV (BIT(12))
89 | #define UART_IRDA_WCTL (BIT(11))
90 | #define UART_IRDA_TX_EN (BIT(10))
91 | #define UART_IRDA_DPLX (BIT(9))
92 | #define UART_TXD_BRK (BIT(8))
93 | #define UART_SW_DTR (BIT(7))
94 | #define UART_SW_RTS (BIT(6))
95 | #define UART_STOP_BIT_NUM 0x00000003
96 | #define UART_STOP_BIT_NUM_S 4
97 | #define UART_BIT_NUM 0x00000003
98 | #define UART_BIT_NUM_S 2
99 | #define UART_PARITY_EN (BIT(1))
100 | #define UART_PARITY (BIT(0))
101 |
102 | #define UART_CONF1( i ) (REG_UART_BASE( i ) + 0x24)
103 | #define UART_RX_TOUT_EN (BIT(31))
104 | #define UART_RX_TOUT_THRHD 0x0000007F
105 | #define UART_RX_TOUT_THRHD_S 24
106 | #define UART_RX_FLOW_EN (BIT(23))
107 | #define UART_RX_FLOW_THRHD 0x0000007F
108 | #define UART_RX_FLOW_THRHD_S 16
109 | #define UART_TXFIFO_EMPTY_THRHD 0x0000007F
110 | #define UART_TXFIFO_EMPTY_THRHD_S 8
111 | #define UART_RXFIFO_FULL_THRHD 0x0000007F
112 | #define UART_RXFIFO_FULL_THRHD_S 0
113 |
114 | #define UART_LOWPULSE( i ) (REG_UART_BASE( i ) + 0x28)
115 | #define UART_LOWPULSE_MIN_CNT 0x000FFFFF
116 | #define UART_LOWPULSE_MIN_CNT_S 0
117 |
118 | #define UART_HIGHPULSE( i ) (REG_UART_BASE( i ) + 0x2C)
119 | #define UART_HIGHPULSE_MIN_CNT 0x000FFFFF
120 | #define UART_HIGHPULSE_MIN_CNT_S 0
121 |
122 | #define UART_PULSE_NUM( i ) (REG_UART_BASE( i ) + 0x30)
123 | #define UART_PULSE_NUM_CNT 0x0003FF
124 | #define UART_PULSE_NUM_CNT_S 0
125 |
126 | #define UART_DATE( i ) (REG_UART_BASE( i ) + 0x78)
127 | #define UART_ID( i ) (REG_UART_BASE( i ) + 0x7C)
128 | #endif // UART_REGISTER_H_INCLUDED
129 |
130 | #define RX_BUFF_SIZE 256
131 | #define TX_BUFF_SIZE 100
132 | #define UART0 0
133 | #define UART1 1
134 |
135 | typedef enum {
136 | FIVE_BITS = 0x0,
137 | SIX_BITS = 0x1,
138 | SEVEN_BITS = 0x2,
139 | EIGHT_BITS = 0x3
140 | } UartBitsNum4Char;
141 |
142 | typedef enum {
143 | ONE_STOP_BIT = 0,
144 | ONE_HALF_STOP_BIT = BIT2,
145 | TWO_STOP_BIT = BIT2
146 | } UartStopBitsNum;
147 |
148 | typedef enum {
149 | NONE_BITS = 0,
150 | ODD_BITS = 0,
151 | EVEN_BITS = BIT4
152 | } UartParityMode;
153 |
154 | typedef enum {
155 | STICK_PARITY_DIS = 0,
156 | STICK_PARITY_EN = BIT3 | BIT5
157 | } UartExistParity;
158 |
159 | typedef enum {
160 | BIT_RATE_9600 = 9600,
161 | BIT_RATE_19200 = 19200,
162 | BIT_RATE_38400 = 38400,
163 | BIT_RATE_57600 = 57600,
164 | BIT_RATE_74880 = 74880,
165 | BIT_RATE_115200 = 115200,
166 | BIT_RATE_230400 = 230400,
167 | BIT_RATE_460800 = 460800,
168 | BIT_RATE_921600 = 921600
169 | } UartBautRate;
170 |
171 | typedef enum {
172 | NONE_CTRL,
173 | HARDWARE_CTRL,
174 | XON_XOFF_CTRL
175 | } UartFlowCtrl;
176 |
177 | typedef enum {
178 | EMPTY,
179 | UNDER_WRITE,
180 | WRITE_OVER
181 | } RcvMsgBuffState;
182 |
183 | typedef struct {
184 | uint32 TrxBuffSize;
185 | uint8 *pTrxBuff;
186 | } TrxMsgBuff;
187 |
188 | typedef enum {
189 | BAUD_RATE_DET,
190 | WAIT_SYNC_FRM,
191 | SRCH_MSG_HEAD,
192 | RCV_MSG_BODY,
193 | RCV_ESC_CHAR,
194 | } RcvMsgState;
195 |
196 |
--------------------------------------------------------------------------------
/html/test/test.js:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | Code to test the webserver. This depends on:
4 | - The cat images being available, for concurrent espfs testing
5 | - the test.cgi script available, for generic data mangling tests
6 |
7 |
8 | This test does a max of 4 requests in parallel. The nonos SDK supports a max of
9 | 5 connections; the default libesphttpd setting is 4 sockets at a time. Unfortunately,
10 | the nonos sdk just closes all sockets opened after the available sockets are opened,
11 | instead of queueing them until a socket frees up.
12 | */
13 |
14 |
15 | function log(line) {
16 | $("#log").insertAdjacentHTML('beforeend', line+'