32 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/html/config/ntp.tpl:
--------------------------------------------------------------------------------
1 | NTP settings
2 |
3 |
4 |
24 |
25 |
26 |
27 |
32 |
33 |
34 |
35 |
43 |
44 |
--------------------------------------------------------------------------------
/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/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 |
--------------------------------------------------------------------------------
/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/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 |
--------------------------------------------------------------------------------
/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/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 |
--------------------------------------------------------------------------------
/html/config/broadcastd.tpl:
--------------------------------------------------------------------------------
1 | Broadcaset Daemon Settings
2 |
3 |
4 |
28 |
29 |
30 |
31 |
32 |
33 | Broadcast Daemon Settings
34 |
35 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
37 |
38 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
61 |
62 |
63 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 | [](http://travis-ci.org/atomicobject/heatshrink)
50 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/src/user/mqueue.c:
--------------------------------------------------------------------------------
1 | /* str_queue.c
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 | #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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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/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/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/html/config/relay.tpl:
--------------------------------------------------------------------------------
1 | Relay Settings
2 |
3 |
4 |
5 |
6 |
7 |
100 |
129 |
130 |
131 |
132 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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<
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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
Room Temperature:
33 | , Humidity:
34 |
35 |
36 |
37 |
38 |
40 |
41 |
42 |
Schedule
43 |
44 |
45 |
START:
46 | END:
47 | SET:
48 |
49 |
50 |
51 |
TIME:
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
Average schedule temperature: °C
71 |
72 |
73 |
74 |
75 | A full weeks schedule can be downloaded as JSON, however uploads support only one day at a time.
76 | You should edit the JSON and leave a single day schedule (don't forget open and close '{}' and remove trailing ',').
77 | Note, if manually editing the JSON the minute component of the time is NOT real minutes,
78 | but a percentage of the hour. Example 14:15 should be 1425, 14:30 = 1450 etc.
79 | I beleive this is because of lack of date libraries on the ESP device.
80 |
81 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------