├── Makefile ├── README.md ├── alan_todo.txt ├── board ├── esp8266_relay_board.brd ├── esp8266_relay_board.sch ├── esp8266_relay_board_brd.png └── esp8266_relay_board_sch.png ├── burn_all.sh ├── burn_boot.sh ├── burn_webpages.sh ├── espSDKFirmware ├── blank.bin └── esp_init_data_default.bin ├── firmware ├── user1.bin ├── user2.bin └── webpages.espfs ├── html ├── about.tpl ├── config │ ├── broadcastd.tpl │ ├── httpd.tpl │ ├── mqtt.tpl │ ├── ntp.tpl │ ├── relay.tpl │ ├── sensor.tpl │ ├── thermostat.tpl │ └── wifi │ │ ├── 140medley.min.js │ │ ├── connecting.html │ │ ├── icons.png │ │ ├── style.css │ │ └── wifi.tpl ├── control │ ├── dht22.tpl │ ├── ds18b20.tpl │ ├── pwm.html │ ├── relay.html │ ├── relay.tpl │ ├── restarting.html │ ├── style.big.css │ ├── style.css │ ├── thermostat.html │ ├── thingspeak.html │ ├── ui.css │ └── ui.tpl ├── favicon.ico ├── index.tpl ├── js │ ├── flash.js │ ├── jquery-1.9.0.min.js │ ├── relay.js │ ├── thermostat.js │ ├── thingspeak.js │ ├── ui.js │ └── ui_tpl.js └── style.css ├── include ├── README ├── arch │ ├── cc.h │ ├── perf.h │ └── sys_arch.h ├── auth.h ├── base64.h ├── broadcastd.h ├── cgi.h ├── cgiflash.h ├── cgithermostat.h ├── cgiwifi.h ├── config.h ├── debug.h ├── dht22.h ├── driver │ ├── i2c.h │ ├── i2c_oled.h │ ├── i2c_oled_fonts.h │ ├── uart.h.bak │ └── uart_register.h.bak ├── ds18b20.h ├── esp8266.h ├── espfs.h ├── espmissingincludes-ip.h ├── espmissingincludes.h ├── heatshrink_config_httpd.h ├── httpclient.h ├── httpd.h ├── httpdconfig.h ├── httpdespfs.h ├── io.h ├── ip_addr.bak ├── jsmn.h ├── lwipopts.h ├── mem_manager.h ├── mqtt.h ├── mqtt_msg.h ├── mqueue.h ├── netbios.h ├── netif │ ├── etharp.h │ ├── if_llc.h │ ├── ppp_oe.h │ └── wlan_lwip_if.h ├── proto.h ├── pwm.h ├── ringbuf.h ├── sdkconfig.h ├── sntp.h.bak ├── stdint.h ├── stdint.h.bak ├── stdout.h ├── syslog.h ├── thermostat.h ├── time_utils.h ├── typedef.h ├── uart_hw.h ├── upgrade.h ├── user_config.h ├── user_interface.h.bak ├── utils.h └── wifi.h ├── lib ├── README └── heatshrink │ ├── .gitignore │ ├── .travis.yml │ ├── LICENSE │ ├── Makefile │ ├── README.md │ ├── dec_sm.dot │ ├── enc_sm.dot │ ├── greatest.h │ ├── heatshrink.c │ ├── heatshrink_common.h │ ├── heatshrink_config.h │ ├── heatshrink_decoder.c │ ├── heatshrink_decoder.h │ ├── heatshrink_encoder.c │ ├── heatshrink_encoder.h │ ├── test_heatshrink_dynamic.c │ ├── test_heatshrink_dynamic_theft.c │ └── test_heatshrink_static.c.bak ├── mkespfsimage ├── Makefile ├── espfsformat.h ├── heatshrink_encoder.c ├── heatshrink_encoder.o ├── main.c ├── main.o └── mkespfsimage ├── platformio.ini ├── src └── user │ ├── auth.c │ ├── base64.c │ ├── broadcastd.c │ ├── cgi.c │ ├── cgiflash.c │ ├── cgithermostat.c │ ├── cgiwifi.c │ ├── config.c │ ├── dht22.c │ ├── ds18b20.c │ ├── espfs.c │ ├── heatshrink_decoder.c │ ├── httpclient.c │ ├── httpd.c │ ├── httpdespfs.c │ ├── io.c │ ├── jsmn.c │ ├── mqtt.c │ ├── mqtt_msg.c │ ├── mqueue.c │ ├── netbios.c │ ├── proto.c │ ├── ringbuf.c │ ├── sntp.c.bak │ ├── stdout.c │ ├── syslog.c │ ├── thermostat.c │ ├── time_utils.c │ ├── user_main.c │ ├── utils.c │ └── wifi.c ├── upload_schedule.sh └── wiflash /alan_todo.txt: -------------------------------------------------------------------------------- 1 | ToDo 2 | 3 | 4 | Configurable GPIO for relays (via webpage?) 5 | 6 | 7 | Done 8 | Avoid thermostat cycling - timestamp relay activations and set limit 9 | (possibly make dedicated function for relay on/off with TS and check on the ON.. should always be able to turn it off) 10 | 11 | Config items for MQTT timeout & thermostat cycling 12 | 13 | Display of a bad or stale temperature should update on thermostat.html page and not keep last reading 14 | 15 | Fix bug where thermostat off time is update is it is already off 16 | 17 | Change thermostat to work in tenths of a degree, not hundredths 18 | 19 | Remove used references to thermostat2 & thermostat3 (commented as may use in future version) 20 | 21 | Publish state to MQTT - thermostat (on/off, mode)+ relays 22 | 23 | Publish all ds18b20 sensors to MQTT by device-id 24 | 25 | Choose which relays associate to each thermostat 26 | 27 | FOTA upgrade now down via webpage push (about.tpl) - thank you #esp-link project 28 | 29 | Thermostat timeout for all sources implemented 30 | 31 | Move all thermostat config to its own page in the Web GUI 32 | 33 | ESPFS webpage upload now available through the Web GUI 34 | 35 | Tidy up about.tpl page and only show firmware upgrade options when flash_map > 2 (over 512Kb) 36 | Disable URLs for flashing firmware if flash_map < 2 37 | 38 | Supports DST for Europe and North America (thanks Martin Harizanov for the code template) 39 | 40 | Correct relay active for thermostat indicated in MQTT and JSON feeds (instead of relay1 default). 41 | 42 | CurrentSetPoint published in state JSONs 43 | 44 | Number of relays is now configurable via UI - if relay is not configured, it cannot be actuated via any means. 45 | Means code should work on 1-Relay boards and have correct UI and logic 46 | 47 | Relays configured as thermostat controlled cannot be actuated via any other means (webpages, IO calls, MQTT) 48 | 49 | Main menu updated 50 | 51 | UI overview page completed to show most things and available on main menu (need to do ds18B20 sensors) 52 | 53 | Thermostat colour map gradients configurable from web UI 54 | 55 | Display all DS18B20 & DHT22 sensor values on new UI overview page 56 | 57 | Tidy up serial interface - add help and validation of inputs 58 | 59 | Add serial userjson input - JSON can be submitted via serial and is published to MQTT and thermostat.cgi?state to allow easy customisation of webpages to support random serial devices 60 | 61 | Added schedule override mode 62 | 63 | user_params parameter added to main CGI to return them as JSON 64 | publish them to MQTT ? 65 | 66 | 67 | Added syslog server 68 | 69 | Made thermostat name configurable and page title to be thermostat name 70 | 71 | Made thermostat schedule downloadable 72 | 73 | Added thermostat manual/auto mode to ui.tpl 74 | 75 | Add timeout for userJSON MQTT publication (timestamp the serial input) 76 | -------------------------------------------------------------------------------- /board/esp8266_relay_board_brd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mharizanov/ESP8266_Relay_Board/bb58eb2f41fc9a136600907f62672e4673c06658/board/esp8266_relay_board_brd.png -------------------------------------------------------------------------------- /board/esp8266_relay_board_sch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mharizanov/ESP8266_Relay_Board/bb58eb2f41fc9a136600907f62672e4673c06658/board/esp8266_relay_board_sch.png -------------------------------------------------------------------------------- /burn_all.sh: -------------------------------------------------------------------------------- 1 | echo "Buring all code to ESP8266 relay board." 2 | echo "Move switch to PGM and hit the reset button" 3 | read -p "Press enter to continue" 4 | 5 | PORT=/dev/cu.usbserial-FTVB6JWH1 6 | ESPTOOL="$HOME/.platformio/packages/tool-esptoolpy/esptool.py" 7 | 8 | "$HOME/.platformio/penv/bin/python" $ESPTOOL --before no_reset --after soft_reset --chip esp8266 --port "$PORT" --baud 115200 write_flash 0x10000 ./firmware/0x10000.bin 0x7c000 ./espSDKFirmware/esp_init_data_default.bin 0x7e000 ./espSDKFirmware/blank.bin 0x0 ./firmware/0x00000.bin 9 | 10 | echo "Done. Check above for errors" 11 | sleep 2 12 | ./burn_webpages.sh 13 | 14 | -------------------------------------------------------------------------------- /burn_boot.sh: -------------------------------------------------------------------------------- 1 | echo "Buring all code to ESP8266 relay board." 2 | echo "Move switch to PGM and hit the reset button" 3 | read -p "Press enter to continue" 4 | 5 | PORT=/dev/cu.usbserial-FTVB6JWH1 6 | #ESPTOOL="$HOME/.platformio/packages/tool-esptoolpy/esptool.py" 7 | ESPTOOL="$HOME/esptool/esptool.py" 8 | 9 | SDK_BASE=$HOME/esp/ESP8266_NONOS_SDK 10 | 11 | #"$HOME/.platformio/penv/bin/python" $ESPTOOL --before no_reset --after soft_reset --chip esp8266 --port "$PORT" --baud 115200 write_flash -fs 1MB 0x1000 ./firmware/user1.bin 0xfc000 $SDK_BASE/bin/esp_init_data_default_v08.bin 0xfe000 $SDK_BASE/bin/blank.bin 0x0 $SDK_BASE/bin/boot_v1.7.bin 12 | "$HOME/.platformio/penv/bin/python" $ESPTOOL --before no_reset --after soft_reset --chip esp8266 --port "$PORT" --baud 230400 write_flash -fs 1MB 0x1000 ./firmware/user1.bin 0xfc000 $SDK_BASE/bin/esp_init_data_default_v08.bin 0xfe000 $SDK_BASE/bin/blank.bin 0x0 $SDK_BASE/bin/boot_v1.7.bin 13 | 14 | echo "Done. Check above for errors" 15 | sleep 2 16 | ./burn_webpages.sh 17 | 18 | -------------------------------------------------------------------------------- /burn_webpages.sh: -------------------------------------------------------------------------------- 1 | PORT=/dev/cu.usbserial-FTVB6JWH1 2 | #ESPTOOL="$HOME/.platformio/packages/tool-esptoolpy/esptool.py" 3 | ESPTOOL="$HOME/esptool/esptool.py" 4 | echo "Compiling webpages into espfs file" 5 | rm webpages.espfs 6 | make webpages.espfs 7 | echo "Burning webpages to ESP8266 relay board" 8 | echo "Move switch to PGM and hit the reset button" 9 | read -p "Press enter to continue" 10 | python3 $ESPTOOL --port $PORT --baud 230400 write_flash 0x50000 ./firmware/webpages.espfs 11 | -------------------------------------------------------------------------------- /espSDKFirmware/blank.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mharizanov/ESP8266_Relay_Board/bb58eb2f41fc9a136600907f62672e4673c06658/espSDKFirmware/blank.bin -------------------------------------------------------------------------------- /espSDKFirmware/esp_init_data_default.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mharizanov/ESP8266_Relay_Board/bb58eb2f41fc9a136600907f62672e4673c06658/espSDKFirmware/esp_init_data_default.bin -------------------------------------------------------------------------------- /firmware/user1.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mharizanov/ESP8266_Relay_Board/bb58eb2f41fc9a136600907f62672e4673c06658/firmware/user1.bin -------------------------------------------------------------------------------- /firmware/user2.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mharizanov/ESP8266_Relay_Board/bb58eb2f41fc9a136600907f62672e4673c06658/firmware/user2.bin -------------------------------------------------------------------------------- /firmware/webpages.espfs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mharizanov/ESP8266_Relay_Board/bb58eb2f41fc9a136600907f62672e4673c06658/firmware/webpages.espfs -------------------------------------------------------------------------------- /html/about.tpl: -------------------------------------------------------------------------------- 1 | 2 | ESP8266 Relay/Thermostat board 3 | 4 | 5 | 6 | 7 |
8 |

About

9 |

10 | Three channel WiFi relay/thermostat board
11 | (c) Martin Harizanov 2014-2015 12 |

13 |

14 | Current firmware: 15 | Alan Pearson fork

16 |

%freeheap%

17 | 18 | 35 | 36 |

Upload New Webpage ESPFS

37 | 38 |
39 | 40 | 41 | 44 |
45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /html/config/broadcastd.tpl: -------------------------------------------------------------------------------- 1 | Broadcaset Daemon Settings 2 | 3 | 4 | 28 | 29 | 30 | 31 |
32 |

33 | Broadcast Daemon Settings 34 |

35 |
36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 |
HTTP GET broadcast enabled?:
Site:
Port:
URL:
ThingSpeak channel:
ThingSpeak RO API key:
46 |
47 | 48 | 49 | -------------------------------------------------------------------------------- /html/config/httpd.tpl: -------------------------------------------------------------------------------- 1 | HTTPD settings 2 | 3 | 4 | 25 | 26 | 27 | 28 |
29 |

30 | HTTPD Settings 31 |

32 |
33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 |
HTTPD Port:
HTTP Basic Auth enabled?:
User:
Password:
41 |
42 | 43 | 44 | -------------------------------------------------------------------------------- /html/config/mqtt.tpl: -------------------------------------------------------------------------------- 1 | MQTT settings 2 | 3 | 4 | 39 | 40 | 41 | 42 |
43 |

44 | MQTT Settings 45 |

46 |
47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 |
MQTT enabled?:
Host:
Port:
Keepalive (sec):
Device ID:
User:
Password:
Use SSL?: (max 1024 bit key size)
Relays subs topic:
Temp subs topic: 60 | If thermostat is configured to use MQTT as temperature source use this topic. 61 |
DHT22 temp pub topic:
DHT22 humi pub topic:
DS18B20 temp pub topic:
State pub topic: System state published to MQTT topic
Serial userJSON pub topic: JSON string received via serial interface published to MQTT topic. Must be refreshed more frequently than Keepalive secs above.
73 |
74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /html/config/ntp.tpl: -------------------------------------------------------------------------------- 1 | NTP settings 2 | 3 | 4 | 24 | 25 | 26 | 27 |
28 |

29 | NTP Settings 30 |

31 |
32 | 33 | 34 | 35 | 36 | 42 | 43 | 44 |
NTP client enabled?:
GMT offset:
DST Zone: 37 |
Restart system after changing to take effect
45 | 46 |
47 | 48 |

%NTP%

49 | 50 | -------------------------------------------------------------------------------- /html/config/relay.tpl: -------------------------------------------------------------------------------- 1 | Relay Settings 2 | 3 | 4 | 5 | 6 | 7 |
8 |

9 | Relay Settings 10 |

11 |
12 | 13 | 14 | 15 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 |
Number of relays 20 |
Relay latching enabled?:
46 |
47 | 48 | 49 |

50 |
51 | 52 | 53 | 54 | 55 | 69 | 70 | 71 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /html/config/sensor.tpl: -------------------------------------------------------------------------------- 1 | Sensor settings 2 | 3 | 4 | 5 | 6 | 7 |
8 |

9 | Sensor Settings 10 |

11 |
12 | 13 | 14 | 15 | 16 | 17 |
DS18B20 enabled?:
DHT22 enabled?:
18 |
19 | 20 | 21 |

22 |
23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /html/config/thermostat.tpl: -------------------------------------------------------------------------------- 1 | Thermostat settings 2 | 3 | 4 | 5 | 6 | 7 |
8 |

9 | Thermostat Settings 10 |

11 |
12 | 13 | 14 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 |
Thermostat input: 15 | 16 |
Zone Name:Thermostat Zone name for display purposes.
Thermostat hysteresis high: (in tenths of a degree, 5 means 0.5 degrees)
Thermostat hysteresis low: (in tenths of a degree, 5 means 0.5 degrees)
Room Temperature timeout secs: Timeout for thermostat room temperature reading. Configured sensor should provide readings every timeout seconds or thermostat turns off
Low temperature colour degrees Thermostat schedule display lowest temp starting point for colour gradient
High temperature colour degrees Thermostat schedule display lowest temp starting point for colour gradient
Thermostat Relay Rest Minutes:To avoid relay cycling, this the minimum OFF period - only applicable to relays configured for thermostat operation.
Syslog Enable:Enable syslog for thermostat events?
Syslog Host IP:Syslog server IP address for thermostat events.
52 |
53 | 54 | 55 |

56 |
57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /html/config/wifi/140medley.min.js: -------------------------------------------------------------------------------- 1 | var t=function(a,b){return function(c,d){return a.replace(/#{([^}]*)}/g,function(a,f){return Function("x","with(x)return "+f).call(c,d||b||{})})}},s=function(a,b){return b?{get:function(c){return a[c]&&b.parse(a[c])},set:function(c,d){a[c]=b.stringify(d)}}:{}}(this.localStorage||{},JSON),p=function(a,b,c,d){c=c||document;d=c[b="on"+b];a=c[b]=function(e){d=d&&d(e=e||c.event);return(a=a&&b(e))?b:d};c=this},m=function(a,b,c){b=document;c=b.createElement("p");c.innerHTML=a;for(a=b.createDocumentFragment();b= 2 | c.firstChild;)a.appendChild(b);return a},$=function(a,b){a=a.match(/^(\W)?(.*)/);return(b||document)["getElement"+(a[1]?a[1]=="#"?"ById":"sByClassName":"sByTagName")](a[2])},j=function(a){for(a=0;a<4;a++)try{return a?new ActiveXObject([,"Msxml2","Msxml3","Microsoft"][a]+".XMLHTTP"):new XMLHttpRequest}catch(b){}}; 3 | -------------------------------------------------------------------------------- /html/config/wifi/connecting.html: -------------------------------------------------------------------------------- 1 | 2 | Connecting 3 | 4 | 5 | 6 | 7 | Connecting to AP now... 8 | 9 | 10 | -------------------------------------------------------------------------------- /html/config/wifi/icons.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mharizanov/ESP8266_Relay_Board/bb58eb2f41fc9a136600907f62672e4673c06658/html/config/wifi/icons.png -------------------------------------------------------------------------------- /html/config/wifi/style.css: -------------------------------------------------------------------------------- 1 | 2 | body { 3 | background-color: #404040; 4 | font-family: sans-serif; 5 | } 6 | 7 | #main { 8 | background-color: #A7C0C0; 9 | -moz-border-radius: 5px; 10 | -webkit-border-radius: 5px; 11 | border-radius: 5px; 12 | border: 2px solid #000000; 13 | width: auto; 14 | margin: 0 auto; 15 | padding: 20px 16 | } 17 | 18 | .icon { 19 | background-image: url("icons.png"); 20 | background-color: transparent; 21 | width: 32px; 22 | height: 32px; 23 | display: inline-block; 24 | } -------------------------------------------------------------------------------- /html/config/wifi/wifi.tpl: -------------------------------------------------------------------------------- 1 | WiFi connection 2 | 3 | 4 | 5 | 88 | 89 | 90 |
91 |

92 | WiFi Settings 93 |

94 |

95 | Current WiFi mode: %WiFiMode% 96 |

97 |

98 | Note: %WiFiapwarn% 99 |

100 |
101 |

102 | To connect to a WiFi network, please select one of the detected networks...
103 |

Scanning...
104 |
105 | 106 |

107 | Current IP: %IPAddress% 108 |

109 | 110 | 111 | 112 | 120 | 121 | 122 | 123 |
WiFi password:
Mode: 113 | 114 | 118 | 119 |
IP address:
IP mask:
GW address:
124 |
125 | 126 | 127 |

128 |
129 | 130 | 131 | 132 | -------------------------------------------------------------------------------- /html/control/dht22.tpl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mharizanov/ESP8266_Relay_Board/bb58eb2f41fc9a136600907f62672e4673c06658/html/control/dht22.tpl -------------------------------------------------------------------------------- /html/control/ds18b20.tpl: -------------------------------------------------------------------------------- 1 | DS18b20 2 | 3 | 4 | 5 | 6 |
7 |

DS18B20 temperature sensor

8 |

9 | There are %numds% DS18B20s connected to GPIO2,
10 | %temperatures% 11 |

12 | 13 |
14 | 15 | -------------------------------------------------------------------------------- /html/control/pwm.html: -------------------------------------------------------------------------------- 1 | 2 | PWM control 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 |
15 |

PWM Control

16 |
17 |
18 |

Temperature set to °C

19 | 20 |
21 | 22 | 23 | 92 | 93 | 94 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /html/control/relay.html: -------------------------------------------------------------------------------- 1 | 2 | Relay control 3 | 4 | 5 | 6 | 7 | 8 |
9 |
10 |
11 |

Relay Control

12 |
13 | 14 | 15 | 16 | 21 | 26 | 31 |
32 | 33 | 34 | 35 | 43 | 44 | -------------------------------------------------------------------------------- /html/control/relay.tpl: -------------------------------------------------------------------------------- 1 | Relay control 2 | 3 | 4 | 5 | 6 |
7 |

Relay control page

8 |

9 | %relay1name% is now %relay1%. You can change that using the buttons below. 10 |

11 |
12 | 13 | 14 |
15 |

16 | %relay2name% is now %relay2%. You can change that using the buttons below. 17 |

18 |
19 | 20 | 21 |
22 |

23 | %relay3name% is now %relay3%. You can change that using the buttons below. 24 |

25 |
26 | 27 | 28 |
29 | 30 | 31 |
32 | 33 | -------------------------------------------------------------------------------- /html/control/restarting.html: -------------------------------------------------------------------------------- 1 | 2 | Restarting 3 | 4 | 5 | 6 | 7 | Restarting now... 8 | 9 | 10 | -------------------------------------------------------------------------------- /html/control/style.big.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family:"Ubuntu Light"; 3 | color:#333 4 | } 5 | 6 | .zone-title { 7 | font-size:42px 8 | } 9 | 10 | .zone-setpoint { 11 | font-size:62px 12 | } 13 | 14 | .block { 15 | margin: 0px auto; 16 | max-width:392px; 17 | padding:20px; 18 | margin-top:50px; 19 | box-shadow: 0px 1px 10px rgba(0, 0, 0, 0.1); 20 | text-align:left; 21 | } 22 | 23 | #toggle { 24 | font-size:22px; 25 | color:#fff; 26 | background-color:#555; 27 | border-radius: 12px; 28 | border:0; 29 | padding:10px; 30 | cursor:pointer; 31 | text-decoration:none; 32 | } 33 | 34 | #relay1 { 35 | font-size:22px; 36 | color:#fff; 37 | background-color:#555; 38 | border-radius: 12px; 39 | border:0; 40 | padding:10px; 41 | cursor:pointer; 42 | text-decoration:none; 43 | } 44 | #relay2 { 45 | font-size:22px; 46 | color:#fff; 47 | background-color:#555; 48 | border-radius: 12px; 49 | border:0; 50 | padding:10px; 51 | cursor:pointer; 52 | text-decoration:none; 53 | } 54 | 55 | #relay3 { 56 | font-size:22px; 57 | color:#fff; 58 | background-color:#555; 59 | border-radius: 12px; 60 | border:0; 61 | padding:10px; 62 | cursor:pointer; 63 | text-decoration:none; 64 | } 65 | 66 | .statusView {width: 100% !important; margin:0px; position: relative !important; height:28px; padding:10px 0 0 0; background-color:#E9E9E9; font-weight:bold; -webkit-border-radius: 0.7em !important; border-radius: 0.7em; display:none; text-align:center; } 67 | .statusViewAlert {width: 100% !important; margin:0px; position: relative !important; height:28px; padding:10px 0 0 0; background-color:#F8B584 !important; font-weight:bold; -webkit-border-radius: 0.7em !important; border-radius: 0.7em; display:none; text-align:center; } 68 | 69 | .btn-small { 70 | font-size:14px; 71 | color:#fff; 72 | background-color:#555; 73 | cursor:pointer; 74 | text-decoration:none; 75 | border:0; 76 | margin-right:-3px; 77 | padding-top:1px; 78 | padding-bottom:1px; 79 | } 80 | 81 | .btn-left { 82 | border-top-left-radius: 5px; 83 | border-bottom-left-radius: 5px; 84 | } 85 | 86 | .btn-right { 87 | border-top-right-radius: 5px; 88 | border-bottom-right-radius: 5px; 89 | } 90 | 91 | .btn-center { 92 | border-radius: 0px; 93 | } 94 | 95 | .slider { 96 | position: relative; 97 | width:100%; 98 | background-color:#fff; 99 | height:35px; 100 | margin-top:10px; 101 | } 102 | 103 | .slider-segment { 104 | position: absolute; 105 | background-color:#ff9600; 106 | height:100%; 107 | border-left: 2px solid #fff; 108 | border-radius: 5px; 109 | } 110 | 111 | .slider-label { 112 | position: absolute; 113 | color:#fff; 114 | margin-top:5px; 115 | margin-left:8px; 116 | font-weight:bold; 117 | text-shadow: 1px 1px rgba(200,200,200,0.5); 118 | font-size:14px; 119 | pointer-events: none; 120 | } 121 | 122 | .slider-button { 123 | position: absolute; 124 | top:0px; 125 | width:35px; 126 | height:100%; 127 | margin-left:-10px; 128 | margin-top:2px; 129 | cursor:pointer; 130 | } 131 | 132 | #slider-segment-temperature { 133 | width:35px; 134 | } 135 | 136 | input[type=text] { 137 | width:36px; 138 | border:0px; 139 | border-bottom: 1px solid #000; 140 | font-size:14px; 141 | color:#333; 142 | text-align:right; 143 | } 144 | 145 | #slider-segment-blank { 146 | height:35px; 147 | font-size:14px; 148 | } 149 | 150 | #timemarker { 151 | position:absolute; 152 | background-color:rgba(0,0,0,0.2); 153 | width:2px; 154 | height:35px; 155 | 156 | margin-top:0px; 157 | margin-left:-1px; 158 | border-top-left-radius: 5px; 159 | border-bottom-left-radius: 5px; 160 | pointer-events: none; 161 | border-left: 1px solid #fff; 162 | } 163 | -------------------------------------------------------------------------------- /html/control/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family:"Ubuntu Light"; 3 | color:#333 4 | } 5 | 6 | .zone-title { 7 | font-size:42px 8 | } 9 | 10 | .zone-setpoint { 11 | font-size:62px 12 | } 13 | 14 | .block { 15 | margin: 0px auto; 16 | max-width:392px; 17 | padding:20px; 18 | margin-top:50px; 19 | box-shadow: 0px 1px 10px rgba(0, 0, 0, 0.1); 20 | text-align:left; 21 | } 22 | 23 | #toggle { 24 | font-size:22px; 25 | color:#fff; 26 | background-color:#555; 27 | border-radius: 12px; 28 | border:0; 29 | padding:10px; 30 | cursor:pointer; 31 | text-decoration:none; 32 | } 33 | 34 | #relay1 { 35 | font-size:16px; 36 | color:#fff; 37 | background-color:#555; 38 | border-radius: 12px; 39 | border:0; 40 | padding:10px; 41 | cursor:pointer; 42 | text-decoration:none; 43 | width:100px; 44 | text-align:center; 45 | float:right ; 46 | margin-right:10px; 47 | } 48 | #relay2 { 49 | font-size:16px; 50 | color:#fff; 51 | background-color:#555; 52 | border-radius: 12px; 53 | border:0; 54 | padding:10px; 55 | cursor:pointer; 56 | text-decoration:none; 57 | width:100px; 58 | text-align:center; 59 | float:right ; 60 | margin-right:10px; 61 | } 62 | 63 | #relay3 { 64 | font-size:16px; 65 | color:#fff; 66 | background-color:#555; 67 | border-radius: 12px; 68 | border:0; 69 | padding:10px; 70 | cursor:pointer; 71 | text-decoration:none; 72 | width:100px; 73 | text-align:center; 74 | float:right; 75 | margin-right:10px; 76 | } 77 | 78 | .relay-label { 79 | padding: 0.1em 0px 0.1em 15px !important; 80 | font-size:22px; 81 | } 82 | 83 | .relay-row { 84 | width:100%; 85 | float:right; 86 | } 87 | 88 | .statusView {width: 100% !important; margin:0px; position: relative !important; height:28px; padding:10px 0 0 0; background-color:#E9E9E9; font-weight:bold; -webkit-border-radius: 0.7em !important; border-radius: 0.7em; display:none; text-align:center; } 89 | .statusViewAlert {width: 100% !important; margin:0px; position: relative !important; height:28px; padding:10px 0 0 0; background-color:#F8B584 !important; font-weight:bold; -webkit-border-radius: 0.7em !important; border-radius: 0.7em; display:none; text-align:center; } 90 | 91 | .btn-small { 92 | font-size:12px; 93 | color:#fff; 94 | background-color:#555; 95 | cursor:pointer; 96 | text-decoration:none; 97 | border:0; 98 | margin-right:-3px; 99 | padding-top:1px; 100 | padding-bottom:1px; 101 | } 102 | 103 | .btn-left { 104 | border-top-left-radius: 5px; 105 | border-bottom-left-radius: 5px; 106 | } 107 | 108 | .btn-right { 109 | border-top-right-radius: 5px; 110 | border-bottom-right-radius: 5px; 111 | } 112 | 113 | .btn-center { 114 | border-radius: 0px; 115 | } 116 | 117 | .slider { 118 | position: relative; 119 | width:100%; 120 | background-color:#fff; 121 | height:22px; 122 | margin-top:10px; 123 | } 124 | 125 | .slider-segment { 126 | position: absolute; 127 | background-color:#ff9600; 128 | height:100%; 129 | border-left: 1px solid #fff; 130 | border-radius: 5px; 131 | } 132 | 133 | .slider-label { 134 | position: absolute; 135 | color:#fff; 136 | margin-top:3px; 137 | margin-left:8px; 138 | font-weight:bold; 139 | text-shadow: 1px 1px rgba(200,200,200,0.5); 140 | font-size:12px; 141 | pointer-events: none; 142 | } 143 | 144 | .slider-button { 145 | position: absolute; 146 | top:0px; 147 | width:20px; 148 | height:100%; 149 | margin-left:-10px; 150 | margin-top:2px; 151 | cursor:pointer; 152 | } 153 | 154 | #slider-segment-temperature { 155 | width:35px; 156 | } 157 | 158 | input[type=text] { 159 | width:36px; 160 | border:0px; 161 | border-bottom: 1px solid #000; 162 | font-size:14px; 163 | color:#333; 164 | text-align:right; 165 | } 166 | 167 | #slider-segment-blank { 168 | height:20px; 169 | font-size:14px; 170 | } 171 | 172 | #timemarker { 173 | position:absolute; 174 | background-color:rgba(0,0,0,0.15); 175 | width:2px; 176 | height:22px; 177 | 178 | margin-top:0px; 179 | margin-left:-1px; 180 | border-top-left-radius: 5px; 181 | border-bottom-left-radius: 5px; 182 | pointer-events: none; 183 | border-left: 1px solid #fff; 184 | } 185 | 186 | 187 | -------------------------------------------------------------------------------- /html/control/thermostat.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Thermostat control 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 | 15 |
Zone name
16 |
17 |
18 |

SET POINT:

19 | 20 | 21 | 24 | 27 | 30 | 31 |
22 | 23 | 25 |
26 |
28 | 29 |
32 |

Room Temperature: 33 | 34 |

35 |
36 | 37 | 38 | 40 | 41 |
42 |
Schedule
43 |
44 |
45 | 51 | 55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 | 67 | 68 | 69 |
70 |

Average schedule temperature: °C

71 |

72 | 73 |

89 |

90 | 91 |
92 |
93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | -------------------------------------------------------------------------------- /html/control/thingspeak.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | 12 | 13 | ThingSpeak Multichannel 14 | 15 | 16 |

17 | Please wait..
18 |
19 |
26 | 28 | 46 | Update 47 | Chart (Latency) 48 |
49 | 50 | 51 | -------------------------------------------------------------------------------- /html/control/ui.css: -------------------------------------------------------------------------------- 1 | .ui-li .ui-btn-inner a.ui-link-inherit, .ui-li-static.ui-li { 2 | //display: block !important; 3 | padding: 0.9em 75px 0.9em 15px !important; 4 | margin-left: 7px; 5 | margin-right: 7px; 6 | } 7 | div.ui-slider-switch { 8 | position: absolute !important; 9 | right: 10px !important; 10 | width: 30% !important; 11 | } 12 | .inputvalue { 13 | position: absolute !important; 14 | right: 20px !important; 15 | width: 40% !important; 16 | text-align:right; 17 | color:coral; 18 | } 19 | 20 | .s-title { 21 | padding: 2.0em 75px 0.5em 5px !important; 22 | font-weight: bold; 23 | text-align:left; 24 | } 25 | 26 | -------------------------------------------------------------------------------- /html/control/ui.tpl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Relay Board 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 |
20 |

ESP8266 Relay Board

21 |

22 | 23 | 24 | 25 |
26 | 27 |
Relay 1
28 |
29 |
30 | 31 |
32 | 33 |
Relay 2
34 |
35 |
36 | 37 |
38 | 39 |
Relay 3
40 |
41 |
42 | 43 | 44 |
45 |
DS18B20 Temperature Sensors
46 |
    47 |
  • 48 | N/A 49 | --.--℃ 50 |
  • 51 |
  • 52 | N/A 53 | --.--℃ 54 |
  • 55 |
  • 56 | N/A 57 | --.--℃ 58 |
  • 59 |
  • 60 | N/A 61 | --.--℃ 62 |
  • 63 |
64 | 65 |
66 |
DHT22 Sensor
67 |
    68 |
  • 69 | DHT22 Temperature 70 | N/A 71 |
  • 72 |
  • 73 | DHT22 Humidity 74 | N/A 75 |
  • 76 |
77 | 78 |
79 |
Thermostat
80 |
    81 |
  • 82 | Thermostat 83 | N/A 84 |
  • 85 |
  • 86 | Thermostat Mode 87 | N/A 88 |
  • 89 |
  • 90 | Thermostat Room Temperature 91 | N/A 92 |
  • 93 |
  • 94 | Thermostat Set Point 95 | N/A 96 |
  • 97 |
  • 98 | Thermostat call for heat 99 | N/A 100 |
  • 101 |
102 | 103 |

104 | 105 |
106 | 107 |
108 | 109 |
110 | 111 | 112 | 113 | 114 | 115 | 128 | 129 | 130 | 131 | 132 | 133 | -------------------------------------------------------------------------------- /html/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mharizanov/ESP8266_Relay_Board/bb58eb2f41fc9a136600907f62672e4673c06658/html/favicon.ico -------------------------------------------------------------------------------- /html/index.tpl: -------------------------------------------------------------------------------- 1 | 2 | ESP8266 Relay Board 3 | 4 | 5 | 6 | 7 |
8 |

Harizanov 3Ch Relay/Thermostat

9 |

10 |

Settings

11 |
WiFi
12 | MQTT
13 | HTTP Daemon
14 | NTP
15 | Sensor
16 | Broadcast Daemon
17 | Relays
18 | Thermostat 19 | 20 |

Control / View

21 | Overview Page
22 | Thingspeak
23 | DHT22 Readings
24 | DS18B20 Readings
25 | Relays
26 | Thermostat 27 | 28 |

System

29 | Restart the system
30 | About 31 | 32 |

33 |
34 | 35 | -------------------------------------------------------------------------------- /html/js/flash.js: -------------------------------------------------------------------------------- 1 | //===== FLASH cards 2 | 3 | var flashSize = 0; 4 | 5 | function flashFirmware(e) { 6 | e.preventDefault(); 7 | var fw_data = document.getElementById('fw-file').files[0]; 8 | 9 | $("#fw-form").setAttribute("hidden", ""); 10 | showNotification("Firmware is being updated ..."); 11 | 12 | ajaxReq("POST", "/flash/upload", function(resp) { 13 | ajaxReq("GET", "/flash/reboot", function(resp) { 14 | showNotification("Firmware has been successfully updated!"); 15 | setTimeout(function() { window.location.reload() }, 4000); 16 | 17 | $("#fw-form").removeAttribute("hidden"); 18 | $("#fw-form").removeAttribute("hidden"); 19 | }); 20 | }, errCb, fw_data) 21 | } 22 | 23 | function errCb(status, errText) { 24 | 25 | // alert (errText); 26 | showWarning("Operation failed:" + errText); 27 | } 28 | function flashEspfs(e) { 29 | e.preventDefault(); 30 | var fw_data = document.getElementById('espfs-file').files[0]; 31 | 32 | $("#espfs-form").setAttribute("hidden", ""); 33 | showNotification("Webpage ESPFS is being updated ..."); 34 | 35 | ajaxReq("POST", "/flash/upload-espfs", function(resp) { 36 | setTimeout(function() { window.location.reload() }, 2000); 37 | showNotification("Webpages have been successfully updated!"); 38 | $("#espfs-form").removeAttribute("hidden"); 39 | $("#espfs-form").removeAttribute("hidden"); 40 | }, errCb, fw_data) 41 | } 42 | 43 | function fetchFlash() { 44 | // Only show flash upload dialogue if flash map >1 45 | // i.e. Flash size > 512Kb 46 | ajaxReq("GET", "/flash/flash-size", function(resp) { 47 | if (resp > 1) { 48 | ajaxReq("GET", "/flash/next", function(resp) { $("#fw-slot").innerHTML = resp; }, errCb, null); 49 | $("#fw-upgrade").removeAttribute("hidden"); 50 | $("#fw-form").removeAttribute("hidden"); 51 | 52 | } else { 53 | $("#fw-upgrade").setAttribute("hidden", ""); 54 | $("#fw-form").setAttribute("hidden", "") 55 | } 56 | }, null, null); 57 | 58 | ajaxReq("GET", "/flash/version", function(resp) { 59 | var v = $("#current-fw"); 60 | if (v != null) { 61 | v.innerHTML = resp; 62 | } else { 63 | v.innerHTML = "Unknown"; 64 | } 65 | }, errCb, null); 66 | } 67 | -------------------------------------------------------------------------------- /html/js/ui_tpl.js: -------------------------------------------------------------------------------- 1 | /* 2 | Based on Luca Soltoggio's work 3 | http://arduinoelettronica.wordpress.com/ 4 | 5 | */ 6 | 7 | var visibleFlag = 1; 8 | 9 | var thermostat = { 10 | room_temp : -9999, 11 | humidity : "N/A", 12 | humidistat : 0, 13 | thermostat_relay_active : 0, 14 | relay1name : "N/A", 15 | opmode : 0, 16 | enable : 0, 17 | manual_setpoint : -9999, 18 | current_setpoint : -9999, 19 | thermostat1_input : 0, 20 | schedule_mode : 0, 21 | mqtthost : "N/A" 22 | }; 23 | 24 | // function for checking if the page is visible or not 25 | // (if not visible it will stop updating data) 26 | function checkVisibility() { 27 | $(window).bind("focus", function(event) { visibleFlag = 1; }); 28 | 29 | $(window).bind("blur", function(event) { visibleFlag = 0; }); 30 | } 31 | 32 | function sensor_get() { 33 | var output = {}; 34 | // if (visibleFlag) { 35 | $.ajax({ 36 | url : "../control/sensor.cgi", 37 | dataType : 'json', 38 | async : true, 39 | timeout : 3000, 40 | tryCount : 0, 41 | retryLimit : 3, 42 | success : function(data) { 43 | if (data.length !== 0) { 44 | statusMsg = false; 45 | if (!connected) 46 | setStatus("Connected", 2, 0); 47 | connected = true; 48 | if (!doingsave) { 49 | sensors = data; 50 | sensor_update(); 51 | } 52 | } 53 | }, 54 | error : function(xhr, textStatus, errorThrown) { 55 | if (textStatus == 'timeout') { 56 | this.tryCount++; 57 | if (this.tryCount <= this.retryLimit) { 58 | // try again 59 | $.ajax(this); 60 | return; 61 | } 62 | return; 63 | } 64 | if (connected) 65 | setStatus("No connection to server!", 0, 1); 66 | connected = false; 67 | } 68 | }); 69 | // } 70 | return output; 71 | } 72 | 73 | function therm_get() { 74 | var output = {}; 75 | 76 | // if (visibleFlag) { 77 | $.ajax({ 78 | url : "thermostat.cgi?param=state", 79 | dataType : 'json', 80 | async : true, 81 | timeout : 3000, 82 | tryCount : 0, 83 | retryLimit : 3, 84 | success : function(data) { 85 | if (data.length !== 0) { 86 | statusMsg = false; 87 | if (!connected) 88 | setStatus("Connected", 2, 0); 89 | connected = true; 90 | if (!doingsave) { 91 | thermostat = data; 92 | therm_update(); 93 | } 94 | } 95 | }, 96 | error : function(xhr, textStatus, errorThrown) { 97 | if (textStatus == 'timeout') { 98 | this.tryCount++; 99 | if (this.tryCount <= this.retryLimit) { 100 | // try again 101 | $.ajax(this); 102 | return; 103 | } 104 | return; 105 | } 106 | if (connected) 107 | setStatus("No connection to server!", 0, 1); 108 | connected = false; 109 | } 110 | }); 111 | // } 112 | return output; 113 | } 114 | 115 | function sensor_update() { 116 | 117 | if (sensors.ds18b20.length > 0) { 118 | $("#ds18b20_0").show(); 119 | $("#ds18b20_temperature_0").html(sensors.ds18b20[0].temperature + "℃"); 120 | $("#ds18b20_id_0").html(sensors.ds18b20[0].id); 121 | } else { 122 | $("#ds18b20_0").hide(); 123 | $("#ds18b20_1").hide(); 124 | $("#ds18b20_2").hide(); 125 | $("#ds18b20_3").hide(); 126 | } 127 | 128 | if (sensors.ds18b20.length > 1) { 129 | $("#ds18b20_1").show(); 130 | $("#ds18b20_temperature_1").html(sensors.ds18b20[1].temperature + "℃"); 131 | $("#ds18b20_id_1").html(sensors.ds18b20[1].id); 132 | } else { 133 | $("#ds18b20_1").hide(); 134 | $("#ds18b20_2").hide(); 135 | $("#ds18b20_3").hide(); 136 | } 137 | 138 | if (sensors.ds18b20.length > 2) { 139 | $("#ds18b20_2").show(); 140 | $("#ds18b20_temperature_2").html(sensors.ds18b20[2].temperature + "℃"); 141 | $("#ds18b20_id_2").html(sensors.ds18b20[2].id); 142 | } else { 143 | $("#ds18b20_2").hide(); 144 | $("#ds18b20_3").hide(); 145 | } 146 | 147 | if (sensors.ds18b20.length > 3) { 148 | $("#ds18b20_3").show(); 149 | $("#ds18b20_temperature_3").html(sensors.ds18b20[3].temperature + "℃"); 150 | $("#ds18b20_id_3").html(sensors.ds18b20[3].id); 151 | } else { 152 | $("#ds18b20_3").hide(); 153 | } 154 | 155 | if (sensors.dht22.length > 0) { 156 | $("#DHT22temperature").html(sensors.dht22[0].temperature); 157 | $("#DHT22humidity").html(sensors.dht22[0].humidity); 158 | } 159 | } 160 | 161 | function therm_update() { 162 | 163 | if (thermostat.enable == 0) { 164 | var therm_state = "Off"; 165 | $("#thermostat_enable").html("Disabled"); 166 | $("#schedule_mode").hide(); 167 | $("#room_temp_li").hide(); 168 | $("#set_point_li").hide(); 169 | $("#call_for_heat_li").hide(); 170 | 171 | } else if (thermostat.enable == 1) { 172 | $("#thermostat_enable").html("Enabled"); 173 | $("#schedule_mode").show(); 174 | $("#room_temp_li").show(); 175 | $("#set_point_li").show(); 176 | $("#call_for_heat_li").show(); 177 | } 178 | if (thermostat.room_temp == -9999) { 179 | $("#thermostat1_room_temperature").html("--.-"); 180 | } else { 181 | $("#thermostat1_room_temperature").html(thermostat.room_temp / 10); 182 | } 183 | 184 | if (thermostat.current_setpoint == -9999) { 185 | $("#thermostat1_setpoint").html("--.-"); 186 | } else { 187 | $("#thermostat1_setpoint").html(thermostat.current_setpoint / 10); 188 | } 189 | 190 | if (thermostat.thermostat_relay_active == 0) { 191 | $("#thermostat1_on").html("No"); 192 | } else if (thermostat.thermostat_relay_active == 1) { 193 | $("#thermostat1_on").html("Yes"); 194 | } else if (thermostat.thermostat_relay_active == 2) { 195 | $("#thermostat1_on").html("Relay Rest Period"); 196 | } else { 197 | $("#thermostat1_on").html("Unknown State"); 198 | } 199 | 200 | if (thermostat.schedule_mode == 0) { 201 | $("#thermostat1_schedule_mode").html("Manual"); 202 | } else if (thermostat.schedule_mode == 1) { 203 | $("#thermostat1_schedule_mode").html("Schedule"); 204 | } else if (thermostat.schedule_mode == 2) { 205 | $("#thermostat1_schedule_mode").html("Schedule Override"); 206 | } else { 207 | $("#thermostat1_schedule_mode").html("Unknown Mode"); 208 | } 209 | } 210 | -------------------------------------------------------------------------------- /html/style.css: -------------------------------------------------------------------------------- 1 | 2 | body { 3 | background-color: #404040; 4 | font-family: sans-serif; 5 | } 6 | 7 | #main { 8 | background-color: #A7C0C0; 9 | -moz-border-radius: 5px; 10 | -webkit-border-radius: 5px; 11 | border-radius: 5px; 12 | border: 2px solid #000000; 13 | width: auto; 14 | margin: 0 auto; 15 | padding: 20px 16 | } 17 | /*===== spinners and notification messages */ 18 | 19 | #messages { 20 | position: absolute; 21 | left: 25%; 22 | width: 50%; 23 | top: 10; 24 | z-index: 200; 25 | font-size: 110%; 26 | text-align: center; 27 | } 28 | #warning { 29 | background-color: #933; 30 | color: #fcc; 31 | padding: 0.1em 0.4em; 32 | } 33 | #notification { 34 | background-color: #693; 35 | color: #cfc; 36 | padding: 0.1em 0.4em; 37 | } 38 | 39 | #spinner { 40 | position: absolute; 41 | right: 10%; 42 | top: 20; 43 | z-index: 1000; 44 | } 45 | .spinner { 46 | height: 50px; 47 | width: 50px; 48 | -webkit-animation: rotation 1s infinite linear; 49 | animation: rotation 1s infinite linear; 50 | border-left: 10px solid rgba(204, 51, 0, 0.15); 51 | border-right: 10px solid rgba(204, 51, 0, 0.15); 52 | border-bottom: 10px solid rgba(204, 51, 0, 0.15); 53 | border-top: 10px solid rgba(204, 51, 0, 0.8); 54 | border-radius: 100%; 55 | } 56 | .spinner-small { 57 | display: inline-block; 58 | height: 1em; 59 | width: 1em; 60 | border-width: 4px; 61 | } 62 | -------------------------------------------------------------------------------- /include/README: -------------------------------------------------------------------------------- 1 | 2 | This directory is intended for project header files. 3 | 4 | A header file is a file containing C declarations and macro definitions 5 | to be shared between several project source files. You request the use of a 6 | header file in your project source file (C, C++, etc) located in `src` folder 7 | by including it, with the C preprocessing directive `#include'. 8 | 9 | ```src/main.c 10 | 11 | #include "header.h" 12 | 13 | int main (void) 14 | { 15 | ... 16 | } 17 | ``` 18 | 19 | Including a header file produces the same results as copying the header file 20 | into each source file that needs it. Such copying would be time-consuming 21 | and error-prone. With a header file, the related declarations appear 22 | in only one place. If they need to be changed, they can be changed in one 23 | place, and programs that include the header file will automatically use the 24 | new version when next recompiled. The header file eliminates the labor of 25 | finding and changing all the copies as well as the risk that a failure to 26 | find one copy will result in inconsistencies within a program. 27 | 28 | In C, the usual convention is to give header files names that end with `.h'. 29 | It is most portable to use only letters, digits, dashes, and underscores in 30 | header file names, and at most one dot. 31 | 32 | Read more about using header files in official GCC documentation: 33 | 34 | * Include Syntax 35 | * Include Operation 36 | * Once-Only Headers 37 | * Computed Includes 38 | 39 | https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html 40 | -------------------------------------------------------------------------------- /include/arch/cc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2001, Swedish Institute of Computer Science. 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. Neither the name of the Institute nor the names of its contributors 14 | * may be used to endorse or promote products derived from this software 15 | * without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 21 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 | * SUCH DAMAGE. 28 | * 29 | * This file is part of the lwIP TCP/IP stack. 30 | * 31 | * Author: Adam Dunkels 32 | * 33 | */ 34 | #ifndef __ARCH_CC_H__ 35 | #define __ARCH_CC_H__ 36 | 37 | //#include 38 | #include "c_types.h" 39 | #include "ets_sys.h" 40 | #include "osapi.h" 41 | // included to define BYTE_ORDER 42 | #include 43 | 44 | #define EFAULT 14 45 | 46 | //#define LWIP_PROVIDE_ERRNO 47 | /* 48 | #if (1) 49 | #define BYTE_ORDER LITTLE_ENDIAN 50 | #else 51 | #define BYTE_ORDER BIG_ENDIAN 52 | #endif 53 | */ 54 | 55 | typedef unsigned char u8_t; 56 | typedef signed char s8_t; 57 | typedef unsigned short u16_t; 58 | typedef signed short s16_t; 59 | typedef unsigned long u32_t; 60 | typedef signed long s32_t; 61 | typedef unsigned long mem_ptr_t; 62 | 63 | #define S16_F "d" 64 | #define U16_F "d" 65 | #define X16_F "x" 66 | 67 | #define S32_F "d" 68 | #define U32_F "d" 69 | #define X32_F "x" 70 | 71 | //#define PACK_STRUCT_FIELD(x) x __attribute__((packed)) 72 | #define PACK_STRUCT_FIELD(x) x 73 | #define PACK_STRUCT_STRUCT __attribute__((packed)) 74 | #define PACK_STRUCT_BEGIN 75 | #define PACK_STRUCT_END 76 | 77 | //#define LWIP_DEBUG 78 | 79 | #ifdef LWIP_DEBUG 80 | #define LWIP_PLATFORM_DIAG(x) os_printf x 81 | #define LWIP_PLATFORM_ASSERT(x) ETS_ASSERT(x) 82 | #else 83 | #define LWIP_PLATFORM_DIAG(x) 84 | #define LWIP_PLATFORM_ASSERT(x) 85 | #endif 86 | 87 | #define SYS_ARCH_DECL_PROTECT(x) 88 | #define SYS_ARCH_PROTECT(x) 89 | #define SYS_ARCH_UNPROTECT(x) 90 | 91 | #define LWIP_PLATFORM_BYTESWAP 1 92 | #define LWIP_PLATFORM_HTONS(_n) ((u16_t)((((_n)&0xff) << 8) | (((_n) >> 8) & 0xff))) 93 | #define LWIP_PLATFORM_HTONL(_n) \ 94 | ((u32_t)((((_n)&0xff) << 24) | (((_n)&0xff00) << 8) | (((_n) >> 8) & 0xff00) | (((_n) >> 24) & 0xff))) 95 | 96 | #if LWIP_RAW 97 | extern u8_t memp_memory_RAW_PCB_base[]; 98 | #endif /* LWIP_RAW */ 99 | 100 | #if LWIP_UDP 101 | extern u8_t memp_memory_UDP_PCB_base[]; 102 | #endif /* LWIP_UDP */ 103 | 104 | #if LWIP_TCP 105 | extern u8_t memp_memory_TCP_PCB_base[]; 106 | extern u8_t memp_memory_TCP_PCB_LISTEN_base[]; 107 | extern u8_t memp_memory_TCP_SEG_base[] SHMEM_ATTR; 108 | #endif /* LWIP_TCP */ 109 | 110 | #if (!NO_SYS || (NO_SYS && !NO_SYS_NO_TIMERS)) /* LWIP_TIMERS */ 111 | extern u8_t memp_memory_SYS_TIMEOUT_base[]; 112 | #endif /* LWIP_TIMERS */ 113 | 114 | extern u8_t memp_memory_PBUF_base[]; 115 | extern u8_t memp_memory_PBUF_POOL_base[]; 116 | 117 | #endif /* __ARCH_CC_H__ */ 118 | -------------------------------------------------------------------------------- /include/arch/perf.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2001, Swedish Institute of Computer Science. 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. Neither the name of the Institute nor the names of its contributors 14 | * may be used to endorse or promote products derived from this software 15 | * without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 21 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 | * SUCH DAMAGE. 28 | * 29 | * This file is part of the lwIP TCP/IP stack. 30 | * 31 | * Author: Adam Dunkels 32 | * 33 | */ 34 | #ifndef __PERF_H__ 35 | #define __PERF_H__ 36 | 37 | #define PERF_START /* null definition */ 38 | #define PERF_STOP(x) /* null definition */ 39 | 40 | #endif /* __PERF_H__ */ 41 | -------------------------------------------------------------------------------- /include/arch/sys_arch.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mharizanov/ESP8266_Relay_Board/bb58eb2f41fc9a136600907f62672e4673c06658/include/arch/sys_arch.h -------------------------------------------------------------------------------- /include/auth.h: -------------------------------------------------------------------------------- 1 | #ifndef AUTH_H 2 | #define AUTH_H 3 | 4 | #include "httpd.h" 5 | #include "httpdconfig.h" 6 | 7 | #ifndef HTTP_AUTH_REALM 8 | #define HTTP_AUTH_REALM "Protected" 9 | #endif 10 | 11 | #define HTTPD_AUTH_SINGLE 0 12 | #define HTTPD_AUTH_CALLBACK 1 13 | 14 | #define AUTH_MAX_USER_LEN 32 15 | #define AUTH_MAX_PASS_LEN 32 16 | 17 | // Parameter given to authWhatever functions. This callback returns the usernames/passwords the device 18 | // has. 19 | typedef int (*AuthGetUserPw)(HttpdConnData *connData, int no, char *user, int userLen, char *pass, int passLen); 20 | 21 | int ICACHE_FLASH_ATTR authBasic(HttpdConnData *connData); 22 | 23 | #endif -------------------------------------------------------------------------------- /include/base64.h: -------------------------------------------------------------------------------- 1 | int base64_decode2(size_t in_len, const char *in, size_t out_len, unsigned char *out); 2 | -------------------------------------------------------------------------------- /include/broadcastd.h: -------------------------------------------------------------------------------- 1 | void broadcastd_init(void); -------------------------------------------------------------------------------- /include/cgi.h: -------------------------------------------------------------------------------- 1 | #ifndef CGI_H 2 | #define CGI_H 3 | 4 | #include "httpd.h" 5 | 6 | void errorResponse(HttpdConnData *connData, int code, char *message); 7 | void noCacheHeaders(HttpdConnData *connData, int code); 8 | 9 | int cgiGPIO(HttpdConnData *connData); 10 | void tplGPIO(HttpdConnData *connData, char *token, void **arg); 11 | int cgiReadFlash(HttpdConnData *connData); 12 | void tplCounter(HttpdConnData *connData, char *token, void **arg); 13 | void tplDHT(HttpdConnData *connData, char *token, void **arg); 14 | int cgiDHT22(HttpdConnData *connData); 15 | void tplDS18b20(HttpdConnData *connData, char *token, void **arg); 16 | int cgiDS18b20(HttpdConnData *connData); 17 | int cgiState(HttpdConnData *connData); 18 | int cgiSensor(HttpdConnData *connData); 19 | int cgiUI(HttpdConnData *connData); 20 | void tplUI(HttpdConnData *connData, char *token, void **arg); 21 | void tplMQTT(HttpdConnData *connData, char *token, void **arg); 22 | int cgiMQTT(HttpdConnData *connData); 23 | void tplHTTPD(HttpdConnData *connData, char *token, void **arg); 24 | int cgiHTTPD(HttpdConnData *connData); 25 | void tplBroadcastD(HttpdConnData *connData, char *token, void **arg); 26 | int cgiBroadcastD(HttpdConnData *connData); 27 | void tplNTP(HttpdConnData *connData, char *token, void **arg); 28 | int cgiNTP(HttpdConnData *connData); 29 | int cgiReset(HttpdConnData *connData); 30 | void tplRLYSettings(HttpdConnData *connData, char *token, void **arg); 31 | int cgiRLYSettings(HttpdConnData *connData); 32 | void tplSensorSettings(HttpdConnData *connData, char *token, void **arg); 33 | int cgiSensorSettings(HttpdConnData *connData); 34 | void tplThermostatSettings(HttpdConnData *connData, char *token, void **arg); 35 | int cgiThermostatSettings(HttpdConnData *connData); 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /include/cgiflash.h: -------------------------------------------------------------------------------- 1 | #ifndef CGIFLASH_H 2 | #define CGIFLASH_H 3 | 4 | #define FW_MAX_SIZE 503808 5 | #define ESPFS_MAX_SIZE 120000 6 | #include "httpd.h" 7 | #include "spi_flash.h" 8 | 9 | int cgiReadFlash(HttpdConnData *connData); 10 | int cgiGetFirmwareNext(HttpdConnData *connData); 11 | int cgiGetFirmwareVersion(HttpdConnData *connData); 12 | int cgiUploadFirmware(HttpdConnData *connData); 13 | int cgiUploadEspfs(HttpdConnData *connData); 14 | int cgiRebootFirmware(HttpdConnData *connData); 15 | int cgiGetFlashSize(HttpdConnData *connData); 16 | // int cgiReset(HttpdConnData *connData); 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /include/cgithermostat.h: -------------------------------------------------------------------------------- 1 | #ifndef CGITHERMOSTAT_H 2 | #define CGITHERMOSTAT_H 3 | 4 | #include "httpd.h" 5 | 6 | int cgiThermostat(HttpdConnData *connData); 7 | void tplThermostat(HttpdConnData *connData, char *token, void **arg); 8 | 9 | #endif 10 | -------------------------------------------------------------------------------- /include/cgiwifi.h: -------------------------------------------------------------------------------- 1 | #ifndef CGIWIFI_H 2 | #define CGIWIFI_H 3 | 4 | #include "httpd.h" 5 | 6 | int cgiWiFiScan(HttpdConnData *connData); 7 | int tplWlan(HttpdConnData *connData, char *token, void **arg); 8 | int cgiWiFi(HttpdConnData *connData); 9 | int cgiWiFiConnect(HttpdConnData *connData); 10 | int cgiWiFiSetMode(HttpdConnData *connData); 11 | int cgiWiFiConnStatus(HttpdConnData *connData); 12 | 13 | #endif -------------------------------------------------------------------------------- /include/config.h: -------------------------------------------------------------------------------- 1 | /* config.h 2 | * 3 | * Copyright (c) 2014-2015, Tuan PM 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * 9 | * * Redistributions of source code must retain the above copyright notice, 10 | * this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * * Neither the name of Redis nor the names of its contributors may be used 15 | * to endorse or promote products derived from this software without 16 | * specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 22 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | * POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | #ifndef USER_CONFIG_H_ 32 | #define USER_CONFIG_H_ 33 | #include "os_type.h" 34 | #include "user_config.h" 35 | 36 | #define THERMOSTAT_MANUAL 0 37 | #define THERMOSTAT_AUTO 1 38 | #define THERMOSTAT_OVERRIDE 2 39 | 40 | #define THERMOSTAT_HEATING 0 41 | #define THERMOSTAT_COOLING 1 42 | 43 | #define USERJSONMAX 250 // max size of JSON string submitted via serial 44 | 45 | typedef struct { 46 | uint16_t start; 47 | uint16_t end; 48 | uint16_t setpoint; // Degrees C in * 100 i.e. 2350=23.5*C 49 | uint16_t active; // pad to 4 byte boundary 50 | } dayScheduleElement; 51 | 52 | typedef struct { 53 | dayScheduleElement daySched[8]; // Max 8 schedules per day 54 | } daySchedule; 55 | 56 | typedef struct { 57 | daySchedule weekSched[7]; // 7 days per week 58 | } weekSchedule; 59 | 60 | typedef struct { 61 | 62 | // 4 byte alignment, hence uint32_t 63 | uint32_t cfg_holder; 64 | 65 | uint8_t sta_mode[8]; 66 | uint8_t sta_ip[16]; 67 | uint8_t sta_mask[16]; 68 | uint8_t sta_gw[16]; 69 | 70 | uint8_t sta_ssid[32]; 71 | uint8_t sta_pass[32]; 72 | uint8_t ap_ip[32]; 73 | uint8_t ap_mask[32]; 74 | 75 | uint32_t sta_type; 76 | 77 | uint8_t ap_gw[32]; 78 | uint8_t broadcastd_ro_apikey[32]; 79 | uint8_t httpd_user[16]; 80 | uint8_t httpd_pass[16]; 81 | 82 | uint32_t httpd_port; 83 | uint32_t httpd_auth; 84 | 85 | uint8_t broadcastd_enable; 86 | uint8_t syslog_enable; 87 | 88 | uint32_t broadcastd_port; 89 | 90 | uint8_t broadcastd_host[32]; 91 | uint8_t broadcastd_url[256]; 92 | uint8_t syslog_host[32]; 93 | uint8_t DST; 94 | 95 | uint8_t ntp_enable; 96 | int8_t ntp_tz; 97 | 98 | uint32_t broadcastd_thingspeak_channel; 99 | 100 | uint32_t mqtt_enable; 101 | uint8_t mqtt_host[64]; 102 | uint32_t mqtt_port; 103 | uint32_t mqtt_keepalive; 104 | 105 | uint8_t mqtt_devid[32]; 106 | uint8_t mqtt_user[32]; 107 | uint8_t mqtt_pass[64]; 108 | uint8_t mqtt_relay_subs_topic[64]; 109 | 110 | uint8_t mqtt_temp_subs_topic[64]; 111 | uint8_t mqtt_dht22_temp_pub_topic[64]; 112 | uint8_t mqtt_dht22_humi_pub_topic[64]; 113 | uint8_t mqtt_ds18b20_temp_pub_topic[64]; 114 | 115 | uint8_t mqtt_state_pub_topic[64]; 116 | uint8_t mqtt_userJSON_pub_topic[64]; 117 | uint8_t sensor_ds18b20_enable; 118 | uint8_t sensor_dht22_enable; 119 | 120 | uint16_t mqtt_use_ssl; 121 | uint8_t relay_total; 122 | uint8_t relay_latching_enable; 123 | 124 | uint8_t relay1_state; 125 | uint8_t relay2_state; 126 | uint8_t relay3_state; 127 | uint8_t relay1_thermostat; 128 | 129 | uint8_t relay2_thermostat; 130 | uint8_t relay3_thermostat; 131 | uint8_t relay1_name[24]; 132 | uint8_t relay2_name[24]; 133 | 134 | uint8_t relay3_name[24]; 135 | uint8_t relay1_gpio; 136 | uint8_t relay2_gpio; 137 | uint8_t relay3_gpio; 138 | 139 | uint8_t thermostat1_zone_name[24]; 140 | uint8_t therm_relay_rest_min; 141 | uint16_t therm_low_temp_colour_deg; 142 | 143 | uint16_t therm_high_temp_colour_deg; 144 | 145 | uint32_t therm_room_temp_timeout_secs; 146 | uint32_t thermostat1_input; 147 | uint32_t thermostat1_schedule_mode; 148 | uint32_t thermostat1_manual_setpoint; 149 | 150 | uint32_t thermostat1_enable; 151 | uint32_t thermostat1_opmode; 152 | uint32_t thermostat1_hysteresis_high; 153 | uint32_t thermostat1_hysteresis_low; 154 | 155 | weekSchedule thermostat1_schedule; 156 | /* 157 | uint32_t thermostat2enable; 158 | uint32_t thermostat2manualsetpoint; 159 | uint32_t thermostat2mode; 160 | uint32_t thermostat2opmode; 161 | uint32_t thermostat2_hysteresis_high; 162 | uint32_t thermostat2_hysteresis_low; 163 | weekSchedule thermostat2schedule; 164 | 165 | uint32_t thermostat3enable; 166 | uint32_t thermostat3manualsetpoint; 167 | uint32_t thermostat3mode; 168 | uint32_t thermostat3opmode; 169 | uint32_t thermostat3_hysteresis_high; 170 | uint32_t thermostat3_hysteresis_low; 171 | weekSchedule thermostat3schedule; 172 | */ 173 | 174 | } SYSCFG; 175 | 176 | typedef struct { 177 | uint8 flag; 178 | uint8 pad[3]; 179 | } SAVE_FLAG; 180 | 181 | void CFG_Save(); 182 | void CFG_Load(); 183 | 184 | extern SYSCFG sysCfg; 185 | 186 | #endif /* USER_CONFIG_H_ */ 187 | -------------------------------------------------------------------------------- /include/debug.h: -------------------------------------------------------------------------------- 1 | /* 2 | * debug.h 3 | * 4 | * Created on: Dec 4, 2014 5 | * Author: Minh 6 | */ 7 | 8 | #ifndef USER_DEBUG_H_ 9 | #define USER_DEBUG_H_ 10 | 11 | 12 | 13 | #define INFO os_printf 14 | 15 | #endif /* USER_DEBUG_H_ */ 16 | -------------------------------------------------------------------------------- /include/dht22.h: -------------------------------------------------------------------------------- 1 | #include "c_types.h" 2 | #include 3 | 4 | enum sensor_type { SENSOR_DHT11, SENSOR_DHT22 }; 5 | 6 | struct sensor_reading { 7 | float temperature; 8 | float humidity; 9 | const char *source; 10 | uint8_t sensor_id[16]; 11 | BOOL success; 12 | time_t readingTS; // timestamp of the reading 13 | }; 14 | 15 | struct sensor_reading *readDHT(void); 16 | void DHTInit(enum sensor_type, uint32_t polltime); 17 | 18 | int dht_temp_str(char *buff); 19 | int dht_humi_str(char *buff); 20 | -------------------------------------------------------------------------------- /include/driver/i2c.h: -------------------------------------------------------------------------------- 1 | #ifndef __I2C_H__ 2 | #define __I2C_H__ 3 | #endif 4 | 5 | /* 6 | I2C driver for the ESP8266 7 | Copyright (C) 2014 Rudy Hardeman (zarya) 8 | 9 | This program is free software; you can redistribute it and/or modify 10 | it under the terms of the GNU General Public License as published by 11 | the Free Software Foundation; either version 2 of the License, or 12 | (at your option) any later version. 13 | 14 | This program is distributed in the hope that it will be useful, 15 | but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | GNU General Public License for more details. 18 | 19 | You should have received a copy of the GNU General Public License along 20 | with this program; if not, write to the Free Software Foundation, Inc., 21 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 22 | */ 23 | 24 | #include "ets_sys.h" 25 | #include "osapi.h" 26 | #include "gpio.h" 27 | 28 | //#define I2C_SLEEP_TIME 10 29 | #define I2C_SLEEP_TIME 2 30 | 31 | //SDA on GPIO14 32 | #define I2C_SDA_MUX PERIPHS_IO_MUX_MTMS_U 33 | #define I2C_SDA_FUNC FUNC_GPIO14 34 | #define I2C_SDA_PIN 14 35 | 36 | //SCK on GPIO0 37 | #define I2C_SCK_MUX PERIPHS_IO_MUX_GPIO0_U 38 | #define I2C_SCK_PIN 0 39 | #define I2C_SCK_FUNC FUNC_GPIO0 40 | 41 | #define i2c_read() GPIO_INPUT_GET(GPIO_ID_PIN(I2C_SDA_PIN)); 42 | 43 | void i2c_init(void); 44 | void i2c_start(void); 45 | void i2c_stop(void); 46 | void i2c_send_ack(uint8 state); 47 | uint8 i2c_check_ack(void); 48 | uint8 i2c_readByte(void); 49 | void i2c_writeByte(uint8 data); 50 | -------------------------------------------------------------------------------- /include/driver/i2c_oled.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Oryginal by: 3 | * Author : Aaron Lee 4 | * Version: 1.00 5 | * Date : 2014.3.24 6 | * Email : hello14blog@gmail.com 7 | * Modification: none 8 | * Mod by reaper7 9 | * found at http://bbs.espressif.com/viewtopic.php?f=15&t=31 10 | */ 11 | 12 | #ifndef __I2C_OLED_H 13 | #define __I2C_OLED_H 14 | 15 | #include "c_types.h" 16 | #include "ets_sys.h" 17 | #include "osapi.h" 18 | 19 | #define OLED_ADDRESS 0x78 // D/C->GND 20 | //#define OLED_ADDRESS 0x7a // D/C->Vcc 21 | 22 | void OLED_writeCmd(unsigned char I2C_Command); 23 | void OLED_writeDat(unsigned char I2C_Data); 24 | bool OLED_Init(void); 25 | void OLED_SetPos(unsigned char x, unsigned char y); 26 | void OLED_Fill(unsigned char fill_Data); 27 | void OLED_CLS(void); 28 | void OLED_ON(void); 29 | void OLED_OFF(void); 30 | void OLED_ShowStr(unsigned char x, unsigned char y, unsigned char ch[], unsigned char TextSize); 31 | void OLED_DrawBMP(unsigned char x0,unsigned char y0,unsigned char x1,unsigned char y1,unsigned char BMP[]); 32 | void OLED_Line(unsigned char x, unsigned char ch[], unsigned char TextSize); 33 | void OLED_Print(unsigned char x, unsigned char y, unsigned char ch[], unsigned char TextSize); 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /include/driver/uart.h.bak: -------------------------------------------------------------------------------- 1 | #ifndef UART_APP_H 2 | #define UART_APP_H 3 | 4 | #include "uart_register.h" 5 | #include "eagle_soc.h" 6 | #include "c_types.h" 7 | 8 | #define RX_BUFF_SIZE 256 9 | #define TX_BUFF_SIZE 100 10 | #define UART0 0 11 | #define UART1 1 12 | 13 | typedef enum { 14 | FIVE_BITS = 0x0, 15 | SIX_BITS = 0x1, 16 | SEVEN_BITS = 0x2, 17 | EIGHT_BITS = 0x3 18 | } UartBitsNum4Char; 19 | 20 | typedef enum { 21 | ONE_STOP_BIT = 0, 22 | ONE_HALF_STOP_BIT = BIT2, 23 | TWO_STOP_BIT = BIT2 24 | } UartStopBitsNum; 25 | 26 | typedef enum { 27 | NONE_BITS = 0, 28 | ODD_BITS = 0, 29 | EVEN_BITS = BIT4 30 | } UartParityMode; 31 | 32 | typedef enum { 33 | STICK_PARITY_DIS = 0, 34 | STICK_PARITY_EN = BIT3 | BIT5 35 | } UartExistParity; 36 | 37 | typedef enum { 38 | BIT_RATE_9600 = 9600, 39 | BIT_RATE_19200 = 19200, 40 | BIT_RATE_38400 = 38400, 41 | BIT_RATE_57600 = 57600, 42 | BIT_RATE_74880 = 74880, 43 | BIT_RATE_115200 = 115200, 44 | BIT_RATE_230400 = 230400, 45 | BIT_RATE_256000 = 256000, 46 | BIT_RATE_460800 = 460800, 47 | BIT_RATE_921600 = 921600 48 | } UartBautRate; 49 | 50 | typedef enum { 51 | NONE_CTRL, 52 | HARDWARE_CTRL, 53 | XON_XOFF_CTRL 54 | } UartFlowCtrl; 55 | 56 | typedef enum { 57 | EMPTY, 58 | UNDER_WRITE, 59 | WRITE_OVER 60 | } RcvMsgBuffState; 61 | 62 | typedef struct { 63 | uint32 RcvBuffSize; 64 | uint8 *pRcvMsgBuff; 65 | uint8 *pWritePos; 66 | uint8 *pReadPos; 67 | uint8 TrigLvl; //JLU: may need to pad 68 | RcvMsgBuffState BuffState; 69 | } RcvMsgBuff; 70 | 71 | typedef struct { 72 | uint32 TrxBuffSize; 73 | uint8 *pTrxBuff; 74 | } TrxMsgBuff; 75 | 76 | typedef enum { 77 | BAUD_RATE_DET, 78 | WAIT_SYNC_FRM, 79 | SRCH_MSG_HEAD, 80 | RCV_MSG_BODY, 81 | RCV_ESC_CHAR, 82 | } RcvMsgState; 83 | 84 | typedef struct { 85 | UartBautRate baut_rate; 86 | UartBitsNum4Char data_bits; 87 | UartExistParity exist_parity; 88 | UartParityMode parity; // chip size in byte 89 | UartStopBitsNum stop_bits; 90 | UartFlowCtrl flow_ctrl; 91 | RcvMsgBuff rcv_buff; 92 | TrxMsgBuff trx_buff; 93 | RcvMsgState rcv_state; 94 | int received; 95 | int buff_uart_no; //indicate which uart use tx/rx buffer 96 | } UartDevice; 97 | 98 | void uart_init(UartBautRate uart0_br, UartBautRate uart1_br); 99 | void uart0_sendStr(const char *str); 100 | 101 | #endif 102 | 103 | -------------------------------------------------------------------------------- /include/driver/uart_register.h.bak: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /include/ds18b20.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | struct sensor_reading *read_ds18b20(void); 4 | bool ds_str(char *buff, int sensornum); 5 | void ds_init(uint32_t polltime); 6 | int readDS(uint8_t *dsaddr); 7 | 8 | struct sensor_reading dsreading[4]; 9 | 10 | extern uint8_t addr[4][8]; 11 | extern uint8_t numds; 12 | -------------------------------------------------------------------------------- /include/esp8266.h: -------------------------------------------------------------------------------- 1 | // Combined include file for esp8266 2 | #ifndef _ESP8266_H_ 3 | #define _ESP8266_H_ 4 | 5 | #undef MEMLEAK_DEBUG 6 | #define USE_OPTIMIZE_PRINTF 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | #include 23 | #include 24 | 25 | #include "espmissingincludes.h" 26 | #include "uart_hw.h" 27 | 28 | #ifdef __WIN32__ 29 | #include <_mingw.h> 30 | #endif 31 | 32 | #endif // _ESP8266_H_ 33 | -------------------------------------------------------------------------------- /include/espfs.h: -------------------------------------------------------------------------------- 1 | #ifndef ESPFS_H 2 | #define ESPFS_H 3 | 4 | 5 | 6 | typedef struct EspFsFile EspFsFile; 7 | 8 | EspFsFile *espFsOpen(char *fileName); 9 | int espFsRead(EspFsFile *fh, char *buff, int len); 10 | void espFsClose(EspFsFile *fh); 11 | 12 | 13 | #endif -------------------------------------------------------------------------------- /include/espmissingincludes-ip.h: -------------------------------------------------------------------------------- 1 | #ifndef ESPMISSINGINCLUDES_IP_H 2 | #define ESPMISSINGINCLUDES_IP_H 3 | 4 | //Missing function prototypes in include folders. Gcc will warn on these if we don't define 'em anywhere. 5 | //MOST OF THESE ARE GUESSED! but they seem to swork and shut up the compiler. 6 | 7 | struct station_info *wifi_softap_get_station_info(); 8 | bool wifi_softap_set_station_info(uint8_t *addr, struct ip_addr *adr); 9 | int igmp_leavegroup(ip_addr_t *host_ip, ip_addr_t *multicast_ip); 10 | int igmp_joingroup(ip_addr_t *host_ip, ip_addr_t *multicast_ip); 11 | void system_station_got_ip_set(ip_addr_t * ip_addr, ip_addr_t *sn_mask, ip_addr_t *gw_addr); 12 | bool wifi_get_ip_info(uint8 if_index, struct ip_info *info); 13 | #endif 14 | -------------------------------------------------------------------------------- /include/espmissingincludes.h: -------------------------------------------------------------------------------- 1 | #ifndef ESPMISSINGINCLUDES_H 2 | #define ESPMISSINGINCLUDES_H 3 | 4 | #include 5 | #include 6 | 7 | // Missing function prototypes in include folders. Gcc will warn on these if we don't define 'em anywhere. 8 | // MOST OF THESE ARE GUESSED! but they seem to swork and shut up the compiler. 9 | typedef struct espconn espconn; 10 | extern void ets_wdt_enable(void); 11 | extern void ets_wdt_disable(void); 12 | extern void wdt_feed(void); 13 | extern void os_intr_unlock(void); 14 | extern void os_intr_lock(void); 15 | int atoi(const char *nptr); 16 | // void ets_install_putc1(void *routine); 17 | // void ets_isr_attach(int intr, void *handler, void *arg); 18 | // void ets_isr_mask(unsigned intr); 19 | // void ets_isr_unmask(unsigned intr); 20 | int ets_memcmp(const void *s1, const void *s2, size_t n); 21 | void *ets_memcpy(void *dest, const void *src, size_t n); 22 | void *ets_memset(void *s, int c, size_t n); 23 | int ets_sprintf(char *str, const char *format, ...) __attribute__((format(printf, 2, 3))); 24 | int ets_str2macaddr(void *, void *); 25 | int ets_strcmp(const char *s1, const char *s2); 26 | char *ets_strcpy(char *dest, const char *src); 27 | // size_t ets_strlen(const char *s); 28 | // int ets_strncmp(const char *s1, const char *s2, int len); 29 | char *ets_strncpy(char *dest, const char *src, size_t n); 30 | char *ets_strstr(const char *haystack, const char *needle); 31 | // void ets_timer_arm_new(ETSTimer *a, int b, int c, int isMstimer); 32 | void ets_timer_disarm(ETSTimer *a); 33 | void ets_timer_setfn(ETSTimer *t, ETSTimerFunc *fn, void *parg); 34 | void ets_update_cpu_frequency(int freqmhz); 35 | int os_printf(const char *format, ...) __attribute__((format(printf, 1, 2))); 36 | int os_snprintf(char *str, size_t size, const char *format, ...) __attribute__((format(printf, 3, 4))); 37 | int os_printf_plus(const char *format, ...) __attribute__((format(printf, 1, 2))); 38 | // void pvPortFree(void *ptr); 39 | // void *pvPortMalloc(size_t xWantedSize); 40 | // void *pvPortZalloc(size_t); 41 | // void uart_div_modify(int no, unsigned int freq); 42 | // void vPortFree(void *ptr); 43 | // void *vPortMalloc(size_t xWantedSize); 44 | uint8 wifi_get_opmode(void); 45 | uint32 system_get_time(); 46 | // int os_random(); 47 | int rand(void); 48 | void ets_bzero(void *s, size_t n); 49 | // void ets_delay_us(long us); 50 | 51 | typedef unsigned char uint8_t; 52 | typedef unsigned short uint16_t; 53 | 54 | #endif 55 | -------------------------------------------------------------------------------- /include/heatshrink_config_httpd.h: -------------------------------------------------------------------------------- 1 | //Heatshrink config for the decompressor. 2 | #ifndef HEATSHRINK_CONFIG_H 3 | #define HEATSHRINK_CONFIG_H 4 | 5 | /* Should functionality assuming dynamic allocation be used? */ 6 | #define HEATSHRINK_DYNAMIC_ALLOC 1 7 | 8 | #if HEATSHRINK_DYNAMIC_ALLOC 9 | /* Optional replacement of malloc/free */ 10 | #define HEATSHRINK_MALLOC(SZ) os_malloc(SZ) 11 | #define HEATSHRINK_FREE(P, SZ) os_free(P) 12 | #else 13 | /* Required parameters for static configuration */ 14 | #define HEATSHRINK_STATIC_INPUT_BUFFER_SIZE 32 15 | #define HEATSHRINK_STATIC_WINDOW_BITS 8 16 | #define HEATSHRINK_STATIC_LOOKAHEAD_BITS 4 17 | #endif 18 | 19 | /* Turn on logging for debugging. */ 20 | #define HEATSHRINK_DEBUGGING_LOGS 0 21 | 22 | /* Use indexing for faster compression. (This requires additional space.) */ 23 | #define HEATSHRINK_USE_INDEX 1 24 | 25 | #endif 26 | 27 | -------------------------------------------------------------------------------- /include/httpclient.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ---------------------------------------------------------------------------- 3 | * "THE BEER-WARE LICENSE" (Revision 42): 4 | * Martin d'Allens wrote this file. As long as you retain 5 | * this notice you can do whatever you want with this stuff. If we meet some day, 6 | * and you think this stuff is worth it, you can buy me a beer in return. 7 | * ---------------------------------------------------------------------------- 8 | */ 9 | 10 | #include 11 | 12 | #ifndef HTTPCLIENT_H 13 | #define HTTPCLIENT_H 14 | 15 | #define HTTP_STATUS_GENERIC_ERROR -1 // In case of TCP or DNS error the callback is called with this status. 16 | #define BUFFER_SIZE_MAX 5000 // Size of http responses that will cause an error. 17 | #include 18 | #include 19 | 20 | /* 21 | * "full_response" is a string containing all response headers and the response body. 22 | * "response_body and "http_status" are extracted from "full_response" for convenience. 23 | * 24 | * A successful request corresponds to an HTTP status code of 200 (OK). 25 | * More info at http://en.wikipedia.org/wiki/List_of_HTTP_status_codes 26 | */ 27 | typedef void (*http_callback)(char *response_body, int http_status, char *full_response); 28 | 29 | /* 30 | * Download a web page from its URL. 31 | * Try: 32 | * http_get("http://wtfismyip.com/text", http_callback_example); 33 | */ 34 | void ICACHE_FLASH_ATTR http_get(const char *url, http_callback user_callback); 35 | 36 | /* 37 | * Post data to a web form. 38 | * The data should be encoded as application/x-www-form-urlencoded. 39 | * Try: 40 | * http_post("http://httpbin.org/post", "first_word=hello&second_word=world", http_callback_example); 41 | */ 42 | void ICACHE_FLASH_ATTR http_post(const char *url, const char *post_data, http_callback user_callback); 43 | 44 | /* 45 | * Call this function to skip URL parsing if the arguments are already in separate variables. 46 | */ 47 | void ICACHE_FLASH_ATTR http_raw_request(const char *hostname, int port, const char *path, const char *post_data, 48 | http_callback user_callback); 49 | 50 | /* 51 | * Output on the UART. 52 | */ 53 | void http_callback_example(char *response, int http_status, char *full_response); 54 | 55 | #endif 56 | -------------------------------------------------------------------------------- /include/httpd.h: -------------------------------------------------------------------------------- 1 | #ifndef HTTPD_H 2 | #define HTTPD_H 3 | #include "lwip/ip_addr.h" 4 | #include 5 | #include 6 | 7 | #define HTTPDVER "0.3" 8 | 9 | #define HTTPD_CGI_MORE 0 10 | #define HTTPD_CGI_DONE 1 11 | #define HTTPD_CGI_NOTFOUND 2 12 | #define HTTPD_CGI_AUTHENTICATED 3 13 | 14 | #define HTTPD_METHOD_GET 1 15 | #define HTTPD_METHOD_POST 2 16 | 17 | typedef struct HttpdPriv HttpdPriv; 18 | typedef struct HttpdConnData HttpdConnData; 19 | typedef struct HttpdPostData HttpdPostData; 20 | 21 | typedef int (*cgiSendCallback)(HttpdConnData *connData); 22 | 23 | // A struct describing a http connection. This gets passed to cgi functions. 24 | struct HttpdConnData { 25 | struct espconn *conn; 26 | char requestType; 27 | char *url; 28 | char *getArgs; 29 | const void *cgiArg; 30 | void *cgiData; 31 | void *cgiPrivData; // Used for streaming handlers storing state between requests 32 | HttpdPriv *priv; 33 | cgiSendCallback cgi; 34 | HttpdPostData *post; 35 | }; 36 | 37 | // A struct describing the POST data sent inside the http connection. This is used by the CGI functions 38 | struct HttpdPostData { 39 | int len; // POST Content-Length 40 | int buffSize; // The maximum length of the post buffer 41 | int buffLen; // The amount of bytes in the current post buffer 42 | int received; // The total amount of bytes received so far 43 | char *buff; // Actual POST data buffer 44 | char *multipartBoundary; 45 | }; 46 | 47 | // A struct describing an url. This is the main struct that's used to send different URL requests to 48 | // different routines. 49 | typedef struct { 50 | const char *url; 51 | cgiSendCallback cgiCb; 52 | const void *cgiArg; 53 | } HttpdBuiltInUrl; 54 | 55 | int ICACHE_FLASH_ATTR cgiRedirect(HttpdConnData *connData); 56 | void ICACHE_FLASH_ATTR httpdRedirect(HttpdConnData *conn, char *newUrl); 57 | int httpdUrlDecode(char *val, int valLen, char *ret, int retLen); 58 | int ICACHE_FLASH_ATTR httpdFindArg(char *line, char *arg, char *buff, int buffLen); 59 | void ICACHE_FLASH_ATTR httpdInit(HttpdBuiltInUrl *fixedUrls, int port); 60 | const char *httpdGetMimetype(char *url); 61 | #ifdef GZIP_COMPRESSION 62 | const char *sendGZIPEncodingIfNeeded(HttpdConnData *connData); 63 | #endif 64 | void ICACHE_FLASH_ATTR httpdStartResponse(HttpdConnData *conn, int code); 65 | void ICACHE_FLASH_ATTR httpdHeader(HttpdConnData *conn, const char *field, const char *val); 66 | void ICACHE_FLASH_ATTR httpdEndHeaders(HttpdConnData *conn); 67 | int ICACHE_FLASH_ATTR httpdGetHeader(HttpdConnData *conn, char *header, char *ret, int retLen); 68 | int ICACHE_FLASH_ATTR httpdSend(HttpdConnData *conn, const char *data, int len); 69 | 70 | #endif -------------------------------------------------------------------------------- /include/httpdconfig.h: -------------------------------------------------------------------------------- 1 | 2 | // Define this if you want to be able to use Heatshrink-compressed espfs images. 3 | #define EFS_HEATSHRINK 4 | 5 | // Pos of esp fs in flash 6 | //#define ESPFS_POS 0x12000 7 | #define ESPFS_POS 0x50000 8 | 9 | // If you want, you can define a realm for the authentication system. 10 | #define HTTP_AUTH_REALM "WiFi Relay Board" 11 | -------------------------------------------------------------------------------- /include/httpdespfs.h: -------------------------------------------------------------------------------- 1 | #ifndef HTTPDESPFS_H 2 | #define HTTPDESPFS_H 3 | 4 | #include "httpd.h" 5 | #include "espfs.h" 6 | 7 | int cgiEspFsHook(HttpdConnData *connData); 8 | int ICACHE_FLASH_ATTR cgiEspFsTemplate(HttpdConnData *connData); 9 | 10 | #endif -------------------------------------------------------------------------------- /include/io.h: -------------------------------------------------------------------------------- 1 | void ICACHE_FLASH_ATTR ioGPIO(int ena, int gpio); 2 | void ICACHE_FLASH_ATTR relayOnOff(int onOff, int relayNumber); 3 | 4 | void ioInit(void); 5 | extern char relay1State; 6 | extern char relay2State; 7 | extern char relay3State; -------------------------------------------------------------------------------- /include/ip_addr.bak: -------------------------------------------------------------------------------- 1 | //Dummy file to keep the file in the SDK from b0rking things up 2 | #include "lwip/ip_addr.h" -------------------------------------------------------------------------------- /include/jsmn.h: -------------------------------------------------------------------------------- 1 | #ifndef __JSMN_H_ 2 | #define __JSMN_H_ 3 | 4 | #include 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | /** 11 | * JSON type identifier. Basic types are: 12 | * o Object 13 | * o Array 14 | * o String 15 | * o Other primitive: number, boolean (true/false) or null 16 | */ 17 | typedef enum { 18 | JSMN_PRIMITIVE = 0, 19 | JSMN_OBJECT = 1, 20 | JSMN_ARRAY = 2, 21 | JSMN_STRING = 3 22 | } jsmntype_t; 23 | 24 | typedef enum { 25 | /* Not enough tokens were provided */ 26 | JSMN_ERROR_NOMEM = -1, 27 | /* Invalid character inside JSON string */ 28 | JSMN_ERROR_INVAL = -2, 29 | /* The string is not a full JSON packet, more bytes expected */ 30 | JSMN_ERROR_PART = -3 31 | } jsmnerr_t; 32 | 33 | /** 34 | * JSON token description. 35 | * @param type type (object, array, string etc.) 36 | * @param start start position in JSON data string 37 | * @param end end position in JSON data string 38 | */ 39 | typedef struct { 40 | jsmntype_t type; 41 | int start; 42 | int end; 43 | int size; 44 | #ifdef JSMN_PARENT_LINKS 45 | int parent; 46 | #endif 47 | } jsmntok_t; 48 | 49 | /** 50 | * JSON parser. Contains an array of token blocks available. Also stores 51 | * the string being parsed now and current position in that string 52 | */ 53 | typedef struct { 54 | unsigned int pos; /* offset in the JSON string */ 55 | unsigned int toknext; /* next token to allocate */ 56 | int toksuper; /* superior token node, e.g parent object or array */ 57 | } jsmn_parser; 58 | 59 | /** 60 | * Create JSON parser over an array of tokens 61 | */ 62 | void jsmn_init(jsmn_parser *parser); 63 | 64 | /** 65 | * Run JSON parser. It parses a JSON data string into and array of tokens, each describing 66 | * a single JSON object. 67 | */ 68 | jsmnerr_t jsmn_parse(jsmn_parser *parser, const char *js, size_t len, 69 | jsmntok_t *tokens, unsigned int num_tokens); 70 | 71 | #ifdef __cplusplus 72 | } 73 | #endif 74 | 75 | #endif /* __JSMN_H_ */ 76 | -------------------------------------------------------------------------------- /include/mem_manager.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mharizanov/ESP8266_Relay_Board/bb58eb2f41fc9a136600907f62672e4673c06658/include/mem_manager.h -------------------------------------------------------------------------------- /include/mqtt.h: -------------------------------------------------------------------------------- 1 | /* mqtt.h 2 | * 3 | * Copyright (c) 2014-2015, Tuan PM 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * 9 | * * Redistributions of source code must retain the above copyright notice, 10 | * this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * * Neither the name of Redis nor the names of its contributors may be used 15 | * to endorse or promote products derived from this software without 16 | * specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 22 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | * POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | #ifndef USER_AT_MQTT_H_ 31 | #define USER_AT_MQTT_H_ 32 | 33 | #include "mqtt_msg.h" 34 | #include "user_interface.h" 35 | #include 36 | 37 | #include "mqueue.h" 38 | 39 | // Temperature reading recieved via MQTT (used for thermostat if configured) 40 | extern int mqttTreading; 41 | // Timestamp when reading was received 42 | extern time_t mqttTreadingTS; 43 | 44 | typedef struct mqtt_event_data_t { 45 | uint8_t type; 46 | const char *topic; 47 | const char *data; 48 | uint16_t topic_length; 49 | uint16_t data_length; 50 | uint16_t data_offset; 51 | } mqtt_event_data_t; 52 | 53 | typedef struct mqtt_state_t { 54 | uint16_t port; 55 | int auto_reconnect; 56 | mqtt_connect_info_t *connect_info; 57 | uint8_t *in_buffer; 58 | uint8_t *out_buffer; 59 | int in_buffer_length; 60 | int out_buffer_length; 61 | uint16_t message_length; 62 | uint16_t message_length_read; 63 | mqtt_message_t *outbound_message; 64 | mqtt_connection_t mqtt_connection; 65 | uint16_t pending_msg_id; 66 | int pending_msg_type; 67 | int pending_publish_qos; 68 | } mqtt_state_t; 69 | 70 | typedef enum { 71 | WIFI_INIT, 72 | WIFI_CONNECTING, 73 | WIFI_CONNECTING_ERROR, 74 | WIFI_CONNECTED, 75 | DNS_RESOLVE, 76 | TCP_DISCONNECTED, 77 | TCP_RECONNECT_REQ, 78 | TCP_RECONNECT, 79 | TCP_CONNECTING, 80 | TCP_CONNECTING_ERROR, 81 | TCP_CONNECTED, 82 | MQTT_CONNECT_SEND, 83 | MQTT_CONNECT_SENDING, 84 | MQTT_SUBSCIBE_SEND, 85 | MQTT_SUBSCIBE_SENDING, 86 | MQTT_DATA, 87 | MQTT_PUBLISH_RECV, 88 | MQTT_PUBLISHING 89 | } tConnState; 90 | 91 | typedef void (*MqttCallback)(uint32_t *args); 92 | typedef void (*MqttDataCallback)(uint32_t *args, const char *topic, uint32_t topic_len, const char *data, 93 | uint32_t lengh); 94 | 95 | typedef struct { 96 | struct espconn *pCon; 97 | uint8_t security; 98 | uint8_t *host; 99 | uint32_t port; 100 | ip_addr_t ip; 101 | mqtt_state_t mqtt_state; 102 | mqtt_connect_info_t connect_info; 103 | MqttCallback connectedCb; 104 | MqttCallback disconnectedCb; 105 | MqttCallback publishedCb; 106 | MqttDataCallback dataCb; 107 | ETSTimer mqttTimer; 108 | uint32_t keepAliveTick; 109 | uint32_t reconnectTick; 110 | uint32_t sendTimeout; 111 | tConnState connState; 112 | QUEUE msgQueue; 113 | } MQTT_Client; 114 | 115 | #define SEC_NONSSL 0 116 | #define SEC_SSL 1 117 | 118 | #define MQTT_FLAG_CONNECTED 1 119 | #define MQTT_FLAG_READY 2 120 | #define MQTT_FLAG_EXIT 4 121 | 122 | #define MQTT_EVENT_TYPE_NONE 0 123 | #define MQTT_EVENT_TYPE_CONNECTED 1 124 | #define MQTT_EVENT_TYPE_DISCONNECTED 2 125 | #define MQTT_EVENT_TYPE_SUBSCRIBED 3 126 | #define MQTT_EVENT_TYPE_UNSUBSCRIBED 4 127 | #define MQTT_EVENT_TYPE_PUBLISH 5 128 | #define MQTT_EVENT_TYPE_PUBLISHED 6 129 | #define MQTT_EVENT_TYPE_EXITED 7 130 | #define MQTT_EVENT_TYPE_PUBLISH_CONTINUATION 8 131 | 132 | void ICACHE_FLASH_ATTR MQTT_InitConnection(MQTT_Client *mqttClient, uint8_t *host, uint32 port, uint8_t security); 133 | void ICACHE_FLASH_ATTR MQTT_InitClient(MQTT_Client *mqttClient, uint8_t *client_id, uint8_t *client_user, 134 | uint8_t *client_pass, uint32_t keepAliveTime, uint8_t cleanSession); 135 | void ICACHE_FLASH_ATTR MQTT_InitLWT(MQTT_Client *mqttClient, uint8_t *will_topic, uint8_t *will_msg, uint8_t will_qos, 136 | uint8_t will_retain); 137 | void ICACHE_FLASH_ATTR MQTT_OnConnected(MQTT_Client *mqttClient, MqttCallback connectedCb); 138 | void ICACHE_FLASH_ATTR MQTT_OnDisconnected(MQTT_Client *mqttClient, MqttCallback disconnectedCb); 139 | void ICACHE_FLASH_ATTR MQTT_OnPublished(MQTT_Client *mqttClient, MqttCallback publishedCb); 140 | void ICACHE_FLASH_ATTR MQTT_OnData(MQTT_Client *mqttClient, MqttDataCallback dataCb); 141 | BOOL ICACHE_FLASH_ATTR MQTT_Subscribe(MQTT_Client *client, char *topic, uint8_t qos); 142 | void ICACHE_FLASH_ATTR MQTT_Connect(MQTT_Client *mqttClient); 143 | void ICACHE_FLASH_ATTR MQTT_Disconnect(MQTT_Client *mqttClient); 144 | BOOL ICACHE_FLASH_ATTR MQTT_Publish(MQTT_Client *client, const char *topic, const char *data, int data_length, int qos, 145 | int retain); 146 | 147 | #endif /* USER_AT_MQTT_H_ */ 148 | -------------------------------------------------------------------------------- /include/mqtt_msg.h: -------------------------------------------------------------------------------- 1 | /* 2 | * File: mqtt_msg.h 3 | * Author: Minh Tuan 4 | * 5 | * Created on July 12, 2014, 1:05 PM 6 | */ 7 | 8 | #ifndef MQTT_MSG_H 9 | #define MQTT_MSG_H 10 | #include "c_types.h" 11 | #ifdef __cplusplus 12 | extern "C" { 13 | #endif 14 | 15 | /* 16 | * Copyright (c) 2014, Stephen Robinson 17 | * All rights reserved. 18 | * 19 | * Redistribution and use in source and binary forms, with or without 20 | * modification, are permitted provided that the following conditions 21 | * are met: 22 | * 23 | * 1. Redistributions of source code must retain the above copyright 24 | * notice, this list of conditions and the following disclaimer. 25 | * 2. Redistributions in binary form must reproduce the above copyright 26 | * notice, this list of conditions and the following disclaimer in the 27 | * documentation and/or other materials provided with the distribution. 28 | * 3. Neither the name of the copyright holder nor the names of its 29 | * contributors may be used to endorse or promote products derived 30 | * from this software without specific prior written permission. 31 | * 32 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 33 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 34 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 35 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 36 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 37 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 38 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 39 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 40 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 41 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 42 | * POSSIBILITY OF SUCH DAMAGE. 43 | * 44 | */ 45 | 46 | /* 7 6 5 4 3 2 1 0*/ 47 | /*| --- Message Type---- | DUP Flag | QoS Level | Retain | */ 48 | /* Remaining Length */ 49 | 50 | 51 | enum mqtt_message_type 52 | { 53 | MQTT_MSG_TYPE_CONNECT = 1, 54 | MQTT_MSG_TYPE_CONNACK = 2, 55 | MQTT_MSG_TYPE_PUBLISH = 3, 56 | MQTT_MSG_TYPE_PUBACK = 4, 57 | MQTT_MSG_TYPE_PUBREC = 5, 58 | MQTT_MSG_TYPE_PUBREL = 6, 59 | MQTT_MSG_TYPE_PUBCOMP = 7, 60 | MQTT_MSG_TYPE_SUBSCRIBE = 8, 61 | MQTT_MSG_TYPE_SUBACK = 9, 62 | MQTT_MSG_TYPE_UNSUBSCRIBE = 10, 63 | MQTT_MSG_TYPE_UNSUBACK = 11, 64 | MQTT_MSG_TYPE_PINGREQ = 12, 65 | MQTT_MSG_TYPE_PINGRESP = 13, 66 | MQTT_MSG_TYPE_DISCONNECT = 14 67 | }; 68 | 69 | typedef struct mqtt_message 70 | { 71 | uint8_t* data; 72 | uint16_t length; 73 | 74 | } mqtt_message_t; 75 | 76 | typedef struct mqtt_connection 77 | { 78 | mqtt_message_t message; 79 | 80 | uint16_t message_id; 81 | uint8_t* buffer; 82 | uint16_t buffer_length; 83 | 84 | } mqtt_connection_t; 85 | 86 | typedef struct mqtt_connect_info 87 | { 88 | char* client_id; 89 | char* username; 90 | char* password; 91 | char* will_topic; 92 | char* will_message; 93 | int keepalive; 94 | int will_qos; 95 | int will_retain; 96 | int clean_session; 97 | 98 | } mqtt_connect_info_t; 99 | 100 | 101 | static inline int ICACHE_FLASH_ATTR mqtt_get_type(uint8_t* buffer) { return (buffer[0] & 0xf0) >> 4; } 102 | static inline int ICACHE_FLASH_ATTR mqtt_get_dup(uint8_t* buffer) { return (buffer[0] & 0x08) >> 3; } 103 | static inline int ICACHE_FLASH_ATTR mqtt_get_qos(uint8_t* buffer) { return (buffer[0] & 0x06) >> 1; } 104 | static inline int ICACHE_FLASH_ATTR mqtt_get_retain(uint8_t* buffer) { return (buffer[0] & 0x01); } 105 | 106 | void ICACHE_FLASH_ATTR mqtt_msg_init(mqtt_connection_t* connection, uint8_t* buffer, uint16_t buffer_length); 107 | int ICACHE_FLASH_ATTR mqtt_get_total_length(uint8_t* buffer, uint16_t length); 108 | const char* ICACHE_FLASH_ATTR mqtt_get_publish_topic(uint8_t* buffer, uint16_t* length); 109 | const char* ICACHE_FLASH_ATTR mqtt_get_publish_data(uint8_t* buffer, uint16_t* length); 110 | uint16_t ICACHE_FLASH_ATTR mqtt_get_id(uint8_t* buffer, uint16_t length); 111 | 112 | mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_connect(mqtt_connection_t* connection, mqtt_connect_info_t* info); 113 | mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_publish(mqtt_connection_t* connection, const char* topic, const char* data, int data_length, int qos, int retain, uint16_t* message_id); 114 | mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_puback(mqtt_connection_t* connection, uint16_t message_id); 115 | mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_pubrec(mqtt_connection_t* connection, uint16_t message_id); 116 | mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_pubrel(mqtt_connection_t* connection, uint16_t message_id); 117 | mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_pubcomp(mqtt_connection_t* connection, uint16_t message_id); 118 | mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_subscribe(mqtt_connection_t* connection, const char* topic, int qos, uint16_t* message_id); 119 | mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_unsubscribe(mqtt_connection_t* connection, const char* topic, uint16_t* message_id); 120 | mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_pingreq(mqtt_connection_t* connection); 121 | mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_pingresp(mqtt_connection_t* connection); 122 | mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_disconnect(mqtt_connection_t* connection); 123 | 124 | 125 | #ifdef __cplusplus 126 | } 127 | #endif 128 | 129 | #endif /* MQTT_MSG_H */ 130 | 131 | -------------------------------------------------------------------------------- /include/mqueue.h: -------------------------------------------------------------------------------- 1 | /* str_queue.h -- 2 | * 3 | * Copyright (c) 2014-2015, Tuan PM 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * 9 | * * Redistributions of source code must retain the above copyright notice, 10 | * this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * * Neither the name of Redis nor the names of its contributors may be used 15 | * to endorse or promote products derived from this software without 16 | * specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 22 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | * POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | #ifndef USER_QUEUE_H_ 32 | #define USER_QUEUE_H_ 33 | #include "os_type.h" 34 | #include "ringbuf.h" 35 | typedef struct { 36 | uint8_t *buf; 37 | RINGBUF rb; 38 | } QUEUE; 39 | 40 | void ICACHE_FLASH_ATTR QUEUE_Init(QUEUE *queue, int bufferSize); 41 | int32_t ICACHE_FLASH_ATTR QUEUE_Puts(QUEUE *queue, uint8_t* buffer, uint16_t len); 42 | int32_t ICACHE_FLASH_ATTR QUEUE_Gets(QUEUE *queue, uint8_t* buffer, uint16_t* len, uint16_t maxLen); 43 | BOOL ICACHE_FLASH_ATTR QUEUE_IsEmpty(QUEUE *queue); 44 | #endif /* USER_QUEUE_H_ */ 45 | -------------------------------------------------------------------------------- /include/netbios.h: -------------------------------------------------------------------------------- 1 | #ifndef __NETBIOS_H__ 2 | #define __NETBIOS_H__ 3 | 4 | #include "user_interface.h" 5 | 6 | extern char netbios_name[17]; 7 | 8 | void netbios_init(void); 9 | 10 | #endif /* __NETBIOS_H__ */ 11 | -------------------------------------------------------------------------------- /include/netif/if_llc.h: -------------------------------------------------------------------------------- 1 | /* $NetBSD: if_llc.h,v 1.12 1999/11/19 20:41:19 thorpej Exp $ */ 2 | 3 | /*- 4 | * Copyright (c) 1988, 1993 5 | * The Regents of the University of California. All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions 9 | * are met: 10 | * 1. Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 4. Neither the name of the University nor the names of its contributors 16 | * may be used to endorse or promote products derived from this software 17 | * without specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 | * SUCH DAMAGE. 30 | * 31 | * @(#)if_llc.h 8.1 (Berkeley) 6/10/93 32 | * $FreeBSD$ 33 | */ 34 | 35 | #ifndef _NET_IF_LLC_H_ 36 | #define _NET_IF_LLC_H_ 37 | 38 | /* 39 | * IEEE 802.2 Link Level Control headers, for use in conjunction with 40 | * 802.{3,4,5} media access control methods. 41 | * 42 | * Headers here do not use bit fields due to shortcommings in many 43 | * compilers. 44 | */ 45 | 46 | struct llc { 47 | uint8_t llc_dsap; 48 | uint8_t llc_ssap; 49 | union { 50 | struct { 51 | uint8_t control; 52 | uint8_t format_id; 53 | uint8_t class; 54 | uint8_t window_x2; 55 | } __packed type_u; 56 | struct { 57 | uint8_t num_snd_x2; 58 | uint8_t num_rcv_x2; 59 | } __packed type_i; 60 | struct { 61 | uint8_t control; 62 | uint8_t num_rcv_x2; 63 | } __packed type_s; 64 | struct { 65 | uint8_t control; 66 | /* 67 | * We cannot put the following fields in a structure because 68 | * the structure rounding might cause padding. 69 | */ 70 | uint8_t frmr_rej_pdu0; 71 | uint8_t frmr_rej_pdu1; 72 | uint8_t frmr_control; 73 | uint8_t frmr_control_ext; 74 | uint8_t frmr_cause; 75 | } __packed type_frmr; 76 | struct { 77 | uint8_t control; 78 | uint8_t org_code[3]; 79 | uint16_t ether_type; 80 | } __packed type_snap; 81 | struct { 82 | uint8_t control; 83 | uint8_t control_ext; 84 | } __packed type_raw; 85 | } __packed llc_un; 86 | } __packed; 87 | 88 | struct frmrinfo { 89 | uint8_t frmr_rej_pdu0; 90 | uint8_t frmr_rej_pdu1; 91 | uint8_t frmr_control; 92 | uint8_t frmr_control_ext; 93 | uint8_t frmr_cause; 94 | } __packed; 95 | 96 | #define llc_control llc_un.type_u.control 97 | #define llc_control_ext llc_un.type_raw.control_ext 98 | #define llc_fid llc_un.type_u.format_id 99 | #define llc_class llc_un.type_u.class 100 | #define llc_window llc_un.type_u.window_x2 101 | #define llc_frmrinfo llc_un.type_frmr.frmr_rej_pdu0 102 | #define llc_frmr_pdu0 llc_un.type_frmr.frmr_rej_pdu0 103 | #define llc_frmr_pdu1 llc_un.type_frmr.frmr_rej_pdu1 104 | #define llc_frmr_control llc_un.type_frmr.frmr_control 105 | #define llc_frmr_control_ext llc_un.type_frmr.frmr_control_ext 106 | #define llc_frmr_cause llc_un.type_frmr.frmr_cause 107 | #define llc_snap llc_un.type_snap 108 | 109 | /* 110 | * Don't use sizeof(struct llc_un) for LLC header sizes 111 | */ 112 | #define LLC_ISFRAMELEN 4 113 | #define LLC_UFRAMELEN 3 114 | #define LLC_FRMRLEN 7 115 | #define LLC_SNAPFRAMELEN 8 116 | 117 | #ifdef CTASSERT 118 | CTASSERT(sizeof (struct llc) == LLC_SNAPFRAMELEN); 119 | #endif 120 | 121 | /* 122 | * Unnumbered LLC format commands 123 | */ 124 | #define LLC_UI 0x3 125 | #define LLC_UI_P 0x13 126 | #define LLC_DISC 0x43 127 | #define LLC_DISC_P 0x53 128 | #define LLC_UA 0x63 129 | #define LLC_UA_P 0x73 130 | #define LLC_TEST 0xe3 131 | #define LLC_TEST_P 0xf3 132 | #define LLC_FRMR 0x87 133 | #define LLC_FRMR_P 0x97 134 | #define LLC_DM 0x0f 135 | #define LLC_DM_P 0x1f 136 | #define LLC_XID 0xaf 137 | #define LLC_XID_P 0xbf 138 | #define LLC_SABME 0x6f 139 | #define LLC_SABME_P 0x7f 140 | 141 | /* 142 | * Supervisory LLC commands 143 | */ 144 | #define LLC_RR 0x01 145 | #define LLC_RNR 0x05 146 | #define LLC_REJ 0x09 147 | 148 | /* 149 | * Info format - dummy only 150 | */ 151 | #define LLC_INFO 0x00 152 | 153 | /* 154 | * ISO PDTR 10178 contains among others 155 | */ 156 | #define LLC_8021D_LSAP 0x42 157 | #define LLC_X25_LSAP 0x7e 158 | #define LLC_SNAP_LSAP 0xaa 159 | #define LLC_ISO_LSAP 0xfe 160 | 161 | #define RFC1042_LEN 6 162 | #define RFC1042 {0xAA, 0xAA, 0x03, 0x00, 0x00, 0x00} 163 | #define ETHERNET_TUNNEL {0xAA, 0xAA, 0x03, 0x00, 0x00, 0xF8} 164 | 165 | /* 166 | * copied from sys/net/ethernet.h 167 | */ 168 | #define ETHERTYPE_AARP 0x80F3 /* AppleTalk AARP */ 169 | #define ETHERTYPE_IPX 0x8137 /* Novell (old) NetWare IPX (ECONFIG E option) */ 170 | 171 | 172 | 173 | #endif /* _NET_IF_LLC_H_ */ 174 | -------------------------------------------------------------------------------- /include/netif/wlan_lwip_if.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2010-2011 Espressif System 3 | * 4 | */ 5 | 6 | #ifndef _WLAN_LWIP_IF_H_ 7 | #define _WLAN_LWIP_IF_H_ 8 | 9 | #define LWIP_IF0_PRIO 28 10 | #define LWIP_IF1_PRIO 29 11 | 12 | enum { 13 | SIG_LWIP_RX = 0, 14 | }; 15 | 16 | struct netif * eagle_lwip_if_alloc(struct ieee80211_conn *conn, const uint8 *macaddr, struct ip_info *info); 17 | struct netif * eagle_lwip_getif(uint8 index); 18 | 19 | #ifndef IOT_SIP_MODE 20 | sint8 ieee80211_output_pbuf(struct netif *ifp, struct pbuf* pb); 21 | #else 22 | sint8 ieee80211_output_pbuf(struct ieee80211_conn *conn, esf_buf *eb); 23 | #endif 24 | 25 | #endif /* _WLAN_LWIP_IF_H_ */ 26 | -------------------------------------------------------------------------------- /include/proto.h: -------------------------------------------------------------------------------- 1 | /* 2 | * File: proto.h 3 | * Author: ThuHien 4 | * 5 | * Created on November 23, 2012, 8:57 AM 6 | */ 7 | 8 | #ifndef _PROTO_H_ 9 | #define _PROTO_H_ 10 | #include 11 | #include "typedef.h" 12 | #include "ringbuf.h" 13 | 14 | typedef void(PROTO_PARSE_CALLBACK)(); 15 | 16 | typedef struct{ 17 | U8 *buf; 18 | U16 bufSize; 19 | U16 dataLen; 20 | U8 isEsc; 21 | U8 isBegin; 22 | PROTO_PARSE_CALLBACK* callback; 23 | }PROTO_PARSER; 24 | 25 | I8 PROTO_Init(PROTO_PARSER *parser, PROTO_PARSE_CALLBACK *completeCallback, U8 *buf, U16 bufSize); 26 | I8 PROTO_Parse(PROTO_PARSER *parser, U8 *buf, U16 len); 27 | I16 PROTO_Add(U8 *buf, const U8 *packet, I16 bufSize); 28 | I16 PROTO_AddRb(RINGBUF *rb, const U8 *packet, I16 len); 29 | I8 PROTO_ParseByte(PROTO_PARSER *parser, U8 value); 30 | I16 PROTO_ParseRb(RINGBUF *rb, U8 *bufOut, U16* len, U16 maxBufLen); 31 | #endif 32 | 33 | -------------------------------------------------------------------------------- /include/pwm.h: -------------------------------------------------------------------------------- 1 | #ifndef __PWM_H__ 2 | #define __PWM_H__ 3 | 4 | // see eagle_soc.h for these definitions 5 | /* 6 | #define PWM_0_OUT_IO_MUX PERIPHS_IO_MUX_MTMS_U 7 | #define PWM_0_OUT_IO_NUM 14 8 | #define PWM_0_OUT_IO_FUNC FUNC_GPIO14 9 | */ 10 | 11 | #define PWM_0_OUT_IO_MUX PERIPHS_IO_MUX_MTDO_U 12 | #define PWM_0_OUT_IO_NUM 15 13 | #define PWM_0_OUT_IO_FUNC FUNC_GPIO15 14 | 15 | #define PWM_CHANNEL 1 16 | 17 | 18 | struct pwm_single_param { 19 | uint16 gpio_set; 20 | uint16 gpio_clear; 21 | uint16 h_time; 22 | }; 23 | 24 | struct pwm_param { 25 | uint16 period; 26 | uint16 freq; 27 | uint8 duty[PWM_CHANNEL]; 28 | }; 29 | 30 | #define PWM_DEPTH 255 31 | #define PWM_1S 1000000 32 | 33 | uint8_t duty; 34 | 35 | void pwm_init(uint16 freq, uint8 *duty); 36 | void pwm_start(void); 37 | 38 | void pwm_set_duty(uint8 duty, uint8 channel); 39 | uint8 pwm_get_duty(uint8 channel); 40 | void pwm_set_freq(uint16 freq); 41 | uint16 pwm_get_freq(void); 42 | #endif 43 | 44 | -------------------------------------------------------------------------------- /include/ringbuf.h: -------------------------------------------------------------------------------- 1 | #ifndef _RING_BUF_H_ 2 | #define _RING_BUF_H_ 3 | 4 | #include 5 | #include 6 | #include "typedef.h" 7 | 8 | typedef struct{ 9 | U8* p_o; /**< Original pointer */ 10 | U8* volatile p_r; /**< Read pointer */ 11 | U8* volatile p_w; /**< Write pointer */ 12 | volatile I32 fill_cnt; /**< Number of filled slots */ 13 | I32 size; /**< Buffer size */ 14 | }RINGBUF; 15 | 16 | I16 RINGBUF_Init(RINGBUF *r, U8* buf, I32 size); 17 | I16 RINGBUF_Put(RINGBUF *r, U8 c); 18 | I16 RINGBUF_Get(RINGBUF *r, U8* c); 19 | #endif 20 | -------------------------------------------------------------------------------- /include/sntp.h.bak: -------------------------------------------------------------------------------- 1 | #ifndef __SNTP_H__ 2 | #define __SNTP_H__ 3 | 4 | #include "lwip/ip_addr.h" 5 | #ifdef __cplusplus 6 | extern "C" { 7 | #endif 8 | 9 | #include 10 | extern time_t sntp_time; 11 | extern int sntp_tz; 12 | 13 | // void sntp_init(int tz); 14 | // void sntp_stop(void); 15 | 16 | extern void sntp_send_request(ip_addr_t *server_addr); 17 | extern void sntp_request(void *arg); 18 | 19 | #ifdef __cplusplus 20 | } 21 | #endif 22 | 23 | #endif /* __SNTP_H__ */ 24 | -------------------------------------------------------------------------------- /include/stdint.h: -------------------------------------------------------------------------------- 1 | 2 | //Including the system-wide stdint.h messes stuff up... but I don't want to change heatshrink 3 | //not to do it. Including this dummy file fixes it too, tho'. 4 | 5 | #ifndef __ets__ 6 | //Do include stdint for testing builds. 7 | #include_next 8 | #endif -------------------------------------------------------------------------------- /include/stdint.h.bak: -------------------------------------------------------------------------------- 1 | 2 | //Including the system-wide stdint.h messes stuff up... but I don't want to change heatshrink 3 | //not to do it. Including this dummy file fixes it too, tho'. 4 | 5 | #ifndef __ets__ 6 | //Do include stdint for testing builds. 7 | #include_next 8 | #endif -------------------------------------------------------------------------------- /include/stdout.h: -------------------------------------------------------------------------------- 1 | void stdoutInit(); 2 | 3 | // Temperature reading timestamp (used for thermostat if configured) 4 | extern time_t serialTreadingTS; 5 | extern int serialTreading; 6 | extern char *userJSON[250]; 7 | // Temperature reading timestamp (used for MQTT publishing if configured) 8 | extern time_t userJSONreadingTS; 9 | -------------------------------------------------------------------------------- /include/syslog.h: -------------------------------------------------------------------------------- 1 | // ets_vprintf(write_mychar, s, args); 2 | 3 | // extern void syslog(char *msgtosend); 4 | 5 | extern void syslog(const char *format, ...); 6 | 7 | #define DBG(format, ...) \ 8 | do { \ 9 | syslog(format, ##__VA_ARGS__); \ 10 | os_printf(format, ##__VA_ARGS__); \ 11 | } while (0) 12 | -------------------------------------------------------------------------------- /include/thermostat.h: -------------------------------------------------------------------------------- 1 | #include "os_type.h" 2 | #include 3 | 4 | void thermostat_init(uint32_t polltime); 5 | void thermostatRelayOn(void); 6 | void thermostatRelayOff(void); 7 | extern int getRoomTemp(); 8 | extern time_t thermostatRelayOffTime; 9 | extern int thermostat1ScheduleSetPoint; 10 | extern int thermostat1CurrentSetPoint; 11 | extern int thermostatRelayActive; // set to 1 if any thermostat controlled relay are on 12 | -------------------------------------------------------------------------------- /include/time_utils.h: -------------------------------------------------------------------------------- 1 | #ifndef __TIME_UTILS_H 2 | #define __TIME_UTILS_H 3 | 4 | char *epoch_to_str(unsigned long epoch); 5 | char *epoch_to_str_hhmm(unsigned long epoch); 6 | 7 | int get_month(unsigned long *t, int year); 8 | int get_year(unsigned long *t); 9 | int wd(int year, int month, int day); 10 | uint64 get_current_timestamp_dst(); 11 | bool IsDST_EU(int day, int month, int dow); 12 | bool IsDST_NA(int day, int month, int dow); 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /include/typedef.h: -------------------------------------------------------------------------------- 1 | /** 2 | * \file 3 | * Standard Types definition 4 | */ 5 | 6 | #ifndef _TYPE_DEF_H_ 7 | #define _TYPE_DEF_H_ 8 | 9 | typedef char I8; 10 | typedef unsigned char U8; 11 | typedef short I16; 12 | typedef unsigned short U16; 13 | typedef long I32; 14 | typedef unsigned long U32; 15 | typedef unsigned long long U64; 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /include/upgrade.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ESPRESSIF MIT License 3 | * 4 | * Copyright (c) 2016 5 | * 6 | * Permission is hereby granted for use on ESPRESSIF SYSTEMS ESP8266 only, in which case, 7 | * it is free of charge, to any person obtaining a copy of this software and associated 8 | * documentation files (the "Software"), to deal in the Software without restriction, including 9 | * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 | * and/or sell copies of the Software, and to permit persons to whom the Software is furnished 11 | * to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all copies or 14 | * substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 18 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 19 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | * 23 | */ 24 | 25 | #ifndef __UPGRADE_H__ 26 | #define __UPGRADE_H__ 27 | 28 | #define SPI_FLASH_SEC_SIZE 4096 29 | #define LIMIT_ERASE_SIZE 0x10000 30 | 31 | #define USER_BIN1 0x00 32 | #define USER_BIN2 0x01 33 | 34 | #define UPGRADE_FLAG_IDLE 0x00 35 | #define UPGRADE_FLAG_START 0x01 36 | #define UPGRADE_FLAG_FINISH 0x02 37 | 38 | #define UPGRADE_FW_BIN1 0x00 39 | #define UPGRADE_FW_BIN2 0x01 40 | 41 | typedef void (*upgrade_states_check_callback)(void * arg); 42 | 43 | //#define UPGRADE_SSL_ENABLE 44 | 45 | struct upgrade_server_info { 46 | uint8 ip[4]; 47 | uint16 port; 48 | 49 | uint8 upgrade_flag; 50 | 51 | uint8 pre_version[16]; 52 | uint8 upgrade_version[16]; 53 | 54 | uint32 check_times; 55 | uint8 *url; 56 | 57 | upgrade_states_check_callback check_cb; 58 | struct espconn *pespconn; 59 | }; 60 | 61 | #define UPGRADE_FLAG_IDLE 0x00 62 | #define UPGRADE_FLAG_START 0x01 63 | #define UPGRADE_FLAG_FINISH 0x02 64 | 65 | void system_upgrade_init(); 66 | void system_upgrade_deinit(); 67 | bool system_upgrade(uint8 *data, uint16 len); 68 | 69 | #ifdef UPGRADE_SSL_ENABLE 70 | bool system_upgrade_start_ssl(struct upgrade_server_info *server); // not supported now 71 | #else 72 | bool system_upgrade_start(struct upgrade_server_info *server); 73 | #endif 74 | #endif 75 | -------------------------------------------------------------------------------- /include/user_config.h: -------------------------------------------------------------------------------- 1 | #ifndef _USER_CONFIG_H_ 2 | #define _USER_CONFIG_H_ 3 | 4 | #define ICACHE_STORE_TYPEDEF_ATTR __attribute__((aligned(4), packed)) 5 | #define ICACHE_STORE_ATTR __attribute__((aligned(4))) 6 | #define ICACHE_RAM_ATTR __attribute__((section(".iram0.text"))) 7 | #define ICACHE_RODATA_ATTR __attribute__((section(".irom.text"))) 8 | 9 | #define CFG_HOLDER 0x00FF0006 10 | //#define CFG_LOCATION 0x3C //Working value on old SDK 11 | #define CFG_LOCATION 0x70 // NONOS-SDK - circa around position 458K in flash 12 | // 0x7C on 512K flash is where the internal RF data lives - stay away from there(last 16k) 13 | #define FWVER "1.4f/May 12th 2024" 14 | 15 | /*DEFAULT CONFIGURATIONS*/ 16 | 17 | #define STA_MODE "dhcp" 18 | #define STA_IP "192.168.1.17" 19 | #define STA_MASK "255.255.255.0" 20 | #define STA_GW "192.168.1.1" 21 | //#define STA_SSID "dd-wrt" 22 | //#define STA_PASS "a1b2c3d4e5" 23 | #define STA_SSID "pearson.uk" 24 | #define STA_PASS "spectrum" 25 | 26 | #define STA_TYPE AUTH_WPA2_PSK 27 | 28 | #define AP_IP "192.168.4.1" 29 | #define AP_MASK "255.255.255.0" 30 | #define AP_GW "192.168.4.1" 31 | 32 | #define HTTPD_PORT 80 33 | #define HTTPD_AUTH 0 34 | #define HTTPD_USER "admin" 35 | #define HTTPD_PASS "pass" 36 | 37 | #define BROADCASTD_ENABLE 0 38 | #define BROADCASTD_PORT 80 39 | #define BROADCASTD_HOST "api.thingspeak.com" 40 | #define BROADCASTD_URL "/update?key=**RWAPI**&field1=%d&field2=%d&field3=%d&field4=%s&field5=%s&field6=%s" 41 | #define BROADCASTD_THINGSPEAK_CHANNEL 0 42 | #define BROADCASTD_RO_APIKEY "**ROAPI**" 43 | 44 | #define SYSLOG_ENABLE 0 45 | #define SYSLOG_HOST "192.168.10.7" 46 | #define NTP_ENABLE 1 47 | #define NTP_TZ 1 48 | 49 | #define MQTT_ENABLE 1 50 | #define MQTT_HOST "192.168.10.3" // host name or IP "192.168.11.1" 51 | #define MQTT_PORT 1883 52 | #define MQTT_KEEPALIVE 120 /*seconds*/ 53 | #define MQTT_DEVID "ESP_%08X" 54 | #define MQTT_USER "tasmota" 55 | #define MQTT_PASS "tasmota" 56 | #define MQTT_USE_SSL 0 57 | #define MQTT_RELAY_SUBS_TOPIC "esp_%08X/in/relay/#" 58 | #define MQTT_TEMP_SUBS_TOPIC "esp_%08X/out/temperature" 59 | #define MQTT_STATE_PUB_TOPIC "esp_%08X/out/state" 60 | #define MQTT_USERJSON_PUB_TOPIC "esp_%08X/out/userJSON" 61 | 62 | #define MQTT_DHT22_TEMP_PUB_TOPIC "esp_%08X/out/dht22/temperature" 63 | #define MQTT_DHT22_HUMI_PUB_TOPIC "esp_%08X/out/dht22/humidity" 64 | #define MQTT_DS18B20_TEMP_PUB_TOPIC "esp_%08X/out/ds18b20/temperature" 65 | 66 | #define SENSOR_DS18B20_ENABLE 0 67 | #define SENSOR_DHT22_ENABLE 0 68 | 69 | #define RELAY_LATCHING_ENABLE 0 70 | #define RELAY_TOTAL 3 // number of relays 71 | #define RELAY1NAME "Relay 1" 72 | #define RELAY2NAME "Relay 2" 73 | #define RELAY3NAME "Relay 3" 74 | 75 | #define RELAY1GPIO 12 76 | #define RELAY2GPIO 13 77 | #define RELAY3GPIO 15 78 | 79 | #define MQTT_BUF_SIZE 300 80 | #define MQTT_RECONNECT_TIMEOUT 5 /*second*/ 81 | #define MQTT_CONNTECT_TIMER 5 /**/ 82 | 83 | #define THERM1_ZONE_NAME "Zone 1" 84 | 85 | #endif 86 | -------------------------------------------------------------------------------- /include/utils.h: -------------------------------------------------------------------------------- 1 | #ifndef _UTILS_H_ 2 | #define _UTILS_H_ 3 | 4 | #include "c_types.h" 5 | 6 | uint32_t UTILS_Atoh(const int8_t *s); 7 | uint8_t UTILS_StrToIP(const int8_t* str, void *ip); 8 | uint8_t UTILS_IsIPV4 (int8_t *str); 9 | char *ULTILS_StrReplace(char *orig, char *rep, char *with); 10 | #endif 11 | -------------------------------------------------------------------------------- /include/wifi.h: -------------------------------------------------------------------------------- 1 | /* 2 | * wifi.h 3 | * 4 | * Created on: Dec 30, 2014 5 | * Author: Minh 6 | */ 7 | 8 | #ifndef USER_WIFI_H_ 9 | #define USER_WIFI_H_ 10 | #include "os_type.h" 11 | typedef void (*WifiCallback)(uint8_t); 12 | void WIFI_Connect(WifiCallback cb); 13 | 14 | 15 | #endif /* USER_WIFI_H_ */ 16 | -------------------------------------------------------------------------------- /lib/README: -------------------------------------------------------------------------------- 1 | 2 | This directory is intended for project specific (private) libraries. 3 | PlatformIO will compile them to static libraries and link into executable file. 4 | 5 | The source code of each library should be placed in a an own separate directory 6 | ("lib/your_library_name/[here are source files]"). 7 | 8 | For example, see a structure of the following two libraries `Foo` and `Bar`: 9 | 10 | |--lib 11 | | | 12 | | |--Bar 13 | | | |--docs 14 | | | |--examples 15 | | | |--src 16 | | | |- Bar.c 17 | | | |- Bar.h 18 | | | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html 19 | | | 20 | | |--Foo 21 | | | |- Foo.c 22 | | | |- Foo.h 23 | | | 24 | | |- README --> THIS FILE 25 | | 26 | |- platformio.ini 27 | |--src 28 | |- main.c 29 | 30 | and a contents of `src/main.c`: 31 | ``` 32 | #include 33 | #include 34 | 35 | int main (void) 36 | { 37 | ... 38 | } 39 | 40 | ``` 41 | 42 | PlatformIO Library Dependency Finder will find automatically dependent 43 | libraries scanning project source files. 44 | 45 | More information about PlatformIO Library Dependency Finder 46 | - https://docs.platformio.org/page/librarymanager/ldf.html 47 | -------------------------------------------------------------------------------- /lib/heatshrink/.gitignore: -------------------------------------------------------------------------------- 1 | heatshrink 2 | test_heatshrink_dynamic 3 | test_heatshrink_static 4 | *.o 5 | *.core 6 | *.dSYM 7 | -------------------------------------------------------------------------------- /lib/heatshrink/.travis.yml: -------------------------------------------------------------------------------- 1 | language: c 2 | 3 | compiler: 4 | - clang 5 | - gcc 6 | 7 | install: make test_heatshrink_dynamic 8 | 9 | script: ./test_heatshrink_dynamic 10 | -------------------------------------------------------------------------------- /lib/heatshrink/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013, Scott Vokes 2 | All rights reserved. 3 | 4 | Permission to use, copy, modify, and/or distribute this software for any 5 | purpose with or without fee is hereby granted, provided that the above 6 | copyright notice and this permission notice appear in all copies. 7 | 8 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | -------------------------------------------------------------------------------- /lib/heatshrink/Makefile: -------------------------------------------------------------------------------- 1 | PROJECT = heatshrink 2 | #OPTIMIZE = -O0 3 | #OPTIMIZE = -Os 4 | OPTIMIZE = -O3 5 | WARN = -Wall -Wextra -pedantic #-Werror 6 | CFLAGS += -std=c99 -g ${WARN} ${OPTIMIZE} 7 | CFLAGS += -Wmissing-prototypes 8 | CFLAGS += -Wstrict-prototypes 9 | CFLAGS += -Wmissing-declarations 10 | 11 | # If libtheft is available, build additional property-based tests. 12 | # Uncomment these to use it in test_heatshrink_dynamic. 13 | #CFLAGS += -DHEATSHRINK_HAS_THEFT 14 | #LDFLAGS += -ltheft 15 | 16 | all: 17 | @echo "For tests, make test_heatshrink_dynamic (default) or change the" 18 | @echo "config.h to disable static memory and build test_heatshrink_static." 19 | @echo "For the standalone command-line tool, make heatshrink." 20 | 21 | ${PROJECT}: heatshrink.c 22 | 23 | OBJS= heatshrink_encoder.o \ 24 | heatshrink_decoder.o \ 25 | 26 | heatshrink: ${OBJS} 27 | test_heatshrink_dynamic: ${OBJS} test_heatshrink_dynamic_theft.o 28 | test_heatshrink_static: ${OBJS} 29 | 30 | *.o: Makefile heatshrink_config.h 31 | 32 | heatshrink_decoder.o: heatshrink_decoder.h heatshrink_common.h 33 | heatshrink_encoder.o: heatshrink_encoder.h heatshrink_common.h 34 | 35 | tags: TAGS 36 | 37 | TAGS: 38 | etags *.[ch] 39 | 40 | diagrams: dec_sm.png enc_sm.png 41 | 42 | dec_sm.png: dec_sm.dot 43 | dot -o $@ -Tpng $< 44 | 45 | enc_sm.png: enc_sm.dot 46 | dot -o $@ -Tpng $< 47 | 48 | clean: 49 | rm -f ${PROJECT} test_heatshrink_{dynamic,static} *.o *.core {dec,enc}_sm.png TAGS 50 | -------------------------------------------------------------------------------- /lib/heatshrink/README.md: -------------------------------------------------------------------------------- 1 | # heatshrink 2 | 3 | A data compression/decompression library for embedded/real-time systems. 4 | 5 | ## Key Features: 6 | 7 | - **Low memory usage (as low as 50 bytes)** 8 | It is useful for some cases with less than 50 bytes, and useful 9 | for many general cases with < 300 bytes. 10 | - **Incremental, bounded CPU use** 11 | You can chew on input data in arbitrarily tiny bites. 12 | This is a useful property in hard real-time environments. 13 | - **Can use either static or dynamic memory allocation** 14 | The library doesn't impose any constraints on memory management. 15 | - **ISC license** 16 | You can use it freely, even for commercial purposes. 17 | 18 | ## Getting Started: 19 | 20 | There is a standalone command-line program, `heatshrink`, but the 21 | encoder and decoder can also be used as libraries, independent of each 22 | other. To do so, copy `heatshrink_common.h`, `heatshrink_config.h`, and 23 | either `heatshrink_encoder.c` or `heatshrink_decoder.c` (and their 24 | respective header) into your project. 25 | 26 | Dynamic allocation is used by default, but in an embedded context, you 27 | probably want to statically allocate the encoder/decoder. Set 28 | `HEATSHRINK_DYNAMIC_ALLOC` to 0 in `heatshrink_config.h`. 29 | 30 | ## More Information and Benchmarks: 31 | 32 | heatshrink is based on [LZSS], since it's particularly suitable for 33 | compression in small amounts of memory. It can use an optional, small 34 | [index] to make compression significantly faster, but otherwise can run 35 | in under 100 bytes of memory. The index currently adds 2^(window size+1) 36 | bytes to memory usage for compression, and temporarily allocates 512 37 | bytes on the stack during index construction. 38 | 39 | For more information, see the [blog post] for an overview, and the 40 | `heatshrink_encoder.h` / `heatshrink_decoder.h` header files for API 41 | documentation. 42 | 43 | [blog post]: http://spin.atomicobject.com/2013/03/14/heatshrink-embedded-data-compression/ 44 | [index]: http://spin.atomicobject.com/2014/01/13/lightweight-indexing-for-embedded-systems/ 45 | [LZSS]: http://en.wikipedia.org/wiki/Lempel-Ziv-Storer-Szymanski 46 | 47 | ## Build Status 48 | 49 | [![Build Status](https://travis-ci.org/atomicobject/heatshrink.png)](http://travis-ci.org/atomicobject/heatshrink) 50 | -------------------------------------------------------------------------------- /lib/heatshrink/dec_sm.dot: -------------------------------------------------------------------------------- 1 | digraph { 2 | graph [label="Decoder state machine", labelloc="t"] 3 | Start [style="invis", shape="point"] 4 | empty 5 | input_available 6 | yield_literal 7 | backref_index_msb 8 | backref_index_lsb 9 | backref_count_msb 10 | backref_count_lsb 11 | yield_backref 12 | check_for_more_input 13 | done [peripheries=2] 14 | 15 | empty->input_available [label="sink()", color="blue", weight=10] 16 | Start->empty 17 | 18 | input_available->yield_literal [label="pop 1-bit"] 19 | input_available->backref_index_msb [label="pop 0-bit", weight=10] 20 | input_available->backref_index_lsb [label="pop 0-bit, index <8 bits", weight=10] 21 | 22 | yield_literal->yield_literal [label="sink()", color="blue"] 23 | yield_literal->yield_literal [label="poll()", color="red"] 24 | yield_literal->check_for_more_input [label="poll(), done", color="red"] 25 | 26 | backref_index_msb->backref_index_msb [label="sink()", color="blue"] 27 | backref_index_msb->backref_index_lsb [label="pop index, upper bits", weight=10] 28 | backref_index_msb->done [label="finish()", color="blue"] 29 | 30 | backref_index_lsb->backref_index_lsb [label="sink()", color="blue"] 31 | backref_index_lsb->backref_count_msb [label="pop index, lower bits", weight=10] 32 | backref_index_lsb->backref_count_lsb [label="pop index, count <=8 bits", weight=10] 33 | backref_index_lsb->done [label="finish()", color="blue"] 34 | 35 | backref_count_msb->backref_count_msb [label="sink()", color="blue"] 36 | backref_count_msb->backref_count_lsb [label="pop count, upper bits", weight=10] 37 | backref_count_msb->done [label="finish()", color="blue"] 38 | 39 | backref_count_lsb->backref_count_lsb [label="sink()", color="blue"] 40 | backref_count_lsb->yield_backref [label="pop count, lower bits", weight=10] 41 | backref_count_lsb->done [label="finish()", color="blue"] 42 | 43 | yield_backref->yield_backref [label="sink()", color="blue"] 44 | yield_backref->yield_backref [label="poll()", color="red"] 45 | yield_backref->check_for_more_input [label="poll(), done", 46 | color="red", weight=10] 47 | 48 | check_for_more_input->empty [label="no"] 49 | check_for_more_input->input_available [label="yes"] 50 | 51 | empty->done [label="finish()", color="blue"] 52 | } 53 | -------------------------------------------------------------------------------- /lib/heatshrink/enc_sm.dot: -------------------------------------------------------------------------------- 1 | digraph { 2 | graph [label="Encoder state machine", labelloc="t"] 3 | start [style="invis", shape="point"] 4 | not_full 5 | filled 6 | search 7 | yield_tag_bit 8 | yield_literal 9 | yield_br_length 10 | yield_br_index 11 | save_backlog 12 | flush_bits 13 | done [peripheries=2] 14 | 15 | start->not_full [label="start"] 16 | 17 | not_full->not_full [label="sink(), not full", color="blue"] 18 | not_full->filled [label="sink(), buffer is full", color="blue"] 19 | not_full->filled [label="finish(), set is_finished", color="blue"] 20 | 21 | filled->search [label="indexing (if any)"] 22 | 23 | search->search [label="step"] 24 | search->yield_tag_bit [label="literal"] 25 | search->yield_tag_bit [label="match found"] 26 | search->save_backlog [label="input exhausted"] 27 | 28 | yield_tag_bit->yield_tag_bit [label="poll(), full buf", color="red"] 29 | yield_tag_bit->yield_literal [label="poll(), literal", color="red"] 30 | yield_tag_bit->yield_br_index [label="poll(), no literal", color="red"] 31 | yield_tag_bit->flush_bits [label="finishing, no literal"] 32 | 33 | yield_literal->yield_literal [label="poll(), full buf", color="red"] 34 | yield_literal->search [label="poll(), no match", color="red"] 35 | yield_literal->yield_tag_bit [label="poll(), match", color="red"] 36 | yield_literal->flush_bits [label="poll(), final literal", color="red"] 37 | 38 | yield_br_index->yield_br_index [label="poll(), full buf", color="red"] 39 | yield_br_index->yield_br_length [label="poll()", color="red"] 40 | 41 | yield_br_length->yield_br_length [label="poll(), full buf", color="red"] 42 | yield_br_length->search [label="done"] 43 | 44 | save_backlog->flush_bits [label="finishing, no literal"] 45 | save_backlog->yield_tag_bit [label="finishing, literal"] 46 | save_backlog->not_full [label="expect more input"] 47 | 48 | flush_bits->flush_bits [label="poll(), full buf", color="red"] 49 | flush_bits->done [label="poll(), flushed", color="red"] 50 | flush_bits->done [label="no more output"] 51 | } 52 | -------------------------------------------------------------------------------- /lib/heatshrink/heatshrink_common.h: -------------------------------------------------------------------------------- 1 | #ifndef HEATSHRINK_H 2 | #define HEATSHRINK_H 3 | 4 | #define HEATSHRINK_AUTHOR "Scott Vokes " 5 | #define HEATSHRINK_URL "https://github.com/atomicobject/heatshrink" 6 | 7 | /* Version 0.3.1 */ 8 | #define HEATSHRINK_VERSION_MAJOR 0 9 | #define HEATSHRINK_VERSION_MINOR 3 10 | #define HEATSHRINK_VERSION_PATCH 1 11 | 12 | #define HEATSHRINK_MIN_WINDOW_BITS 4 13 | #define HEATSHRINK_MAX_WINDOW_BITS 15 14 | 15 | #define HEATSHRINK_MIN_LOOKAHEAD_BITS 2 16 | 17 | #define HEATSHRINK_LITERAL_MARKER 0x01 18 | #define HEATSHRINK_BACKREF_MARKER 0x00 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /lib/heatshrink/heatshrink_config.h: -------------------------------------------------------------------------------- 1 | #ifndef HEATSHRINK_CONFIG_H 2 | #define HEATSHRINK_CONFIG_H 3 | 4 | /* Should functionality assuming dynamic allocation be used? */ 5 | #define HEATSHRINK_DYNAMIC_ALLOC 1 6 | 7 | #if HEATSHRINK_DYNAMIC_ALLOC 8 | /* Optional replacement of malloc/free */ 9 | #define HEATSHRINK_MALLOC(SZ) malloc(SZ) 10 | #define HEATSHRINK_FREE(P, SZ) free(P) 11 | #else 12 | /* Required parameters for static configuration */ 13 | #define HEATSHRINK_STATIC_INPUT_BUFFER_SIZE 32 14 | #define HEATSHRINK_STATIC_WINDOW_BITS 8 15 | #define HEATSHRINK_STATIC_LOOKAHEAD_BITS 4 16 | #endif 17 | 18 | /* Turn on logging for debugging. */ 19 | #define HEATSHRINK_DEBUGGING_LOGS 0 20 | 21 | /* Use indexing for faster compression. (This requires additional space.) */ 22 | #define HEATSHRINK_USE_INDEX 1 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /lib/heatshrink/heatshrink_decoder.h: -------------------------------------------------------------------------------- 1 | #ifndef HEATSHRINK_DECODER_H 2 | #define HEATSHRINK_DECODER_H 3 | 4 | #include "../../include/espmissingincludes.h" 5 | #include "heatshrink_common.h" 6 | #include "heatshrink_config.h" 7 | #include 8 | #include 9 | 10 | typedef enum { 11 | HSDR_SINK_OK, /* data sunk, ready to poll */ 12 | HSDR_SINK_FULL, /* out of space in internal buffer */ 13 | HSDR_SINK_ERROR_NULL = -1, /* NULL argument */ 14 | } HSD_sink_res; 15 | 16 | typedef enum { 17 | HSDR_POLL_EMPTY, /* input exhausted */ 18 | HSDR_POLL_MORE, /* more data remaining, call again w/ fresh output buffer */ 19 | HSDR_POLL_ERROR_NULL = -1, /* NULL arguments */ 20 | HSDR_POLL_ERROR_UNKNOWN = -2, 21 | } HSD_poll_res; 22 | 23 | typedef enum { 24 | HSDR_FINISH_DONE, /* output is done */ 25 | HSDR_FINISH_MORE, /* more output remains */ 26 | HSDR_FINISH_ERROR_NULL = -1, /* NULL arguments */ 27 | } HSD_finish_res; 28 | 29 | #if HEATSHRINK_DYNAMIC_ALLOC 30 | #define HEATSHRINK_DECODER_INPUT_BUFFER_SIZE(BUF) ((BUF)->input_buffer_size) 31 | #define HEATSHRINK_DECODER_WINDOW_BITS(BUF) ((BUF)->window_sz2) 32 | #define HEATSHRINK_DECODER_LOOKAHEAD_BITS(BUF) ((BUF)->lookahead_sz2) 33 | #else 34 | #define HEATSHRINK_DECODER_INPUT_BUFFER_SIZE(_) HEATSHRINK_STATIC_INPUT_BUFFER_SIZE 35 | #define HEATSHRINK_DECODER_WINDOW_BITS(_) (HEATSHRINK_STATIC_WINDOW_BITS) 36 | #define HEATSHRINK_DECODER_LOOKAHEAD_BITS(BUF) (HEATSHRINK_STATIC_LOOKAHEAD_BITS) 37 | #endif 38 | 39 | typedef struct { 40 | uint16_t input_size; /* bytes in input buffer */ 41 | uint16_t input_index; /* offset to next unprocessed input byte */ 42 | uint16_t output_count; /* how many bytes to output */ 43 | uint16_t output_index; /* index for bytes to output */ 44 | uint16_t head_index; /* head of window buffer */ 45 | uint16_t bit_accumulator; 46 | uint8_t state; /* current state machine node */ 47 | uint8_t current_byte; /* current byte of input */ 48 | uint8_t bit_index; /* current bit index */ 49 | 50 | #if HEATSHRINK_DYNAMIC_ALLOC 51 | /* Fields that are only used if dynamically allocated. */ 52 | uint8_t window_sz2; /* window buffer bits */ 53 | uint8_t lookahead_sz2; /* lookahead bits */ 54 | uint16_t input_buffer_size; /* input buffer size */ 55 | 56 | /* Input buffer, then expansion window buffer */ 57 | uint8_t buffers[]; 58 | #else 59 | /* Input buffer, then expansion window buffer */ 60 | uint8_t buffers[(1 << HEATSHRINK_DECODER_WINDOW_BITS(_)) + HEATSHRINK_DECODER_INPUT_BUFFER_SIZE(_)]; 61 | #endif 62 | } heatshrink_decoder; 63 | 64 | #if HEATSHRINK_DYNAMIC_ALLOC 65 | /* Allocate a decoder with an input buffer of INPUT_BUFFER_SIZE bytes, 66 | * an expansion buffer size of 2^WINDOW_SZ2, and a lookahead 67 | * size of 2^lookahead_sz2. (The window buffer and lookahead sizes 68 | * must match the settings used when the data was compressed.) 69 | * Returns NULL on error. */ 70 | heatshrink_decoder *heatshrink_decoder_alloc(uint16_t input_buffer_size, uint8_t expansion_buffer_sz2, 71 | uint8_t lookahead_sz2); 72 | 73 | /* Free a decoder. */ 74 | void heatshrink_decoder_free(heatshrink_decoder *hsd); 75 | #endif 76 | 77 | /* Reset a decoder. */ 78 | void heatshrink_decoder_reset(heatshrink_decoder *hsd); 79 | 80 | /* Sink at most SIZE bytes from IN_BUF into the decoder. *INPUT_SIZE is set to 81 | * indicate how many bytes were actually sunk (in case a buffer was filled). */ 82 | HSD_sink_res heatshrink_decoder_sink(heatshrink_decoder *hsd, uint8_t *in_buf, size_t size, size_t *input_size); 83 | 84 | /* Poll for output from the decoder, copying at most OUT_BUF_SIZE bytes into 85 | * OUT_BUF (setting *OUTPUT_SIZE to the actual amount copied). */ 86 | HSD_poll_res heatshrink_decoder_poll(heatshrink_decoder *hsd, uint8_t *out_buf, size_t out_buf_size, 87 | size_t *output_size); 88 | 89 | /* Notify the dencoder that the input stream is finished. 90 | * If the return value is HSDR_FINISH_MORE, there is still more output, so 91 | * call heatshrink_decoder_poll and repeat. */ 92 | HSD_finish_res heatshrink_decoder_finish(heatshrink_decoder *hsd); 93 | 94 | #endif 95 | -------------------------------------------------------------------------------- /lib/heatshrink/heatshrink_encoder.h: -------------------------------------------------------------------------------- 1 | #ifndef HEATSHRINK_ENCODER_H 2 | #define HEATSHRINK_ENCODER_H 3 | 4 | //#include "../../include/espmissingincludes.h" 5 | #include 6 | #include 7 | 8 | #include "heatshrink_common.h" 9 | #include "heatshrink_config.h" 10 | 11 | #if defined TENSILICA 12 | #include 13 | #endif 14 | 15 | 16 | typedef enum { 17 | HSER_SINK_OK, /* data sunk into input buffer */ 18 | HSER_SINK_ERROR_NULL = -1, /* NULL argument */ 19 | HSER_SINK_ERROR_MISUSE = -2, /* API misuse */ 20 | } HSE_sink_res; 21 | 22 | typedef enum { 23 | HSER_POLL_EMPTY, /* input exhausted */ 24 | HSER_POLL_MORE, /* poll again for more output */ 25 | HSER_POLL_ERROR_NULL = -1, /* NULL argument */ 26 | HSER_POLL_ERROR_MISUSE = -2, /* API misuse */ 27 | } HSE_poll_res; 28 | 29 | typedef enum { 30 | HSER_FINISH_DONE, /* encoding is complete */ 31 | HSER_FINISH_MORE, /* more output remaining; use poll */ 32 | HSER_FINISH_ERROR_NULL = -1, /* NULL argument */ 33 | } HSE_finish_res; 34 | 35 | #if HEATSHRINK_DYNAMIC_ALLOC 36 | #define HEATSHRINK_ENCODER_WINDOW_BITS(HSE) ((HSE)->window_sz2) 37 | #define HEATSHRINK_ENCODER_LOOKAHEAD_BITS(HSE) ((HSE)->lookahead_sz2) 38 | #define HEATSHRINK_ENCODER_INDEX(HSE) ((HSE)->search_index) 39 | struct hs_index { 40 | uint16_t size; 41 | int16_t index[]; 42 | }; 43 | #else 44 | #define HEATSHRINK_ENCODER_WINDOW_BITS(_) (HEATSHRINK_STATIC_WINDOW_BITS) 45 | #define HEATSHRINK_ENCODER_LOOKAHEAD_BITS(_) (HEATSHRINK_STATIC_LOOKAHEAD_BITS) 46 | #define HEATSHRINK_ENCODER_INDEX(HSE) (&(HSE)->search_index) 47 | struct hs_index { 48 | uint16_t size; 49 | int16_t index[2 << HEATSHRINK_STATIC_WINDOW_BITS]; 50 | }; 51 | #endif 52 | 53 | typedef struct { 54 | uint16_t input_size; /* bytes in input buffer */ 55 | uint16_t match_scan_index; 56 | uint16_t match_length; 57 | uint16_t match_pos; 58 | uint16_t outgoing_bits; /* enqueued outgoing bits */ 59 | uint8_t outgoing_bits_count; 60 | uint8_t flags; 61 | uint8_t state; /* current state machine node */ 62 | uint8_t current_byte; /* current byte of output */ 63 | uint8_t bit_index; /* current bit index */ 64 | #if HEATSHRINK_DYNAMIC_ALLOC 65 | uint8_t window_sz2; /* 2^n size of window */ 66 | uint8_t lookahead_sz2; /* 2^n size of lookahead */ 67 | #if HEATSHRINK_USE_INDEX 68 | struct hs_index *search_index; 69 | #endif 70 | /* input buffer and / sliding window for expansion */ 71 | uint8_t buffer[]; 72 | #else 73 | #if HEATSHRINK_USE_INDEX 74 | struct hs_index search_index; 75 | #endif 76 | /* input buffer and / sliding window for expansion */ 77 | uint8_t buffer[2 << HEATSHRINK_ENCODER_WINDOW_BITS(_)]; 78 | #endif 79 | } heatshrink_encoder; 80 | 81 | #if HEATSHRINK_DYNAMIC_ALLOC 82 | /* Allocate a new encoder struct and its buffers. 83 | * Returns NULL on error. */ 84 | heatshrink_encoder *heatshrink_encoder_alloc(uint8_t window_sz2, uint8_t lookahead_sz2); 85 | 86 | /* Free an encoder. */ 87 | void heatshrink_encoder_free(heatshrink_encoder *hse); 88 | #endif 89 | 90 | /* Reset an encoder. */ 91 | void heatshrink_encoder_reset(heatshrink_encoder *hse); 92 | 93 | /* Sink up to SIZE bytes from IN_BUF into the encoder. 94 | * INPUT_SIZE is set to the number of bytes actually sunk (in case a 95 | * buffer was filled.). */ 96 | HSE_sink_res heatshrink_encoder_sink(heatshrink_encoder *hse, uint8_t *in_buf, size_t size, size_t *input_size); 97 | 98 | /* Poll for output from the encoder, copying at most OUT_BUF_SIZE bytes into 99 | * OUT_BUF (setting *OUTPUT_SIZE to the actual amount copied). */ 100 | HSE_poll_res heatshrink_encoder_poll(heatshrink_encoder *hse, uint8_t *out_buf, size_t out_buf_size, 101 | size_t *output_size); 102 | 103 | /* Notify the encoder that the input stream is finished. 104 | * If the return value is HSER_FINISH_MORE, there is still more output, so 105 | * call heatshrink_encoder_poll and repeat. */ 106 | HSE_finish_res heatshrink_encoder_finish(heatshrink_encoder *hse); 107 | 108 | #endif 109 | -------------------------------------------------------------------------------- /mkespfsimage/Makefile: -------------------------------------------------------------------------------- 1 | 2 | CFLAGS=-I../lib/heatshrink -std=gnu99 -I~/.platformio/packages/framework-esp8266-nonos-sdk/include 3 | OBJS=main.o heatshrink_encoder.o 4 | TARGET=mkespfsimage 5 | 6 | $(TARGET): $(OBJS) 7 | $(CC) -o $@ $^ 8 | 9 | clean: 10 | rm -f $(TARGET) $(OBJS) 11 | -------------------------------------------------------------------------------- /mkespfsimage/espfsformat.h: -------------------------------------------------------------------------------- 1 | #ifndef ESPROFSFORMAT_H 2 | #define ESPROFSFORMAT_H 3 | 4 | //#include "espmissingincludes.h" 5 | 6 | /* 7 | Stupid cpio-like tool to make read-only 'filesystems' that live on the flash SPI chip of the module. 8 | Can (will) use lzf compression (when I come around to it) to make shit quicker. Aligns names, files, 9 | headers on 4-byte boundaries so the SPI abstraction hardware in the ESP8266 doesn't crap on itself 10 | when trying to do a <4byte or unaligned read. 11 | */ 12 | 13 | /* 14 | The idea 'borrows' from cpio: it's basically a concatenation of {header, filename, file} data. 15 | Header, filename and file data is 32-bit aligned. The last file is indicated by data-less header 16 | with the FLAG_LASTFILE flag set. 17 | */ 18 | 19 | #define FLAG_LASTFILE (1 << 0) 20 | #define COMPRESS_NONE 0 21 | #define COMPRESS_HEATSHRINK 1 22 | 23 | typedef struct { 24 | int32_t magic; 25 | int8_t flags; 26 | int8_t compression; 27 | int16_t nameLen; 28 | int32_t fileLenComp; 29 | int32_t fileLenDecomp; 30 | } __attribute__((packed)) EspFsHeader; 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /mkespfsimage/heatshrink_encoder.c: -------------------------------------------------------------------------------- 1 | //Stupid wraparound include to make sure object file doesn't end up in heatshrink dir 2 | 3 | #include "../lib/heatshrink/heatshrink_encoder.c" 4 | -------------------------------------------------------------------------------- /mkespfsimage/heatshrink_encoder.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mharizanov/ESP8266_Relay_Board/bb58eb2f41fc9a136600907f62672e4673c06658/mkespfsimage/heatshrink_encoder.o -------------------------------------------------------------------------------- /mkespfsimage/main.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mharizanov/ESP8266_Relay_Board/bb58eb2f41fc9a136600907f62672e4673c06658/mkespfsimage/main.o -------------------------------------------------------------------------------- /mkespfsimage/mkespfsimage: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mharizanov/ESP8266_Relay_Board/bb58eb2f41fc9a136600907f62672e4673c06658/mkespfsimage/mkespfsimage -------------------------------------------------------------------------------- /platformio.ini: -------------------------------------------------------------------------------- 1 | ; PlatformIO Project Configuration File 2 | ; 3 | ; Build options: build flags, source filter 4 | ; Upload options: custom upload port, speed and extra flags 5 | ; Library options: dependencies, extra library storages 6 | ; Advanced options: extra scripting 7 | ; 8 | ; Please visit documentation for the other options and examples 9 | ; https://docs.platformio.org/page/projectconf.html 10 | 11 | [platformio] 12 | data_dir = data 13 | 14 | [env:esp01] 15 | ;relay board has 512Kb flash 16 | platform = espressif8266 @ 4.0.1 17 | board = esp01 18 | 19 | framework = esp8266-nonos-sdk 20 | monitor_speed = 74880 21 | 22 | build_flags = 23 | ; -I /Users/apearson/dev/esp32/relay_board/include 24 | ; -I /Users/apearson/dev/esp32/relay_board/lib/heatshrink 25 | ; -I ${platformio.packages_dir}/framework-esp8266-nonos-sdk/driver_lib/include 26 | -I /Users/apearson/esp/ESP8266_NONOS_SDK/third_party/include 27 | 28 | ;-I ${platformio.packages_dir}/framework-esp8266-nonos-sdk/third_party/include 29 | 30 | -D LWIP_OPEN_SRC 31 | -D GZIP_COMPRESSION 32 | -D ICACHE_FLASH 33 | -D TENSILICA 34 | -D PIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190703 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /src/user/auth.c: -------------------------------------------------------------------------------- 1 | /* 2 | HTTP auth implementation. Only does basic authentication for now. 3 | */ 4 | 5 | /* 6 | * ---------------------------------------------------------------------------- 7 | * "THE BEER-WARE LICENSE" (Revision 42): 8 | * Jeroen Domburg wrote this file. As long as you retain 9 | * this notice you can do whatever you want with this stuff. If we meet some day, 10 | * and you think this stuff is worth it, you can buy me a beer in return. 11 | * ---------------------------------------------------------------------------- 12 | */ 13 | 14 | #include "auth.h" 15 | #include "base64.h" 16 | #include "cgi.h" 17 | #include "config.h" 18 | #include "espmissingincludes.h" 19 | #include "httpd.h" 20 | #include "io.h" 21 | #include "lwip/ip_addr.h" 22 | #include "mem.h" 23 | #include "user_interface.h" 24 | #include 25 | #include 26 | static uint8_t remoteip[4]; 27 | 28 | int ICACHE_FLASH_ATTR authBasic(HttpdConnData *connData) { 29 | const char *forbidden = "401 Forbidden."; 30 | int no = 0; 31 | int r; 32 | char hdr[(AUTH_MAX_USER_LEN + AUTH_MAX_PASS_LEN + 2) * 10]; 33 | char userpass[AUTH_MAX_USER_LEN + AUTH_MAX_PASS_LEN + 2]; 34 | char user[AUTH_MAX_USER_LEN]; 35 | char pass[AUTH_MAX_PASS_LEN]; 36 | if (connData->conn == NULL) { 37 | // Connection aborted. Clean up. 38 | return HTTPD_CGI_DONE; 39 | } 40 | 41 | struct espconn *pespconn = connData->conn; 42 | 43 | r = httpdGetHeader(connData, "Authorization", hdr, sizeof(hdr)); 44 | if (r && strncmp(hdr, "Basic", 5) == 0) { 45 | r = base64_decode2(strlen(hdr) - 6, hdr + 6, sizeof(userpass), (unsigned char *)userpass); 46 | if (r < 0) 47 | r = 0; // just clean out string on decode error 48 | userpass[r] = 0; // zero-terminate user:pass string 49 | // os_printf("Auth: %s\n", userpass); 50 | while (((AuthGetUserPw)(connData->cgiArg))(connData, no, user, AUTH_MAX_USER_LEN, pass, AUTH_MAX_PASS_LEN)) { 51 | // Check user/pass against auth header 52 | if (strlen(userpass) == strlen(user) + strlen(pass) + 1 && os_strncmp(userpass, user, strlen(user)) == 0 && 53 | userpass[strlen(user)] == ':' && os_strcmp(userpass + strlen(user) + 1, pass) == 0) { 54 | // Authenticated. Yay! 55 | 56 | os_memcpy(&remoteip, pespconn->proto.tcp->remote_ip, 4); 57 | return HTTPD_CGI_AUTHENTICATED; 58 | } 59 | no++; // Not authenticated with this user/pass. Check next user/pass combo. 60 | } 61 | } 62 | 63 | if (sysCfg.httpd_auth == 1 && (os_memcmp(remoteip, pespconn->proto.tcp->remote_ip, 4) != 0)) { 64 | // Not authenticated. Go bug user with login screen. 65 | httpdStartResponse(connData, 401); 66 | httpdHeader(connData, "Content-Type", "text/plain"); 67 | httpdHeader(connData, "WWW-Authenticate", "Basic realm=\"" HTTP_AUTH_REALM "\""); 68 | httpdEndHeaders(connData); 69 | httpdSend(connData, forbidden, -1); 70 | // Okay, all done. 71 | return HTTPD_CGI_DONE; 72 | } else 73 | return HTTPD_CGI_AUTHENTICATED; 74 | } 75 | -------------------------------------------------------------------------------- /src/user/base64.c: -------------------------------------------------------------------------------- 1 | /* base64.c : base-64 / MIME encode/decode */ 2 | /* PUBLIC DOMAIN - Jon Mayo - November 13, 2003 */ 3 | #include "espmissingincludes.h" 4 | #include "c_types.h" 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include "base64.h" 10 | #include "user_config.h" 11 | 12 | static const uint8_t ICACHE_STORE_ATTR ICACHE_RODATA_ATTR base64dec_tab[256]= { 13 | 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 14 | 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 15 | 255,255,255,255,255,255,255,255,255,255,255, 62,255,255,255, 63, 16 | 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,255,255,255, 0,255,255, 17 | 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 18 | 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,255,255,255,255,255, 19 | 255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 20 | 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,255,255,255,255,255, 21 | 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 22 | 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 23 | 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 24 | 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 25 | 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 26 | 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 27 | 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 28 | 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 29 | }; 30 | 31 | static uint8_t byte_of_aligned_array(const uint8_t* aligned_array, uint32_t index) 32 | { 33 | if( (((uint32_t)aligned_array)%4) != 0 ){ 34 | os_printf("aligned_array is not 4-byte aligned.\n"); 35 | return 0; 36 | } 37 | uint32_t v = ((uint32_t *)aligned_array)[ index/4 ]; 38 | uint8_t *p = (uint8_t *) (&v); 39 | return p[ (index%4) ]; 40 | } 41 | 42 | #if 0 43 | static int ICACHE_FLASH_ATTR base64decode(const char in[4], char out[3]) { 44 | uint8_t v[4]; 45 | 46 | v[0]=base64dec_tab[(unsigned)in[0]]; 47 | v[1]=base64dec_tab[(unsigned)in[1]]; 48 | v[2]=base64dec_tab[(unsigned)in[2]]; 49 | v[3]=base64dec_tab[(unsigned)in[3]]; 50 | 51 | out[0]=(v[0]<<2)|(v[1]>>4); 52 | out[1]=(v[1]<<4)|(v[2]>>2); 53 | out[2]=(v[2]<<6)|(v[3]); 54 | return (v[0]|v[1]|v[2]|v[3])!=255 ? in[3]=='=' ? in[2]=='=' ? 1 : 2 : 3 : 0; 55 | } 56 | #endif 57 | 58 | /* decode a base64 string in one shot */ 59 | int ICACHE_FLASH_ATTR base64_decode2(size_t in_len, const char *in, size_t out_len, unsigned char *out) { 60 | unsigned int ii, io; 61 | uint32_t v; 62 | unsigned int rem; 63 | 64 | for(io=0,ii=0,v=0,rem=0;ii=8) { 73 | rem-=8; 74 | if(io>=out_len) return -1; /* truncation is failure */ 75 | out[io++]=(v>>rem)&255; 76 | } 77 | } 78 | if(rem>=8) { 79 | rem-=8; 80 | if(io>=out_len) return -1; /* truncation is failure */ 81 | out[io++]=(v>>rem)&255; 82 | } 83 | return io; 84 | } 85 | 86 | //Only need decode functions for now. 87 | #if 0 88 | 89 | static const uint8_t base64enc_tab[64]= "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 90 | 91 | void base64encode(const unsigned char in[3], unsigned char out[4], int count) { 92 | out[0]=base64enc_tab[(in[0]>>2)]; 93 | out[1]=base64enc_tab[((in[0]&3)<<4)|(in[1]>>4)]; 94 | out[2]=count<2 ? '=' : base64enc_tab[((in[1]&15)<<2)|(in[2]>>6)]; 95 | out[3]=count<3 ? '=' : base64enc_tab[(in[2]&63)]; 96 | } 97 | 98 | 99 | int base64_encode(size_t in_len, const unsigned char *in, size_t out_len, char *out) { 100 | unsigned ii, io; 101 | uint_least32_t v; 102 | unsigned rem; 103 | 104 | for(io=0,ii=0,v=0,rem=0;ii=6) { 110 | rem-=6; 111 | if(io>=out_len) return -1; /* truncation is failure */ 112 | out[io++]=base64enc_tab[(v>>rem)&63]; 113 | } 114 | } 115 | if(rem) { 116 | v<<=(6-rem); 117 | if(io>=out_len) return -1; /* truncation is failure */ 118 | out[io++]=base64enc_tab[v&63]; 119 | } 120 | while(io&3) { 121 | if(io>=out_len) return -1; /* truncation is failure */ 122 | out[io++]='='; 123 | } 124 | if(io>=out_len) return -1; /* no room for null terminator */ 125 | out[io]=0; 126 | return io; 127 | } 128 | 129 | #endif -------------------------------------------------------------------------------- /src/user/heatshrink_decoder.c: -------------------------------------------------------------------------------- 1 | #include "httpdconfig.h" 2 | #ifdef EFS_HEATSHRINK 3 | //Stupid wrapper so we don't have to move c-files around 4 | //Also loads httpd-specific config. 5 | 6 | #define _STDLIB_H_ 7 | #define _STRING_H_ 8 | #define _STDDEF_H 9 | #define _STDINT_H 10 | 11 | #include "espmissingincludes.h" 12 | #include "c_types.h" 13 | #include "mem.h" 14 | #include "osapi.h" 15 | #include "heatshrink_config_httpd.h" 16 | #define memset(x,y,z) os_memset(x,y,z) 17 | #define memcpy(x,y,z) os_memcpy(x,y,z) 18 | #include "../lib/heatshrink/heatshrink_decoder.c" 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /src/user/httpdespfs.c: -------------------------------------------------------------------------------- 1 | /* 2 | Connector to let httpd use the espfs filesystem to serve the files in it. 3 | */ 4 | 5 | /* 6 | * ---------------------------------------------------------------------------- 7 | * "THE BEER-WARE LICENSE" (Revision 42): 8 | * Jeroen Domburg wrote this file. As long as you retain 9 | * this notice you can do whatever you want with this stuff. If we meet some day, 10 | * and you think this stuff is worth it, you can buy me a beer in return. 11 | * ---------------------------------------------------------------------------- 12 | */ 13 | 14 | #include "c_types.h" 15 | #include "espmissingincludes.h" 16 | #include "user_interface.h" 17 | #include 18 | #include 19 | //#include "espconn.h" 20 | #include "mem.h" 21 | 22 | #include "espfs.h" 23 | #include "httpd.h" 24 | #include "httpdespfs.h" 25 | 26 | // This is a catch-all cgi function. It takes the url passed to it, looks up the corresponding 27 | // path in the filesystem and if it exists, passes the file through. This simulates what a normal 28 | // webserver would do with static files. 29 | int ICACHE_FLASH_ATTR cgiEspFsHook(HttpdConnData *connData) { 30 | EspFsFile *file = connData->cgiData; 31 | int len; 32 | char buff[1024]; 33 | #ifdef GZIP_COMPRESSION 34 | const char *gzipSendResult = NULL; 35 | #endif 36 | 37 | if (connData->conn == NULL) { 38 | // Connection aborted. Clean up. 39 | espFsClose(file); 40 | return HTTPD_CGI_DONE; 41 | } 42 | 43 | if (file == NULL) { 44 | // First call to this cgi. Open the file so we can read it. 45 | file = espFsOpen(connData->url); 46 | if (file == NULL) { 47 | return HTTPD_CGI_NOTFOUND; 48 | } 49 | connData->cgiData = file; 50 | httpdStartResponse(connData, 200); 51 | httpdHeader(connData, "Content-Type", httpdGetMimetype(connData->url)); 52 | #ifdef GZIP_COMPRESSION 53 | gzipSendResult = sendGZIPEncodingIfNeeded(connData); 54 | if (gzipSendResult != NULL) { 55 | httpdEndHeaders(connData); 56 | httpdSend(connData, gzipSendResult, os_strlen(gzipSendResult)); 57 | return HTTPD_CGI_DONE; 58 | } 59 | #endif 60 | httpdHeader(connData, "Cache-Control", "max-age=3600, must-revalidate"); 61 | httpdEndHeaders(connData); 62 | return HTTPD_CGI_MORE; 63 | } 64 | 65 | len = espFsRead(file, buff, 1024); 66 | if (len > 0) 67 | espconn_sent(connData->conn, (uint8 *)buff, len); 68 | if (len != 1024) { 69 | // We're done. 70 | espFsClose(file); 71 | return HTTPD_CGI_DONE; 72 | } else { 73 | // Ok, till next time. 74 | return HTTPD_CGI_MORE; 75 | } 76 | } 77 | 78 | // cgiEspFsTemplate can be used as a template. 79 | 80 | typedef struct { 81 | EspFsFile *file; 82 | void *tplArg; 83 | char token[64]; 84 | int tokenPos; 85 | } TplData; 86 | 87 | typedef void (*TplCallback)(HttpdConnData *connData, char *token, void **arg); 88 | 89 | int ICACHE_FLASH_ATTR cgiEspFsTemplate(HttpdConnData *connData) { 90 | TplData *tpd = connData->cgiData; 91 | int len; 92 | int x, sp = 0; 93 | char *e = NULL; 94 | char buff[1025]; 95 | 96 | if (connData->conn == NULL) { 97 | // Connection aborted. Clean up. 98 | ((TplCallback)(connData->cgiArg))(connData, NULL, &tpd->tplArg); 99 | espFsClose(tpd->file); 100 | os_free(tpd); 101 | return HTTPD_CGI_DONE; 102 | } 103 | 104 | if (tpd == NULL) { 105 | // First call to this cgi. Open the file so we can read it. 106 | tpd = (TplData *)os_malloc(sizeof(TplData)); 107 | tpd->file = espFsOpen(connData->url); 108 | tpd->tplArg = NULL; 109 | tpd->tokenPos = -1; 110 | if (tpd->file == NULL) { 111 | espFsClose(tpd->file); 112 | os_free(tpd); 113 | return HTTPD_CGI_NOTFOUND; 114 | } 115 | connData->cgiData = tpd; 116 | httpdStartResponse(connData, 200); 117 | httpdHeader(connData, "Content-Type", httpdGetMimetype(connData->url)); 118 | httpdEndHeaders(connData); 119 | return HTTPD_CGI_MORE; 120 | } 121 | 122 | len = espFsRead(tpd->file, buff, 1024); 123 | if (len > 0) { 124 | sp = 0; 125 | e = buff; 126 | for (x = 0; x < len; x++) { 127 | if (tpd->tokenPos == -1) { 128 | // Inside ordinary text. 129 | if (buff[x] == '%') { 130 | // Send raw data up to now 131 | if (sp != 0) 132 | httpdSend(connData, e, sp); 133 | sp = 0; 134 | // Go collect token chars. 135 | tpd->tokenPos = 0; 136 | } else { 137 | sp++; 138 | } 139 | } else { 140 | if (buff[x] == '%') { 141 | if (tpd->tokenPos == 0) { 142 | // This is the second % of a %% escape string. 143 | // Send a single % and resume with the normal program flow. 144 | httpdSend(connData, "%", 1); 145 | } else { 146 | // This is an actual token. 147 | tpd->token[tpd->tokenPos++] = 0; // zero-terminate token 148 | ((TplCallback)(connData->cgiArg))(connData, tpd->token, &tpd->tplArg); 149 | } 150 | // Go collect normal chars again. 151 | e = &buff[x + 1]; 152 | tpd->tokenPos = -1; 153 | } else { 154 | if (tpd->tokenPos < (sizeof(tpd->token) - 1)) 155 | tpd->token[tpd->tokenPos++] = buff[x]; 156 | } 157 | } 158 | } 159 | } 160 | // Send remaining bit. 161 | if (sp != 0) 162 | httpdSend(connData, e, sp); 163 | if (len != 1024) { 164 | // We're done. 165 | ((TplCallback)(connData->cgiArg))(connData, NULL, &tpd->tplArg); 166 | espFsClose(tpd->file); 167 | os_free(tpd); 168 | return HTTPD_CGI_DONE; 169 | } else { 170 | // Ok, till next time. 171 | return HTTPD_CGI_MORE; 172 | } 173 | } 174 | -------------------------------------------------------------------------------- /src/user/io.c: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * ---------------------------------------------------------------------------- 4 | * "THE BEER-WARE LICENSE" (Revision 42): 5 | * Jeroen Domburg wrote this file. As long as you retain 6 | * this notice you can do whatever you want with this stuff. If we meet some day, 7 | * and you think this stuff is worth it, you can buy me a beer in return. 8 | * ---------------------------------------------------------------------------- 9 | */ 10 | 11 | #include "c_types.h" 12 | #include "ets_sys.h" 13 | #include "user_interface.h" 14 | //#include "espconn.h" 15 | #include "config.h" 16 | #include "gpio.h" 17 | #include "mem.h" 18 | #include "osapi.h" 19 | 20 | #include "espmissingincludes.h" 21 | #define BTNGPIO 0 22 | 23 | static ETSTimer resetBtntimer; 24 | 25 | char relay1State = 0; 26 | char relay2State = 0; 27 | char relay3State = 0; 28 | 29 | void ICACHE_FLASH_ATTR ioGPIO(int ena, int gpio) { 30 | // gpio_output_set is overkill. ToDo: use better macros 31 | if (ena) { 32 | gpio_output_set((1 << gpio), 0, (1 << gpio), 0); 33 | } else { 34 | gpio_output_set(0, (1 << gpio), (1 << gpio), 0); 35 | } 36 | } 37 | 38 | void ICACHE_FLASH_ATTR relayOnOff(int onOff, int relayNumber) { 39 | 40 | if (relayNumber == 1 && !sysCfg.relay1_thermostat && sysCfg.relay_total > 0) { 41 | ioGPIO(onOff, RELAY1GPIO); 42 | relay1State = onOff; 43 | if (sysCfg.relay_latching_enable) { 44 | sysCfg.relay1_state = onOff; 45 | CFG_Save(); 46 | } 47 | } else if (relayNumber == 2 && !sysCfg.relay2_thermostat && sysCfg.relay_total > 1) { 48 | ioGPIO(onOff, RELAY2GPIO); 49 | relay2State = onOff; 50 | if (sysCfg.relay_latching_enable) { 51 | sysCfg.relay2_state = onOff; 52 | CFG_Save(); 53 | } 54 | } else if (relayNumber == 3 && !sysCfg.relay3_thermostat && sysCfg.relay_total > 2) { 55 | ioGPIO(onOff, RELAY3GPIO); 56 | relay3State = onOff; 57 | if (sysCfg.relay_latching_enable) { 58 | sysCfg.relay3_state = onOff; 59 | CFG_Save(); 60 | } 61 | } else { 62 | os_printf( 63 | "relayOnOff:Invalid relay number %d or relay is controlled by thermostat only (configured for %d relays).\n", 64 | relayNumber, sysCfg.relay_total); 65 | } 66 | } 67 | 68 | static void ICACHE_FLASH_ATTR resetBtnTimerCb(void *arg) { 69 | static int resetCnt = 0; 70 | if (!GPIO_INPUT_GET(BTNGPIO)) { 71 | resetCnt++; 72 | } else { 73 | if (resetCnt >= 6) { // 3 sec pressed 74 | wifi_station_disconnect(); 75 | wifi_set_opmode(0x3); // reset to AP+STA mode 76 | os_printf("Reset to AP mode. Restarting system...\n"); 77 | system_restart(); 78 | } 79 | resetCnt = 0; 80 | } 81 | } 82 | 83 | void ICACHE_FLASH_ATTR ioInit() { 84 | 85 | // Set GPIO0, GPIO12-14 to output mode 86 | PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDI_U, FUNC_GPIO12); 87 | PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, FUNC_GPIO13); 88 | PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, FUNC_GPIO15); 89 | PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO0_U, FUNC_GPIO0); 90 | 91 | // set GPIO to init state 92 | GPIO_OUTPUT_SET(0, (1 << 0)); 93 | // GPIO_OUTPUT_SET(2,0); 94 | 95 | if (sysCfg.relay_latching_enable) { 96 | 97 | os_printf("Relay latching is %d, Relay1=%d,Relay2=%d,Relay3=%d\n\r", (int)sysCfg.relay_latching_enable, 98 | (int)sysCfg.relay1_state, (int)sysCfg.relay2_state, (int)sysCfg.relay3_state); 99 | 100 | relay1State = (int)sysCfg.relay1_state; 101 | relay2State = (int)sysCfg.relay2_state; 102 | relay3State = (int)sysCfg.relay3_state; 103 | 104 | ioGPIO((int)sysCfg.relay1_state, RELAY1GPIO); 105 | ioGPIO((int)sysCfg.relay2_state, RELAY2GPIO); 106 | ioGPIO((int)sysCfg.relay3_state, RELAY3GPIO); 107 | } 108 | 109 | else { 110 | ioGPIO(0, RELAY1GPIO); 111 | ioGPIO(0, RELAY2GPIO); 112 | ioGPIO(0, RELAY3GPIO); 113 | } 114 | 115 | // gpio_output_set(0, 0, (1<<12), (1< 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * 9 | * * Redistributions of source code must retain the above copyright notice, 10 | * this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * * Neither the name of Redis nor the names of its contributors may be used 15 | * to endorse or promote products derived from this software without 16 | * specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 22 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | * POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | #include "mqueue.h" 31 | 32 | #include "mem.h" 33 | #include "os_type.h" 34 | #include "osapi.h" 35 | #include "proto.h" 36 | #include "user_interface.h" 37 | void ICACHE_FLASH_ATTR QUEUE_Init(QUEUE *queue, int bufferSize) { 38 | queue->buf = (uint8_t *)os_zalloc(bufferSize); 39 | RINGBUF_Init(&queue->rb, queue->buf, bufferSize); 40 | } 41 | int32_t ICACHE_FLASH_ATTR QUEUE_Puts(QUEUE *queue, uint8_t *buffer, uint16_t len) { 42 | return PROTO_AddRb(&queue->rb, buffer, len); 43 | } 44 | int32_t ICACHE_FLASH_ATTR QUEUE_Gets(QUEUE *queue, uint8_t *buffer, uint16_t *len, uint16_t maxLen) { 45 | 46 | return PROTO_ParseRb(&queue->rb, buffer, len, maxLen); 47 | } 48 | 49 | BOOL ICACHE_FLASH_ATTR QUEUE_IsEmpty(QUEUE *queue) { 50 | if (queue->rb.fill_cnt <= 0) 51 | return TRUE; 52 | return FALSE; 53 | } 54 | -------------------------------------------------------------------------------- /src/user/proto.c: -------------------------------------------------------------------------------- 1 | #include "proto.h" 2 | #include "ringbuf.h" 3 | I8 ICACHE_FLASH_ATTR PROTO_Init(PROTO_PARSER *parser, PROTO_PARSE_CALLBACK *completeCallback, U8 *buf, U16 bufSize) 4 | { 5 | parser->buf = buf; 6 | parser->bufSize = bufSize; 7 | parser->dataLen = 0; 8 | parser->callback = completeCallback; 9 | parser->isEsc = 0; 10 | return 0; 11 | } 12 | 13 | I8 ICACHE_FLASH_ATTR PROTO_ParseByte(PROTO_PARSER *parser, U8 value) 14 | { 15 | switch(value){ 16 | case 0x7D: 17 | parser->isEsc = 1; 18 | break; 19 | 20 | case 0x7E: 21 | parser->dataLen = 0; 22 | parser->isEsc = 0; 23 | parser->isBegin = 1; 24 | break; 25 | 26 | case 0x7F: 27 | if (parser->callback != NULL) 28 | parser->callback(); 29 | parser->isBegin = 0; 30 | return 0; 31 | break; 32 | 33 | default: 34 | if(parser->isBegin == 0) break; 35 | 36 | if(parser->isEsc){ 37 | value ^= 0x20; 38 | parser->isEsc = 0; 39 | } 40 | 41 | if(parser->dataLen < parser->bufSize) 42 | parser->buf[parser->dataLen++] = value; 43 | 44 | break; 45 | } 46 | return -1; 47 | } 48 | 49 | I8 ICACHE_FLASH_ATTR PROTO_Parse(PROTO_PARSER *parser, U8 *buf, U16 len) 50 | { 51 | while(len--) 52 | PROTO_ParseByte(parser, *buf++); 53 | 54 | return 0; 55 | } 56 | I16 ICACHE_FLASH_ATTR PROTO_ParseRb(RINGBUF* rb, U8 *bufOut, U16* len, U16 maxBufLen) 57 | { 58 | U8 c; 59 | 60 | PROTO_PARSER proto; 61 | PROTO_Init(&proto, NULL, bufOut, maxBufLen); 62 | while(RINGBUF_Get(rb, &c) == 0){ 63 | if(PROTO_ParseByte(&proto, c) == 0){ 64 | *len = proto.dataLen; 65 | return 0; 66 | } 67 | } 68 | return -1; 69 | } 70 | I16 ICACHE_FLASH_ATTR PROTO_Add(U8 *buf, const U8 *packet, I16 bufSize) 71 | { 72 | U16 i = 2; 73 | U16 len = *(U16*) packet; 74 | 75 | if (bufSize < 1) return -1; 76 | 77 | *buf++ = 0x7E; 78 | bufSize--; 79 | 80 | while (len--) { 81 | switch (*packet) { 82 | case 0x7D: 83 | case 0x7E: 84 | case 0x7F: 85 | if (bufSize < 2) return -1; 86 | *buf++ = 0x7D; 87 | *buf++ = *packet++ ^ 0x20; 88 | i += 2; 89 | bufSize -= 2; 90 | break; 91 | default: 92 | if (bufSize < 1) return -1; 93 | *buf++ = *packet++; 94 | i++; 95 | bufSize--; 96 | break; 97 | } 98 | } 99 | 100 | if (bufSize < 1) return -1; 101 | *buf++ = 0x7F; 102 | 103 | return i; 104 | } 105 | 106 | I16 ICACHE_FLASH_ATTR PROTO_AddRb(RINGBUF *rb, const U8 *packet, I16 len) 107 | { 108 | U16 i = 2; 109 | 110 | if(RINGBUF_Put(rb, 0x7E) == -1) return -1; 111 | while (len--) { 112 | switch (*packet) { 113 | case 0x7D: 114 | case 0x7E: 115 | case 0x7F: 116 | if(RINGBUF_Put(rb, 0x7D) == -1) return -1; 117 | if(RINGBUF_Put(rb, *packet++ ^ 0x20) == -1) return -1; 118 | i += 2; 119 | break; 120 | default: 121 | if(RINGBUF_Put(rb, *packet++) == -1) return -1; 122 | i++; 123 | break; 124 | } 125 | } 126 | if(RINGBUF_Put(rb, 0x7F) == -1) return -1; 127 | return i; 128 | } 129 | 130 | -------------------------------------------------------------------------------- /src/user/ringbuf.c: -------------------------------------------------------------------------------- 1 | /** 2 | * \file 3 | * Ring Buffer library 4 | */ 5 | 6 | #include "ringbuf.h" 7 | 8 | 9 | /** 10 | * \brief init a RINGBUF object 11 | * \param r pointer to a RINGBUF object 12 | * \param buf pointer to a byte array 13 | * \param size size of buf 14 | * \return 0 if successfull, otherwise failed 15 | */ 16 | I16 ICACHE_FLASH_ATTR RINGBUF_Init(RINGBUF *r, U8* buf, I32 size) 17 | { 18 | if(r == NULL || buf == NULL || size < 2) return -1; 19 | 20 | r->p_o = r->p_r = r->p_w = buf; 21 | r->fill_cnt = 0; 22 | r->size = size; 23 | 24 | return 0; 25 | } 26 | /** 27 | * \brief put a character into ring buffer 28 | * \param r pointer to a ringbuf object 29 | * \param c character to be put 30 | * \return 0 if successfull, otherwise failed 31 | */ 32 | I16 ICACHE_FLASH_ATTR RINGBUF_Put(RINGBUF *r, U8 c) 33 | { 34 | if(r->fill_cnt>=r->size)return -1; // ring buffer is full, this should be atomic operation 35 | 36 | 37 | r->fill_cnt++; // increase filled slots count, this should be atomic operation 38 | 39 | 40 | *r->p_w++ = c; // put character into buffer 41 | 42 | if(r->p_w >= r->p_o + r->size) // rollback if write pointer go pass 43 | r->p_w = r->p_o; // the physical boundary 44 | 45 | return 0; 46 | } 47 | /** 48 | * \brief get a character from ring buffer 49 | * \param r pointer to a ringbuf object 50 | * \param c read character 51 | * \return 0 if successfull, otherwise failed 52 | */ 53 | I16 ICACHE_FLASH_ATTR RINGBUF_Get(RINGBUF *r, U8* c) 54 | { 55 | if(r->fill_cnt<=0)return -1; // ring buffer is empty, this should be atomic operation 56 | 57 | 58 | r->fill_cnt--; // decrease filled slots count 59 | 60 | 61 | *c = *r->p_r++; // get the character out 62 | 63 | if(r->p_r >= r->p_o + r->size) // rollback if write pointer go pass 64 | r->p_r = r->p_o; // the physical boundary 65 | 66 | return 0; 67 | } 68 | -------------------------------------------------------------------------------- /src/user/syslog.c: -------------------------------------------------------------------------------- 1 | #define DEFAULT_LAN_PORT 12476 2 | #include "lwip/ip_addr.h" 3 | 4 | #include "config.h" 5 | #include "espconn.h" 6 | #include "mem.h" 7 | #include "stdarg.h" 8 | 9 | #include 10 | 11 | struct espconn pssdpudpconn; 12 | esp_udp ssdp_udp; 13 | 14 | void parseBytes(const char *str, char sep, uint8_t *bytes, int maxBytes, int base) { 15 | for (int i = 0; i < maxBytes; i++) { 16 | bytes[i] = strtoul(str, NULL, base); // Convert byte 17 | str = strchr(str, sep); // Find next separator 18 | if (str == NULL || *str == '\0') { 19 | break; // No more separators, exit 20 | } 21 | str++; // Point to next character after separator 22 | } 23 | } 24 | 25 | void syslog(const char *format, ...) { 26 | 27 | char buff[256] = ""; 28 | char sysid[12] = ""; 29 | ssdp_udp.remote_port = 514; 30 | 31 | os_sprintf(sysid, "%02X: ", system_get_chip_id()); 32 | strcat(buff, sysid); 33 | 34 | va_list args; 35 | va_start(args, format); 36 | ets_vsnprintf(&buff[7], 244, format, args); 37 | va_end(args); 38 | 39 | if (sysCfg.syslog_enable) { 40 | 41 | parseBytes((const char *)sysCfg.syslog_host, '.', ssdp_udp.remote_ip, 4, 10); 42 | 43 | /* 44 | ssdp_udp.remote_ip[0] = 192; 45 | ssdp_udp.remote_ip[1] = 168; 46 | ssdp_udp.remote_ip[2] = 10; 47 | ssdp_udp.remote_ip[3] = 7; 48 | */ 49 | ssdp_udp.local_port = DEFAULT_LAN_PORT; 50 | pssdpudpconn.type = ESPCONN_UDP; 51 | pssdpudpconn.proto.udp = &(ssdp_udp); 52 | 53 | espconn_create(&pssdpudpconn); 54 | 55 | int len = strlen(buff); 56 | int ret = espconn_sendto(&pssdpudpconn, (uint8_t *)buff, len); 57 | if (ret != 0) { 58 | os_printf("syslog: UDP send error!"); 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/user/time_utils.c: -------------------------------------------------------------------------------- 1 | 2 | #include "c_types.h" 3 | #include "config.h" 4 | #include "espmissingincludes.h" 5 | #include "lwip/sntp.h" 6 | #include "osapi.h" 7 | 8 | #define IS_LEAP(year) (year % 4 == 0) 9 | #define SEC_IN_NON_LEAP (86400 * 365) 10 | #define SEC_IN_LEAP (86400 * 366) 11 | #define SEC_IN_YEAR(year) (IS_LEAP(year) ? SEC_IN_LEAP : SEC_IN_NON_LEAP) 12 | 13 | char buf[30]; 14 | 15 | unsigned char calendar[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; 16 | unsigned char calendar_leap[] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; 17 | 18 | unsigned char *get_calendar(int year) { return IS_LEAP(year) ? calendar_leap : calendar; } 19 | 20 | // take epoch, cycle through it, subtracting one years worth of 21 | // seconds at a time, and count the years as you 22 | // go, until you have less seconds left in epoch 23 | // than in year. Congrats you iterator is the current year, 24 | // but epoch is now somewhere in 1970... 25 | int ICACHE_FLASH_ATTR get_year(unsigned long *t) { 26 | int year = 1970; 27 | while (*t > SEC_IN_YEAR(year)) { 28 | *t -= SEC_IN_YEAR(year); 29 | year++; 30 | } 31 | return year; 32 | } 33 | 34 | // work out day of week. Crazy date math 35 | // https://cs.uwaterloo.ca/~alopez-o/math-faq/node73.html 36 | // Monday is 0. 37 | int ICACHE_FLASH_ATTR wd(int year, int month, int day) { 38 | size_t JND = day + ((153 * (month + 12 * ((14 - month) / 12) - 3) + 2) / 5) + 39 | (365 * (year + 4800 - ((14 - month) / 12))) + ((year + 4800 - ((14 - month) / 12)) / 4) - 40 | ((year + 4800 - ((14 - month) / 12)) / 100) + ((year + 4800 - ((14 - month) / 12)) / 400) - 32045; 41 | return (int)JND % 7; 42 | } 43 | 44 | // see get_year expaination below. 45 | // Same principle here, except we subtract seconds in a month 46 | // taking care of leapyears. Iterator is your month 47 | int ICACHE_FLASH_ATTR get_month(unsigned long *t, int year) { 48 | unsigned char *cal = get_calendar(year); 49 | int i = 0; 50 | while (*t > cal[i] * 86400) { 51 | *t -= cal[i] * 86400; 52 | i++; 53 | } 54 | return i + 1; 55 | } 56 | 57 | char *ICACHE_FLASH_ATTR epoch_to_str(unsigned long epoch) { 58 | int year = get_year(&epoch); 59 | unsigned char month = get_month(&epoch, year); 60 | unsigned char day = 1 + (epoch / 86400); 61 | epoch = epoch % 86400; 62 | unsigned char hour = epoch / 3600; 63 | epoch %= 3600; 64 | unsigned char min = epoch / 60; 65 | unsigned char sec = epoch % 60; 66 | 67 | os_sprintf(buf, "%02d:%02d:%02d %02d/%02d/%02d", hour, min, sec, day, month, year); 68 | 69 | return buf; 70 | } 71 | 72 | char *ICACHE_FLASH_ATTR epoch_to_str_hhmm(unsigned long epoch) { 73 | epoch = epoch % 86400; 74 | unsigned char hour = epoch / 3600; 75 | epoch %= 3600; 76 | unsigned char min = epoch / 60; 77 | 78 | os_sprintf(buf, "%02d:%02d", hour, min); 79 | return buf; 80 | } 81 | 82 | bool IsDST_EU(int day, int month, int dow) { 83 | if (month < 3 || month > 10) 84 | return false; 85 | if (month > 3 && month < 10) 86 | return true; 87 | 88 | int previousSunday = day - (dow+1); 89 | 90 | if (month == 3) { 91 | return previousSunday >= 18; 92 | } 93 | if (month == 10) 94 | return previousSunday < 25; 95 | 96 | return false; // this line never going to happen 97 | } 98 | 99 | bool IsDST_NA(int day, int month, int dow) { 100 | // January, February, and December are out. 101 | if (month < 3 || month > 11) { 102 | return false; 103 | } 104 | // April to October are in 105 | if (month > 3 && month < 11) { 106 | return true; 107 | } 108 | int previousSunday = day - dow; 109 | // In march, we are DST if our previous Sunday was on or after the 8th. 110 | if (month == 3) { 111 | return previousSunday >= 8; 112 | } 113 | // In November we must be before the first Sunday to be DST. 114 | // That means the previous Sunday must be before the 1st. 115 | return previousSunday <= 1; 116 | } 117 | 118 | uint64 get_current_timestamp_dst() { 119 | // Return timestamp with DST adjustment 120 | 121 | unsigned long epoch = sntp_get_current_timestamp(); 122 | 123 | // both get_year and get_month appear to manipulate epoch, 124 | // so don't use the epoch variable after they have been called. 125 | int year = get_year(&epoch); 126 | int month = get_month(&epoch, year); 127 | int day = day = 1 + (epoch / 86400); 128 | int dow = wd(year, month, day); 129 | 130 | // os_printf("sntp : %d, %s \n", epoch, sntp_get_real_time(epoch)); 131 | 132 | if (sysCfg.DST == 1) { 133 | // Europe DST 134 | if (IsDST_EU(day, month, dow)) { 135 | return (sntp_get_current_timestamp() + 3600); 136 | } else { 137 | return (sntp_get_current_timestamp()); 138 | } 139 | } else if (sysCfg.DST == 2) { 140 | // US DST 141 | if (IsDST_NA(day, month, dow)) { 142 | return (sntp_get_current_timestamp() + 3600); 143 | } else { 144 | return (sntp_get_current_timestamp()); 145 | } 146 | } 147 | return (sntp_get_current_timestamp()); 148 | } 149 | -------------------------------------------------------------------------------- /src/user/utils.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, Tuan PM 3 | * Email: tuanpm@live.com 4 | * 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions 9 | * are met: 10 | * 11 | * 1. Redistributions of source code must retain the above copyright 12 | * notice, this list of conditions and the following disclaimer. 13 | * 2. Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in the 15 | * documentation and/or other materials provided with the distribution. 16 | * 3. Neither the name of the copyright holder nor the names of its 17 | * contributors may be used to endorse or promote products derived 18 | * from this software without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 24 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 | * POSSIBILITY OF SUCH DAMAGE. 31 | * 32 | */ 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include "utils.h" 39 | 40 | 41 | uint8_t ICACHE_FLASH_ATTR UTILS_IsIPV4 (int8_t *str) 42 | { 43 | uint8_t segs = 0; /* Segment count. */ 44 | uint8_t chcnt = 0; /* Character count within segment. */ 45 | uint8_t accum = 0; /* Accumulator for segment. */ 46 | /* Catch NULL pointer. */ 47 | if (str == 0) 48 | return 0; 49 | /* Process every character in string. */ 50 | 51 | while (*str != '\0') { 52 | /* Segment changeover. */ 53 | 54 | if (*str == '.') { 55 | /* Must have some digits in segment. */ 56 | if (chcnt == 0) 57 | return 0; 58 | /* Limit number of segments. */ 59 | if (++segs == 4) 60 | return 0; 61 | /* Reset segment values and restart loop. */ 62 | chcnt = accum = 0; 63 | str++; 64 | continue; 65 | } 66 | 67 | /* Check numeric. */ 68 | if ((*str < '0') || (*str > '9')) 69 | return 0; 70 | 71 | /* Accumulate and check segment. */ 72 | 73 | if ((accum = accum * 10 + *str - '0') > 255) 74 | return 0; 75 | /* Advance other segment specific stuff and continue loop. */ 76 | 77 | chcnt++; 78 | str++; 79 | } 80 | 81 | /* Check enough segments and enough characters in last segment. */ 82 | 83 | if (segs != 3) 84 | return 0; 85 | if (chcnt == 0) 86 | return 0; 87 | /* Address okay. */ 88 | 89 | return 1; 90 | } 91 | uint8_t ICACHE_FLASH_ATTR UTILS_StrToIP(const int8_t* str, void *ip) 92 | { 93 | 94 | /* The count of the number of bytes processed. */ 95 | int i; 96 | /* A pointer to the next digit to process. */ 97 | const char * start; 98 | 99 | start = (const char * )str; 100 | for (i = 0; i < 4; i++) { 101 | /* The digit being processed. */ 102 | char c; 103 | /* The value of this byte. */ 104 | int n = 0; 105 | while (1) { 106 | c = * start; 107 | start++; 108 | if (c >= '0' && c <= '9') { 109 | n *= 10; 110 | n += c - '0'; 111 | } 112 | /* We insist on stopping at "." if we are still parsing 113 | the first, second, or third numbers. If we have reached 114 | the end of the numbers, we will allow any character. */ 115 | else if ((i < 3 && c == '.') || i == 3) { 116 | break; 117 | } 118 | else { 119 | return 0; 120 | } 121 | } 122 | if (n >= 256) { 123 | return 0; 124 | } 125 | ((uint8_t*)ip)[i] = n; 126 | } 127 | return 1; 128 | 129 | } 130 | uint32_t ICACHE_FLASH_ATTR UTILS_Atoh(const int8_t *s) 131 | { 132 | uint32_t value = 0, digit; 133 | int8_t c; 134 | 135 | while((c = *s++)){ 136 | if('0' <= c && c <= '9') 137 | digit = c - '0'; 138 | else if('A' <= c && c <= 'F') 139 | digit = c - 'A' + 10; 140 | else if('a' <= c && c<= 'f') 141 | digit = c - 'a' + 10; 142 | else break; 143 | 144 | value = (value << 4) | digit; 145 | } 146 | 147 | return value; 148 | } 149 | 150 | -------------------------------------------------------------------------------- /src/user/wifi.c: -------------------------------------------------------------------------------- 1 | /* 2 | * wifi.c 3 | * 4 | * Created on: Dec 30, 2014 5 | * Author: Minh 6 | */ 7 | 8 | #include "user_interface.h" 9 | 10 | #include "config.h" 11 | #include "debug.h" 12 | #include "espconn.h" 13 | #include "mem.h" 14 | #include "os_type.h" 15 | #include "osapi.h" 16 | #include "wifi.h" 17 | 18 | static ETSTimer WiFiLinker; 19 | WifiCallback wifiCb = NULL; 20 | static uint8_t wifiStatus = STATION_IDLE, lastWifiStatus = STATION_IDLE; 21 | 22 | static void ICACHE_FLASH_ATTR wifi_check_ip(void *arg) { 23 | struct ip_info ipConfig; 24 | 25 | os_timer_disarm(&WiFiLinker); 26 | wifi_get_ip_info(STATION_IF, &ipConfig); 27 | wifiStatus = wifi_station_get_connect_status(); 28 | if (wifiStatus == STATION_GOT_IP && ipConfig.ip.addr != 0) { 29 | os_timer_setfn(&WiFiLinker, (os_timer_func_t *)wifi_check_ip, NULL); 30 | os_timer_arm(&WiFiLinker, 2000, 0); 31 | } else { 32 | if (wifi_station_get_connect_status() == STATION_WRONG_PASSWORD) { 33 | INFO("STATION_WRONG_PASSWORD\r\n"); 34 | wifi_station_connect(); 35 | } else if (wifi_station_get_connect_status() == STATION_NO_AP_FOUND) { 36 | 37 | INFO("STATION_NO_AP_FOUND\r\n"); 38 | wifi_station_connect(); 39 | } else if (wifi_station_get_connect_status() == STATION_CONNECT_FAIL) { 40 | 41 | INFO("STATION_CONNECT_FAIL\r\n"); 42 | wifi_station_connect(); 43 | } else if (wifi_station_get_connect_status() == STATION_IDLE) { 44 | INFO("STATION_IDLE\r\n"); 45 | } else if (wifi_station_get_connect_status() == STATION_CONNECTING) { 46 | INFO("STATION_CONNECTING\r\n"); 47 | } else if (wifi_station_get_connect_status() == STATION_GOT_IP) { 48 | INFO("STATION_STATION_GOT_IP\r\n"); 49 | } else { 50 | os_printf("%s: status = %d\n\r", __func__, wifi_station_get_connect_status()); 51 | } 52 | 53 | os_timer_setfn(&WiFiLinker, (os_timer_func_t *)wifi_check_ip, NULL); 54 | os_timer_arm(&WiFiLinker, 500, 0); 55 | } 56 | if (wifiStatus != lastWifiStatus) { 57 | lastWifiStatus = wifiStatus; 58 | if (wifiCb) 59 | wifiCb(wifiStatus); 60 | } 61 | } 62 | 63 | void ICACHE_FLASH_ATTR WIFI_Connect(WifiCallback cb) { 64 | struct station_config stationConf; 65 | struct ip_info info; 66 | 67 | INFO("WIFI_INIT\r\n"); 68 | os_timer_disarm(&WiFiLinker); 69 | 70 | // wifi_set_opmode(STATION_MODE); 71 | wifi_station_set_auto_connect(FALSE); 72 | 73 | wifiCb = cb; 74 | 75 | os_memset(&stationConf, 0, sizeof(struct station_config)); 76 | 77 | os_sprintf((char *)stationConf.ssid, "%s", sysCfg.sta_ssid); 78 | os_sprintf((char *)stationConf.password, "%s", sysCfg.sta_pass); 79 | 80 | wifi_get_ip_info(STATION_IF, &info); 81 | char *dhcp = (char *)sysCfg.sta_mode; 82 | char *ip, *mask, *gw; 83 | if (!dhcp || strcmp(dhcp, "dhcp") != 0) { 84 | ip = (char *)sysCfg.sta_ip; 85 | mask = (char *)sysCfg.sta_mask; 86 | gw = (char *)sysCfg.sta_gw; 87 | if (ip) 88 | info.ip.addr = ipaddr_addr(ip); 89 | if (mask) 90 | info.netmask.addr = ipaddr_addr(mask); 91 | if (gw) 92 | info.gw.addr = ipaddr_addr(gw); 93 | wifi_set_ip_info(STATION_IF, &info); 94 | } 95 | 96 | wifi_get_ip_info(SOFTAP_IF, &info); 97 | ip = (char *)sysCfg.ap_ip; 98 | mask = (char *)sysCfg.ap_mask; 99 | gw = (char *)sysCfg.ap_gw; 100 | if (ip) 101 | info.ip.addr = ipaddr_addr(ip); 102 | if (mask) 103 | info.netmask.addr = ipaddr_addr(mask); 104 | if (gw) 105 | info.gw.addr = ipaddr_addr(gw); 106 | 107 | if (wifi_get_opmode() != STATION_MODE) 108 | wifi_set_ip_info(SOFTAP_IF, &info); 109 | 110 | wifi_station_set_config(&stationConf); 111 | 112 | os_timer_disarm(&WiFiLinker); 113 | os_timer_setfn(&WiFiLinker, (os_timer_func_t *)wifi_check_ip, NULL); 114 | os_timer_arm(&WiFiLinker, 1000, 0); 115 | 116 | wifi_station_set_auto_connect(TRUE); 117 | wifi_station_connect(); 118 | } 119 | -------------------------------------------------------------------------------- /upload_schedule.sh: -------------------------------------------------------------------------------- 1 | curl 'http://192.168.10.239/control/thermostat.cgi?param=thermostat_schedule' \ 2 | -X 'POST' \ 3 | -H 'Accept: text/plain, */*; q=0.01' \ 4 | -H 'Origin: http://heating.pearson.uk' \ 5 | -H 'Content-Type: application/x-www-form-urlencoded; charset=UTF-8' \ 6 | -H 'Referer: http://heating.pearson.uk/control/thermostat.html' \ 7 | -H 'Content-Length: 201' \ 8 | -H 'Host: heating.pearson.uk' \ 9 | -H 'Accept-Language: en-gb' \ 10 | -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.6.1 Safari/605.1.15' \ 11 | -H 'Accept-Encoding: gzip, deflate' \ 12 | -H 'Connection: keep-alive' \ 13 | -H 'X-Requested-With: XMLHttpRequest' \ 14 | --data '{"sun":[{"s":0,"e":100,"sp":100},{"s":100,"e":300,"sp":205},{"s":300,"e":645,"sp":150},{"s":645,"e":945,"sp":205},{"s":945,"e":1730,"sp":100},{"s":1730,"e":2130,"sp":205},{"s":2130,"e":2400,"sp":100}]}' 15 | 16 | 17 | 18 | #Don't forget to change --length parameter to curl above 19 | -------------------------------------------------------------------------------- /wiflash: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | # 3 | # Flash an esp8266 over wifi. This communicates with the esphttpd's /flash handlers 4 | # and POSTS the correct binary depending on the parittion that needs to be flashed 5 | # next. 6 | # 7 | # ---------------------------------------------------------------------------- 8 | # "THE BEER-WARE LICENSE" (Revision 42): 9 | # Thorsten von Eicken wrote this file. As long as you retain 10 | # this notice you can do whatever you want with this stuff. If we meet some day, 11 | # and you think this stuff is worth it, you can buy me a beer in return. 12 | # ---------------------------------------------------------------------------- 13 | 14 | show_help() { 15 | cat < with either or 18 | depending on its current state. Reboot the esp8266 after flashing and wait for it to come 19 | up again. 20 | -v Be verbose 21 | -h show this help 22 | 23 | Example: ${0##*/} -v esp8266 firmware/user1.bin firmware/user2.bin 24 | ${0##*/} 192.168.4.1 firmware/user1.bin firmware/user2.bin 25 | EOT 26 | } 27 | 28 | if ! which curl >/dev/null; then 29 | echo "ERROR: Cannot find curl: it is required for this script." >&2 30 | exit 1 31 | fi 32 | 33 | start=`date +%s` 34 | 35 | # ===== Parse arguments 36 | 37 | verbose= 38 | 39 | while getopts "hvx:" opt; do 40 | case "$opt" in 41 | h) show_help; exit 0 ;; 42 | v) verbose=1 ;; 43 | x) foo="$OPTARG" ;; 44 | '?') show_help >&2; exit 1 ;; 45 | esac 46 | done 47 | 48 | # Shift off the options and optional --. 49 | shift "$((OPTIND-1))" 50 | 51 | # Get the fixed arguments 52 | if [[ $# != 3 ]]; then 53 | show_help >&2 54 | exit 1 55 | fi 56 | hostname=$1 57 | user1=$2 58 | user2=$3 59 | 60 | re='[-A-Za-z0-9.]+' 61 | if [[ ! "$hostname" =~ $re ]]; then 62 | echo "ERROR: hostname ${hostname} is not a valid hostname or ip address" >&2 63 | exit 1 64 | fi 65 | 66 | if [[ ! -r "$user1" ]]; then 67 | echo "ERROR: cannot read user1 firmware file ($user1)" >&2 68 | exit 1 69 | fi 70 | 71 | if [[ ! -r "$user2" ]]; then 72 | echo "ERROR: cannot read user2 firmware file ($user2)" >&2 73 | exit 1 74 | fi 75 | 76 | # ===== Retrieve the 'next' firmware required 77 | 78 | fw= 79 | while true; do 80 | [[ -n "$verbose" ]] && echo "Fetching http://$hostname/flash/next" >&2 81 | v=; [[ -n "$verbose" ]] && v=-v 82 | next=`curl -m 10 $v -s "http://$hostname/flash/next"` 83 | if [[ $? != 0 ]]; then 84 | echo "Error retrieving http://$hostname/flash/next" >&2 85 | exit 1 86 | fi 87 | case "$next" in 88 | user1.bin) 89 | echo "Flashing user1.bin" >&2 90 | fw="$user1" 91 | break;; 92 | user2.bin) 93 | echo "Flashing user2.bin" >&2 94 | fw="$user2" 95 | break;; 96 | *) 97 | echo "Error retrieving or parsing http://$hostname/flash/next" >&2 98 | exit 1 99 | ;; 100 | esac 101 | done 102 | 103 | #silent=-s 104 | [[ -n "$verbose" ]] && silent= 105 | res=`curl $silent -XPOST --data-binary "@$fw" "http://$hostname/flash/upload"` 106 | if [[ $? != 0 ]]; then 107 | echo "Error flashing $fw" >&2 108 | exit 1 109 | fi 110 | 111 | res=`curl $silent -XPOST --data-binary "@firmware/webpages.espfs" "http://$hostname/flash/upload-espfs"` 112 | 113 | sleep 2 114 | echo "Rebooting into new firmware" >&2 115 | curl -m 10 -s "http://$hostname/flash/reboot" 116 | 117 | sleep 2 118 | echo "Waiting for ESP8266 to come back" 119 | while true; do 120 | [[ -n "$verbose" ]] && echo "Fetching http://$hostname/flash/next" >&2 121 | next2=`curl -m 10 $v -s "http://$hostname/flash/next"` 122 | [[ -n "$verbose" ]] && echo "got: $next2" 123 | re='user[12]\.bin' 124 | if [[ "$next2" =~ $re ]]; then 125 | if [[ "$next2" != "$next" ]]; then 126 | sec=$(( `date +%s` - $start )) 127 | echo "Success, took $sec seconds" >&2 128 | exit 0 129 | else 130 | echo "Flashing seems to have failed and it reverted to the old firmware?" >&2 131 | exit 1 132 | fi 133 | fi 134 | sleep 1 135 | done 136 | --------------------------------------------------------------------------------