├── .gitignore ├── mqtt ├── .gitignore ├── tools │ ├── xxd.exe │ ├── .gitattributes │ └── makefile.sh ├── mqtt │ ├── include │ │ ├── debug.h │ │ ├── utils.h │ │ ├── typedef.h │ │ ├── ringbuf.h │ │ ├── proto.h │ │ ├── queue.h │ │ ├── mqtt_msg.h │ │ └── mqtt.h │ ├── Makefile │ ├── ringbuf.c │ ├── queue.c │ ├── proto.c │ ├── utils.c │ └── mqtt_msg.c ├── modules │ ├── include │ │ ├── wifi.h │ │ └── config.h │ ├── Makefile │ ├── wifi.c │ └── config.c ├── .travis.yml ├── include │ ├── user_config.h │ └── driver │ │ ├── uart.h │ │ └── uart_register.h ├── user │ ├── Makefile │ └── user_main.c ├── driver │ ├── Makefile │ └── uart.c ├── Makefile └── README.md ├── user ├── ntp.h ├── debug.h ├── mqtt.h ├── utils.h ├── config.h ├── user_main.c ├── Makefile ├── config.c ├── ntp.c ├── utils.c ├── mqtt_msg.h └── mqtt_msg.c ├── include ├── at_version.h ├── user_config.h ├── driver │ ├── i2c_oled.h │ ├── i2c.h │ ├── uart.h │ ├── uart_register.h │ └── i2c_oled_fonts.h └── at.h ├── driver ├── Makefile ├── i2c.h ├── i2c_oled.c ├── i2c.c └── uart.c ├── README.md ├── Makefile ├── Makefile.linux ├── Makefile.mac └── Makefile.windows /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | firmware/ 3 | include/user_config.h-real 4 | -------------------------------------------------------------------------------- /mqtt/.gitignore: -------------------------------------------------------------------------------- 1 | .cproject 2 | .project 3 | build/ 4 | firmware/ 5 | .settings/ 6 | .DS_Store -------------------------------------------------------------------------------- /mqtt/tools/xxd.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shantanugoel/esp8266-smartwatch/HEAD/mqtt/tools/xxd.exe -------------------------------------------------------------------------------- /user/ntp.h: -------------------------------------------------------------------------------- 1 | #ifndef NTP_H 2 | #define NTP_H 3 | 4 | unsigned long ntp_get_time(); 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /include/at_version.h: -------------------------------------------------------------------------------- 1 | #ifndef __AT_VERSION_H__ 2 | #define __AT_VERSION_H__ 3 | 4 | #define AT_VERSION_main 0x00 5 | #define AT_VERSION_sub 0x19 6 | 7 | #define AT_VERSION (AT_VERSION_main << 8 | AT_VERSION_sub) 8 | 9 | #endif 10 | -------------------------------------------------------------------------------- /user/debug.h: -------------------------------------------------------------------------------- 1 | /* 2 | * debug.h 3 | * 4 | * Created on: Dec 4, 2014 5 | * Author: Minh 6 | */ 7 | 8 | #ifndef USER_DEBUG_H_ 9 | #define USER_DEBUG_H_ 10 | 11 | 12 | 13 | #define INFO uart0_sendStr 14 | 15 | #endif /* USER_DEBUG_H_ */ 16 | -------------------------------------------------------------------------------- /mqtt/mqtt/include/debug.h: -------------------------------------------------------------------------------- 1 | /* 2 | * debug.h 3 | * 4 | * Created on: Dec 4, 2014 5 | * Author: Minh 6 | */ 7 | 8 | #ifndef USER_DEBUG_H_ 9 | #define USER_DEBUG_H_ 10 | 11 | #ifndef INFO 12 | #define INFO os_printf 13 | #endif 14 | 15 | #endif /* USER_DEBUG_H_ */ 16 | -------------------------------------------------------------------------------- /user/mqtt.h: -------------------------------------------------------------------------------- 1 | /* 2 | * at_mqtt.h 3 | * 4 | * Created on: Nov 28, 2014 5 | * Author: Minh Tuan 6 | */ 7 | 8 | #ifndef USER_AT_MQTT_H_ 9 | #define USER_AT_MQTT_H_ 10 | 11 | 12 | void MQTT_Start(); 13 | void MQTT_Pub(uint32_t data); 14 | #endif /* USER_AT_MQTT_H_ */ 15 | -------------------------------------------------------------------------------- /mqtt/tools/.gitattributes: -------------------------------------------------------------------------------- 1 | # Enforce Unix newlines 2 | *.css text eol=lf 3 | *.html text eol=lf 4 | *.js text eol=lf 5 | *.json text eol=lf 6 | *.less text eol=lf 7 | *.md text eol=lf 8 | *.svg text eol=lf 9 | *.yml text eol=lf 10 | *.py text eol=lf 11 | *.sh text eol=lf 12 | -------------------------------------------------------------------------------- /mqtt/mqtt/include/utils.h: -------------------------------------------------------------------------------- 1 | #ifndef _UTILS_H_ 2 | #define _UTILS_H_ 3 | 4 | #include "c_types.h" 5 | 6 | uint32_t ICACHE_FLASH_ATTR UTILS_Atoh(const int8_t *s); 7 | uint8_t ICACHE_FLASH_ATTR UTILS_StrToIP(const int8_t* str, void *ip); 8 | uint8_t ICACHE_FLASH_ATTR UTILS_IsIPV4 (int8_t *str); 9 | #endif 10 | -------------------------------------------------------------------------------- /user/utils.h: -------------------------------------------------------------------------------- 1 | #ifndef _UTILS_H_ 2 | #define _UTILS_H_ 3 | 4 | #include "c_types.h" 5 | 6 | uint32_t UTILS_Atoh(const int8_t *s); 7 | uint8_t UTILS_StrToIP(const int8_t* str, void *ip); 8 | uint8_t UTILS_IsIPV4 (int8_t *str); 9 | char *ULTILS_StrReplace(char *orig, char *rep, char *with); 10 | #endif 11 | -------------------------------------------------------------------------------- /mqtt/mqtt/include/typedef.h: -------------------------------------------------------------------------------- 1 | /** 2 | * \file 3 | * Standard Types definition 4 | */ 5 | 6 | #ifndef _TYPE_DEF_H_ 7 | #define _TYPE_DEF_H_ 8 | 9 | typedef char I8; 10 | typedef unsigned char U8; 11 | typedef short I16; 12 | typedef unsigned short U16; 13 | typedef long I32; 14 | typedef unsigned long U32; 15 | typedef unsigned long long U64; 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /mqtt/modules/include/wifi.h: -------------------------------------------------------------------------------- 1 | /* 2 | * wifi.h 3 | * 4 | * Created on: Dec 30, 2014 5 | * Author: Minh 6 | */ 7 | 8 | #ifndef USER_WIFI_H_ 9 | #define USER_WIFI_H_ 10 | #include "os_type.h" 11 | typedef void (*WifiCallback)(uint8_t); 12 | void ICACHE_FLASH_ATTR WIFI_Connect(uint8_t* ssid, uint8_t* pass, WifiCallback cb); 13 | 14 | 15 | #endif /* USER_WIFI_H_ */ 16 | -------------------------------------------------------------------------------- /mqtt/tools/makefile.sh: -------------------------------------------------------------------------------- 1 | 2 | # 3 | # Generate the certificates and keys for encrypt. 4 | # 5 | 6 | # set default cert for use in the client 7 | xxd -i client.cer | sed -e \ 8 | "s/client_cer/default_certificate/" > cert.h 9 | # set default key for use in the server 10 | xxd -i server.key_1024 | sed -e \ 11 | "s/server_key_1024/default_private_key/" > private_key.h 12 | -------------------------------------------------------------------------------- /mqtt/mqtt/include/ringbuf.h: -------------------------------------------------------------------------------- 1 | #ifndef _RING_BUF_H_ 2 | #define _RING_BUF_H_ 3 | 4 | #include 5 | #include 6 | #include "typedef.h" 7 | 8 | typedef struct{ 9 | U8* p_o; /**< Original pointer */ 10 | U8* volatile p_r; /**< Read pointer */ 11 | U8* volatile p_w; /**< Write pointer */ 12 | volatile I32 fill_cnt; /**< Number of filled slots */ 13 | I32 size; /**< Buffer size */ 14 | }RINGBUF; 15 | 16 | I16 ICACHE_FLASH_ATTR RINGBUF_Init(RINGBUF *r, U8* buf, I32 size); 17 | I16 ICACHE_FLASH_ATTR RINGBUF_Put(RINGBUF *r, U8 c); 18 | I16 ICACHE_FLASH_ATTR RINGBUF_Get(RINGBUF *r, U8* c); 19 | #endif 20 | -------------------------------------------------------------------------------- /user/config.h: -------------------------------------------------------------------------------- 1 | /* 2 | * config.h 3 | * 4 | * Created on: Dec 6, 2014 5 | * Author: Minh 6 | */ 7 | 8 | #ifndef USER_CONFIG_H_ 9 | #define USER_CONFIG_H_ 10 | #include "os_type.h" 11 | #include "user_config.h" 12 | typedef struct{ 13 | uint32_t cfg_holder; 14 | uint32_t device_id; 15 | 16 | uint8_t sta_ssid[32]; 17 | uint8_t sta_pwd[32]; 18 | uint32_t sta_type; 19 | 20 | uint8_t ap_ssid[32]; 21 | uint8_t ap_pwd[32]; 22 | uint32_t ap_type; 23 | 24 | uint8_t mqtt_host[64]; 25 | uint32_t mqtt_port; 26 | 27 | uint8_t ota_host[64]; 28 | uint32_t ota_port; 29 | 30 | uint8_t ota_key[64]; 31 | } SYSCFG; 32 | 33 | typedef struct { 34 | uint8 flag; 35 | uint8 pad[3]; 36 | } SAVE_FLAG; 37 | 38 | void CFG_Save(); 39 | void CFG_Load(); 40 | 41 | extern SYSCFG sysCfg; 42 | 43 | #endif /* USER_CONFIG_H_ */ 44 | -------------------------------------------------------------------------------- /user/user_main.c: -------------------------------------------------------------------------------- 1 | #include "ets_sys.h" 2 | #include "driver/uart.h" 3 | #include "osapi.h" 4 | #include "mqtt.h" 5 | #include "config.h" 6 | #include "debug.h" 7 | #include "gpio.h" 8 | #include "user_interface.h" 9 | #include "os_type.h" 10 | #include "user_config.h" 11 | #include "driver/uart_register.h" 12 | #include "driver/uart.h" 13 | #include "driver/i2c.h" 14 | #include "driver/i2c_oled.h" 15 | 16 | extern void ets_wdt_disable(void); 17 | 18 | static volatile bool OLED; 19 | 20 | void user_init(void) 21 | { 22 | uart_init(BIT_RATE_115200, BIT_RATE_115200); 23 | os_delay_us(1000000); 24 | 25 | i2c_init(); 26 | OLED = OLED_Init(); 27 | 28 | OLED_Print(2, 0, "ESP8266 SMARTWATCH", 1); 29 | 30 | wifi_set_opmode(STATION_MODE); 31 | CFG_Load(); 32 | MQTT_Start(); 33 | INFO("\r\nSystem started ...\r\n"); 34 | } 35 | -------------------------------------------------------------------------------- /include/user_config.h: -------------------------------------------------------------------------------- 1 | #ifndef _USER_CONFIG_H_ 2 | #define _USER_CONFIG_H_ 3 | #include "user_interface.h" 4 | 5 | #define CFG_HOLDER 0x00FF55A1 6 | #define CFG_LOCATION 0x3C 7 | 8 | #define MQTT_HOST "m11.cloudmqtt.com" //or "mqtt.domain.com 9 | #define MQTT_PORT 10596 10 | #define MQTT_BUF_SIZE 1024 11 | 12 | #define MQTT_CLIENT_ID "ESP8266_%8X" 13 | #define MQTT_USER "MQTTUSER" 14 | #define MQTT_PASS "MQTTPASS" 15 | #define MQTT_SUB_TOPIC_NUM 1 16 | 17 | 18 | #define OTA_HOST MQTT_HOST 19 | #define OTA_PORT 80 20 | 21 | #define KEY "39cdfe29a1863489e788" 22 | 23 | #define AP_SSID "DVES_%08X" 24 | #define AP_PASS "dves" 25 | #define AP_TYPE AUTH_OPEN 26 | 27 | #define STA_SSID "ssid" // WIFI SSID 28 | #define STA_PASS "pwd" // WIFI PASSWORD 29 | #define STA_TYPE AUTH_WPA2_PSK 30 | 31 | #define MQTT_RECONNECT_TIMEOUT 5 32 | #define MQTT_CONNTECT_TIMER 5 33 | #endif 34 | -------------------------------------------------------------------------------- /mqtt/.travis.yml: -------------------------------------------------------------------------------- 1 | language: cpp 2 | before_install: 3 | - sudo apt-get install -y python-serial srecord 4 | install: 5 | - wget https://github.com/GeorgeHahn/nodemcu-firmware/raw/travis/tools/esp-open-sdk.tar.gz -O tools/esp-open-sdk.tar.gz 6 | - tar -zxvf tools/esp-open-sdk.tar.gz 7 | - export PATH=$PATH:$PWD/esp-open-sdk/sdk:$PWD/esp-open-sdk/xtensa-lx106-elf/bin 8 | - wget http://bbs.espressif.com/download/file.php?id=189 -O tools/esp_iot_sdk_v0.9.5_15_01_23.zip 9 | - unzip tools/esp_iot_sdk_v0.9.5_15_01_23.zip 10 | script: 11 | - make all SDK_BASE="$PWD/esp_iot_sdk_v0.9.5" 12 | - cd firmware/ 13 | - file_name="esp_mqtt_v${TRAVIS_TAG}.${TRAVIS_BUILD_NUMBER}.bin" 14 | - srec_cat -output ${file_name} -binary 0x00000.bin -binary -fill 0xff 0x00000 0x40000 0x40000.bin -binary -offset 0x40000 15 | deploy: 16 | provider: releases 17 | api_key: 18 | file: "$TRAVIS_BUILD_DIR/firmware/${file_name}" 19 | skip_cleanup: true 20 | on: 21 | tags: true 22 | repo: tuanpmt/esp_mqtt -------------------------------------------------------------------------------- /mqtt/mqtt/include/proto.h: -------------------------------------------------------------------------------- 1 | /* 2 | * File: proto.h 3 | * Author: ThuHien 4 | * 5 | * Created on November 23, 2012, 8:57 AM 6 | */ 7 | 8 | #ifndef _PROTO_H_ 9 | #define _PROTO_H_ 10 | #include 11 | #include "typedef.h" 12 | #include "ringbuf.h" 13 | 14 | typedef void(PROTO_PARSE_CALLBACK)(); 15 | 16 | typedef struct{ 17 | U8 *buf; 18 | U16 bufSize; 19 | U16 dataLen; 20 | U8 isEsc; 21 | U8 isBegin; 22 | PROTO_PARSE_CALLBACK* callback; 23 | }PROTO_PARSER; 24 | 25 | I8 ICACHE_FLASH_ATTR PROTO_Init(PROTO_PARSER *parser, PROTO_PARSE_CALLBACK *completeCallback, U8 *buf, U16 bufSize); 26 | I8 ICACHE_FLASH_ATTR PROTO_Parse(PROTO_PARSER *parser, U8 *buf, U16 len); 27 | I16 ICACHE_FLASH_ATTR PROTO_Add(U8 *buf, const U8 *packet, I16 bufSize); 28 | I16 ICACHE_FLASH_ATTR PROTO_AddRb(RINGBUF *rb, const U8 *packet, I16 len); 29 | I8 ICACHE_FLASH_ATTR PROTO_ParseByte(PROTO_PARSER *parser, U8 value); 30 | I16 ICACHE_FLASH_ATTR PROTO_ParseRb(RINGBUF *rb, U8 *bufOut, U16* len, U16 maxBufLen); 31 | #endif 32 | 33 | -------------------------------------------------------------------------------- /mqtt/include/user_config.h: -------------------------------------------------------------------------------- 1 | #ifndef _USER_CONFIG_H_ 2 | #define _USER_CONFIG_H_ 3 | 4 | #define CFG_HOLDER 0x00FF55A4 /* Change this value to load default configurations */ 5 | #define CFG_LOCATION 0x3C /* Please don't change or if you know what you doing */ 6 | #define CLIENT_SSL_ENABLE 7 | 8 | /*DEFAULT CONFIGURATIONS*/ 9 | 10 | #define MQTT_HOST "192.168.11.122" //or "mqtt.yourdomain.com" 11 | #define MQTT_PORT 1880 12 | #define MQTT_BUF_SIZE 1024 13 | #define MQTT_KEEPALIVE 120 /*second*/ 14 | 15 | #define MQTT_CLIENT_ID "DVES_%08X" 16 | #define MQTT_USER "DVES_USER" 17 | #define MQTT_PASS "DVES_PASS" 18 | 19 | #define STA_SSID "DVES_HOME" 20 | #define STA_PASS "yourpassword" 21 | #define STA_TYPE AUTH_WPA2_PSK 22 | 23 | #define MQTT_RECONNECT_TIMEOUT 5 /*second*/ 24 | 25 | #define DEFAULT_SECURITY 0 26 | #define QUEUE_BUFFER_SIZE 2048 27 | 28 | #define PROTOCOL_NAMEv31 /*MQTT version 3.1 compatible with Mosquitto v0.15*/ 29 | //PROTOCOL_NAMEv311 /*MQTT version 3.11 compatible with https://eclipse.org/paho/clients/testing/*/ 30 | #endif 31 | -------------------------------------------------------------------------------- /include/driver/i2c_oled.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Oryginal by: 3 | * Author : Aaron Lee 4 | * Version: 1.00 5 | * Date : 2014.3.24 6 | * Email : hello14blog@gmail.com 7 | * Modification: none 8 | * Mod by reaper7 9 | * found at http://bbs.espressif.com/viewtopic.php?f=15&t=31 10 | */ 11 | 12 | #ifndef __I2C_OLED_H 13 | #define __I2C_OLED_H 14 | 15 | #include "c_types.h" 16 | #include "ets_sys.h" 17 | #include "osapi.h" 18 | 19 | #define OLED_ADDRESS 0x78 // D/C->GND 20 | //#define OLED_ADDRESS 0x7a // D/C->Vcc 21 | 22 | void OLED_writeCmd(unsigned char I2C_Command); 23 | void OLED_writeDat(unsigned char I2C_Data); 24 | bool OLED_Init(void); 25 | void OLED_SetPos(unsigned char x, unsigned char y); 26 | void OLED_Fill(unsigned char fill_Data); 27 | void OLED_CLS(void); 28 | void OLED_ON(void); 29 | void OLED_OFF(void); 30 | void OLED_ShowStr(unsigned char x, unsigned char y, unsigned char ch[], unsigned char TextSize); 31 | void OLED_DrawBMP(unsigned char x0,unsigned char y0,unsigned char x1,unsigned char y1,unsigned char BMP[]); 32 | void OLED_Line(unsigned char x, unsigned char ch[], unsigned char TextSize); 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /include/at.h: -------------------------------------------------------------------------------- 1 | #ifndef __AT_H 2 | #define __AT_H 3 | 4 | #include "c_types.h" 5 | 6 | //#define at_busyTaskPrio 1 7 | //#define at_busyTaskQueueLen 4 8 | 9 | 10 | #define at_recvTaskPrio 0 11 | #define at_recvTaskQueueLen 64 12 | 13 | #define at_procTaskPrio 1 14 | #define at_procTaskQueueLen 1 15 | 16 | #define at_backOk uart0_sendStr("\r\nOK\r\n") 17 | #define at_backError uart0_sendStr("\r\nERROR\r\n") 18 | #define at_backTeError "+CTE ERROR: %d\r\n" 19 | 20 | typedef enum{ 21 | at_statIdle, 22 | at_statRecving, 23 | at_statProcess, 24 | at_statIpSending, 25 | at_statIpSended, 26 | at_statIpTraning 27 | }at_stateType; 28 | 29 | typedef enum{ 30 | m_init, 31 | m_wact, 32 | m_gotip, 33 | m_linked, 34 | m_unlink, 35 | m_wdact 36 | }at_mdStateType; 37 | 38 | typedef struct 39 | { 40 | char *at_cmdName; 41 | int8_t at_cmdLen; 42 | void (*at_testCmd)(uint8_t id); 43 | void (*at_queryCmd)(uint8_t id); 44 | void (*at_setupCmd)(uint8_t id, char *pPara); 45 | void (*at_exeCmd)(uint8_t id); 46 | }at_funcationType; 47 | 48 | void at_init(void); 49 | void at_cmdProcess(uint8_t *pAtRcvData); 50 | 51 | #endif 52 | -------------------------------------------------------------------------------- /driver/Makefile: -------------------------------------------------------------------------------- 1 | 2 | ############################################################# 3 | # Required variables for each makefile 4 | # Discard this section from all parent makefiles 5 | # Expected variables (with automatic defaults): 6 | # CSRCS (all "C" files in the dir) 7 | # SUBDIRS (all subdirs with a Makefile) 8 | # GEN_LIBS - list of libs to be generated () 9 | # GEN_IMAGES - list of images to be generated () 10 | # COMPONENTS_xxx - a list of libs/objs in the form 11 | # subdir/lib to be extracted and rolled up into 12 | # a generated lib/image xxx.a () 13 | # 14 | ifndef PDIR 15 | GEN_LIBS = libdriver.a 16 | endif 17 | 18 | 19 | ############################################################# 20 | # Configuration i.e. compile options etc. 21 | # Target specific stuff (defines etc.) goes in here! 22 | # Generally values applying to a tree are captured in the 23 | # makefile at its root level - these are then overridden 24 | # for a subtree within the makefile rooted therein 25 | # 26 | #DEFINES += 27 | 28 | ############################################################# 29 | # Recursion Magic - Don't touch this!! 30 | # 31 | # Each subtree potentially has an include directory 32 | # corresponding to the common APIs applicable to modules 33 | # rooted at that subtree. Accordingly, the INCLUDE PATH 34 | # of a module can only contain the include directories up 35 | # its parent path, and not its siblings 36 | # 37 | # Required for each makefile to inherit from the parent 38 | # 39 | 40 | INCLUDES := $(INCLUDES) -I $(PDIR)include 41 | INCLUDES += -I ./ 42 | PDIR := ../$(PDIR) 43 | sinclude $(PDIR)Makefile 44 | 45 | -------------------------------------------------------------------------------- /mqtt/mqtt/Makefile: -------------------------------------------------------------------------------- 1 | 2 | ############################################################# 3 | # Required variables for each makefile 4 | # Discard this section from all parent makefiles 5 | # Expected variables (with automatic defaults): 6 | # CSRCS (all "C" files in the dir) 7 | # SUBDIRS (all subdirs with a Makefile) 8 | # GEN_LIBS - list of libs to be generated () 9 | # GEN_IMAGES - list of images to be generated () 10 | # COMPONENTS_xxx - a list of libs/objs in the form 11 | # subdir/lib to be extracted and rolled up into 12 | # a generated lib/image xxx.a () 13 | # 14 | ifndef PDIR 15 | GEN_LIBS = libmqtt.a 16 | endif 17 | 18 | 19 | ############################################################# 20 | # Configuration i.e. compile options etc. 21 | # Target specific stuff (defines etc.) goes in here! 22 | # Generally values applying to a tree are captured in the 23 | # makefile at its root level - these are then overridden 24 | # for a subtree within the makefile rooted therein 25 | # 26 | #DEFINES += 27 | 28 | ############################################################# 29 | # Recursion Magic - Don't touch this!! 30 | # 31 | # Each subtree potentially has an include directory 32 | # corresponding to the common APIs applicable to modules 33 | # rooted at that subtree. Accordingly, the INCLUDE PATH 34 | # of a module can only contain the include directories up 35 | # its parent path, and not its siblings 36 | # 37 | # Required for each makefile to inherit from the parent 38 | # 39 | 40 | INCLUDES := $(INCLUDES) -I $(PDIR)include 41 | INCLUDES += -I ./ 42 | PDIR := ../$(PDIR) 43 | sinclude $(PDIR)Makefile 44 | 45 | -------------------------------------------------------------------------------- /mqtt/user/Makefile: -------------------------------------------------------------------------------- 1 | 2 | ############################################################# 3 | # Required variables for each makefile 4 | # Discard this section from all parent makefiles 5 | # Expected variables (with automatic defaults): 6 | # CSRCS (all "C" files in the dir) 7 | # SUBDIRS (all subdirs with a Makefile) 8 | # GEN_LIBS - list of libs to be generated () 9 | # GEN_IMAGES - list of images to be generated () 10 | # COMPONENTS_xxx - a list of libs/objs in the form 11 | # subdir/lib to be extracted and rolled up into 12 | # a generated lib/image xxx.a () 13 | # 14 | ifndef PDIR 15 | GEN_LIBS = libuser.a 16 | endif 17 | 18 | 19 | ############################################################# 20 | # Configuration i.e. compile options etc. 21 | # Target specific stuff (defines etc.) goes in here! 22 | # Generally values applying to a tree are captured in the 23 | # makefile at its root level - these are then overridden 24 | # for a subtree within the makefile rooted therein 25 | # 26 | #DEFINES += 27 | 28 | ############################################################# 29 | # Recursion Magic - Don't touch this!! 30 | # 31 | # Each subtree potentially has an include directory 32 | # corresponding to the common APIs applicable to modules 33 | # rooted at that subtree. Accordingly, the INCLUDE PATH 34 | # of a module can only contain the include directories up 35 | # its parent path, and not its siblings 36 | # 37 | # Required for each makefile to inherit from the parent 38 | # 39 | 40 | INCLUDES := $(INCLUDES) -I $(PDIR)include 41 | INCLUDES += -I ./ 42 | PDIR := ../$(PDIR) 43 | sinclude $(PDIR)Makefile 44 | 45 | -------------------------------------------------------------------------------- /mqtt/driver/Makefile: -------------------------------------------------------------------------------- 1 | 2 | ############################################################# 3 | # Required variables for each makefile 4 | # Discard this section from all parent makefiles 5 | # Expected variables (with automatic defaults): 6 | # CSRCS (all "C" files in the dir) 7 | # SUBDIRS (all subdirs with a Makefile) 8 | # GEN_LIBS - list of libs to be generated () 9 | # GEN_IMAGES - list of images to be generated () 10 | # COMPONENTS_xxx - a list of libs/objs in the form 11 | # subdir/lib to be extracted and rolled up into 12 | # a generated lib/image xxx.a () 13 | # 14 | ifndef PDIR 15 | GEN_LIBS = libdriver.a 16 | endif 17 | 18 | 19 | ############################################################# 20 | # Configuration i.e. compile options etc. 21 | # Target specific stuff (defines etc.) goes in here! 22 | # Generally values applying to a tree are captured in the 23 | # makefile at its root level - these are then overridden 24 | # for a subtree within the makefile rooted therein 25 | # 26 | #DEFINES += 27 | 28 | ############################################################# 29 | # Recursion Magic - Don't touch this!! 30 | # 31 | # Each subtree potentially has an include directory 32 | # corresponding to the common APIs applicable to modules 33 | # rooted at that subtree. Accordingly, the INCLUDE PATH 34 | # of a module can only contain the include directories up 35 | # its parent path, and not its siblings 36 | # 37 | # Required for each makefile to inherit from the parent 38 | # 39 | 40 | INCLUDES := $(INCLUDES) -I $(PDIR)include 41 | INCLUDES += -I ./ 42 | PDIR := ../$(PDIR) 43 | sinclude $(PDIR)Makefile 44 | 45 | -------------------------------------------------------------------------------- /mqtt/modules/Makefile: -------------------------------------------------------------------------------- 1 | 2 | ############################################################# 3 | # Required variables for each makefile 4 | # Discard this section from all parent makefiles 5 | # Expected variables (with automatic defaults): 6 | # CSRCS (all "C" files in the dir) 7 | # SUBDIRS (all subdirs with a Makefile) 8 | # GEN_LIBS - list of libs to be generated () 9 | # GEN_IMAGES - list of images to be generated () 10 | # COMPONENTS_xxx - a list of libs/objs in the form 11 | # subdir/lib to be extracted and rolled up into 12 | # a generated lib/image xxx.a () 13 | # 14 | ifndef PDIR 15 | GEN_LIBS = libmqtt.a 16 | endif 17 | 18 | 19 | ############################################################# 20 | # Configuration i.e. compile options etc. 21 | # Target specific stuff (defines etc.) goes in here! 22 | # Generally values applying to a tree are captured in the 23 | # makefile at its root level - these are then overridden 24 | # for a subtree within the makefile rooted therein 25 | # 26 | #DEFINES += 27 | 28 | ############################################################# 29 | # Recursion Magic - Don't touch this!! 30 | # 31 | # Each subtree potentially has an include directory 32 | # corresponding to the common APIs applicable to modules 33 | # rooted at that subtree. Accordingly, the INCLUDE PATH 34 | # of a module can only contain the include directories up 35 | # its parent path, and not its siblings 36 | # 37 | # Required for each makefile to inherit from the parent 38 | # 39 | 40 | INCLUDES := $(INCLUDES) -I $(PDIR)include 41 | INCLUDES += -I ./ 42 | PDIR := ../$(PDIR) 43 | sinclude $(PDIR)Makefile 44 | 45 | -------------------------------------------------------------------------------- /user/Makefile: -------------------------------------------------------------------------------- 1 | 2 | ############################################################# 3 | # Required variables for each makefile 4 | # Discard this section from all parent makefiles 5 | # Expected variables (with automatic defaults): 6 | # CSRCS (all "C" files in the dir) 7 | # SUBDIRS (all subdirs with a Makefile) 8 | # GEN_LIBS - list of libs to be generated () 9 | # GEN_IMAGES - list of images to be generated () 10 | # COMPONENTS_xxx - a list of libs/objs in the form 11 | # subdir/lib to be extracted and rolled up into 12 | # a generated lib/image xxx.a () 13 | # 14 | ifndef PDIR 15 | GEN_LIBS = libuser.a 16 | endif 17 | 18 | 19 | ############################################################# 20 | # Configuration i.e. compile options etc. 21 | # Target specific stuff (defines etc.) goes in here! 22 | # Generally values applying to a tree are captured in the 23 | # makefile at its root level - these are then overridden 24 | # for a subtree within the makefile rooted therein 25 | # 26 | #DEFINES += 27 | 28 | ############################################################# 29 | # Recursion Magic - Don't touch this!! 30 | # 31 | # Each subtree potentially has an include directory 32 | # corresponding to the common APIs applicable to modules 33 | # rooted at that subtree. Accordingly, the INCLUDE PATH 34 | # of a module can only contain the include directories up 35 | # its parent path, and not its siblings 36 | # 37 | # Required for each makefile to inherit from the parent 38 | # 39 | 40 | INCLUDES := $(INCLUDES) -I $(PDIR)include 41 | INCLUDES += -I ./ 42 | INCLUDES += -I ../../rom/include 43 | INCLUDES += -I ../../include/ets 44 | PDIR := ../$(PDIR) 45 | sinclude $(PDIR)Makefile 46 | 47 | -------------------------------------------------------------------------------- /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 | 30 | //SDA on GPIO2 31 | #define I2C_SDA_MUX PERIPHS_IO_MUX_GPIO2_U 32 | #define I2C_SDA_FUNC FUNC_GPIO2 33 | #define I2C_SDA_PIN 2 34 | 35 | //SCK on GPIO14 36 | //#define I2C_SCK_MUX PERIPHS_IO_MUX_MTMS_U 37 | //#define I2C_SCK_FUNC FUNC_GPIO14 38 | //#define I2C_SCK_PIN 14 39 | 40 | //SCK on GPIO0 41 | #define I2C_SCK_MUX PERIPHS_IO_MUX_GPIO0_U 42 | #define I2C_SCK_PIN 0 43 | #define I2C_SCK_FUNC FUNC_GPIO0 44 | 45 | #define i2c_read() GPIO_INPUT_GET(GPIO_ID_PIN(I2C_SDA_PIN)); 46 | 47 | void i2c_init(void); 48 | void i2c_start(void); 49 | void i2c_stop(void); 50 | void i2c_send_ack(uint8 state); 51 | uint8 i2c_check_ack(void); 52 | uint8 i2c_readByte(void); 53 | void i2c_writeByte(uint8 data); 54 | -------------------------------------------------------------------------------- /mqtt/mqtt/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/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 | #undef IICSECOND 32 | 33 | #if defined(IICSECOND) 34 | #define I2C_SDA_MUX PERIPHS_IO_MUX_U0TXD_U 35 | #define I2C_SDA_FUNC FUNC_GPIO1 36 | #define I2C_SDA_PIN 1 37 | 38 | #define I2C_SCK_MUX PERIPHS_IO_MUX_U0RXD_U 39 | #define I2C_SCK_FUNC FUNC_GPIO3 40 | #define I2C_SCK_PIN 3 41 | #else 42 | #define I2C_SDA_MUX PERIPHS_IO_MUX_GPIO2_U 43 | #define I2C_SDA_FUNC FUNC_GPIO2 44 | #define I2C_SDA_PIN 2 45 | 46 | #define I2C_SCK_MUX PERIPHS_IO_MUX_GPIO0_U 47 | #define I2C_SCK_FUNC FUNC_GPIO0 48 | #define I2C_SCK_PIN 0 49 | #endif 50 | 51 | #define i2c_read() GPIO_INPUT_GET(GPIO_ID_PIN(I2C_SDA_PIN)); 52 | 53 | void i2c_init(void); 54 | void i2c_start(void); 55 | void i2c_stop(void); 56 | void i2c_send_ack(uint8 state); 57 | uint8 i2c_check_ack(void); 58 | uint8 i2c_readByte(void); 59 | void i2c_writeByte(uint8 data); 60 | -------------------------------------------------------------------------------- /mqtt/mqtt/include/queue.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 | -------------------------------------------------------------------------------- /mqtt/modules/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 | typedef struct{ 36 | uint32_t cfg_holder; 37 | uint8_t device_id[16]; 38 | 39 | uint8_t sta_ssid[64]; 40 | uint8_t sta_pwd[64]; 41 | uint32_t sta_type; 42 | 43 | uint8_t mqtt_host[64]; 44 | uint32_t mqtt_port; 45 | uint8_t mqtt_user[32]; 46 | uint8_t mqtt_pass[32]; 47 | uint32_t mqtt_keepalive; 48 | uint8_t security; 49 | } SYSCFG; 50 | 51 | typedef struct { 52 | uint8 flag; 53 | uint8 pad[3]; 54 | } SAVE_FLAG; 55 | 56 | void ICACHE_FLASH_ATTR CFG_Save(); 57 | void ICACHE_FLASH_ATTR CFG_Load(); 58 | 59 | extern SYSCFG sysCfg; 60 | 61 | #endif /* USER_CONFIG_H_ */ 62 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | #esp8266-smartwatch 2 | This project is by [Shantanu Goel](http://tech.shantanugoel.com/) for a smartwatch based on ESP8266. This software repository consists the following development: 3 | * Modify and refactor Tuan PM's port of the [MQTT client library for ESP8266](https://github.com/tuanpmt/esp_mqtt) 4 | * Use zarya's [I2C driver](https://github.com/zarya/esp8266_i2c_driver) 5 | * Modify and refactor this [OLED driver](http://www.esp8266.com/viewtopic.php?p=4311#p4311) 6 | * Add an NTP driver and a client 7 | 8 | Thanks to [Nathan](https://github.com/nathanchantrell/esp_mqtt_oled) for the original code that combined the mqtt and oled drivers 9 | 10 | The aim is to build an extensible smartwatch framework which is easily configurable 11 | 12 | ##Hardware 13 | * ESP8266 (Developing currently on ESP-01 but others should be usable as is) 14 | * A 0.96" 128x64 I2C OLED which is easily available from ebay or other electronic shops 15 | * A 3.3v USB FTDI board for programming/powering the esp8266 and the oled during development. Will be replaced by a LIPO battery finally 16 | 17 | ##Current Status 18 | * Subscribes to an MQTT topic and displays it on the OLED 19 | * Using this with tasker on phone and [ThingFabric](http://www.thingfabric.com) to send phone notifications to the watch 20 | * Gets the current time from NTP server at boot up and displays on the OLED 21 | 22 | ##Changelog 23 | Check commit history 24 | 25 | ##Configuration 26 | * I2C address for the OLED is in include/driver/i2c_oled.h 27 | * MQTT broker and WiFi settings are in include/user_config.h 28 | * GPIO pins to use for I2C are in driver/i2c.h 29 | * MQTT topics to subscribe to are in the MQTT_Start() function in user/mqtt.c 30 | * What to do with the incoming messages is defined in deliver_publish() in user/mqtt.c 31 | * NTP server IP address is in user/ntp.c 32 | 33 | ##TODO 34 | * Decouple OLED code from ntp 35 | * Build clock function on top of the ntp client to update display with latest time 36 | * Refactor MQTT code and segregate wifi and ntp/clock management from it 37 | * Refactor OLED code to better manage all the different writes ongoing and prevent a write wiping out other things on display 38 | * Add framework to configure things for individual users without having to recompile the code 39 | * Add watchfaces (wishlist) 40 | * Add buttons support to take actions on the watch 41 | * Add communication support from watch to phone 42 | -------------------------------------------------------------------------------- /mqtt/mqtt/queue.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 "queue.h" 31 | 32 | #include "user_interface.h" 33 | #include "osapi.h" 34 | #include "os_type.h" 35 | #include "mem.h" 36 | #include "proto.h" 37 | void ICACHE_FLASH_ATTR QUEUE_Init(QUEUE *queue, int bufferSize) 38 | { 39 | queue->buf = (uint8_t*)os_zalloc(bufferSize); 40 | RINGBUF_Init(&queue->rb, queue->buf, bufferSize); 41 | } 42 | int32_t ICACHE_FLASH_ATTR QUEUE_Puts(QUEUE *queue, uint8_t* buffer, uint16_t len) 43 | { 44 | return PROTO_AddRb(&queue->rb, buffer, len); 45 | } 46 | int32_t ICACHE_FLASH_ATTR QUEUE_Gets(QUEUE *queue, uint8_t* buffer, uint16_t* len, uint16_t maxLen) 47 | { 48 | 49 | return PROTO_ParseRb(&queue->rb, buffer, len, maxLen); 50 | } 51 | 52 | BOOL ICACHE_FLASH_ATTR QUEUE_IsEmpty(QUEUE *queue) 53 | { 54 | if(queue->rb.fill_cnt<=0) 55 | return TRUE; 56 | return FALSE; 57 | } 58 | -------------------------------------------------------------------------------- /user/config.c: -------------------------------------------------------------------------------- 1 | /* 2 | * config.c 3 | * 4 | * Created on: Dec 6, 2014 5 | * Author: Minh 6 | */ 7 | #include "ets_sys.h" 8 | #include "os_type.h" 9 | #include "mem.h" 10 | #include "osapi.h" 11 | #include "user_interface.h" 12 | 13 | #include "config.h" 14 | #include "user_config.h" 15 | #include "debug.h" 16 | 17 | SYSCFG sysCfg; 18 | SAVE_FLAG saveFlag; 19 | 20 | void CFG_Save() 21 | { 22 | spi_flash_read((CFG_LOCATION + 3) * SPI_FLASH_SEC_SIZE, 23 | (uint32 *)&saveFlag, sizeof(SAVE_FLAG)); 24 | 25 | if (saveFlag.flag == 0) { 26 | spi_flash_erase_sector(CFG_LOCATION + 1); 27 | spi_flash_write((CFG_LOCATION + 1) * SPI_FLASH_SEC_SIZE, 28 | (uint32 *)&sysCfg, sizeof(SYSCFG)); 29 | saveFlag.flag = 1; 30 | spi_flash_erase_sector(CFG_LOCATION + 3); 31 | spi_flash_write((CFG_LOCATION + 3) * SPI_FLASH_SEC_SIZE, 32 | (uint32 *)&saveFlag, sizeof(SAVE_FLAG)); 33 | } else { 34 | spi_flash_erase_sector(CFG_LOCATION + 0); 35 | spi_flash_write((CFG_LOCATION + 0) * SPI_FLASH_SEC_SIZE, 36 | (uint32 *)&sysCfg, sizeof(SYSCFG)); 37 | saveFlag.flag = 0; 38 | spi_flash_erase_sector(CFG_LOCATION + 3); 39 | spi_flash_write((CFG_LOCATION + 3) * SPI_FLASH_SEC_SIZE, 40 | (uint32 *)&saveFlag, sizeof(SAVE_FLAG)); 41 | } 42 | } 43 | 44 | void CFG_Load() 45 | { 46 | 47 | INFO("\r\nload configurations...\r\n"); 48 | spi_flash_read((CFG_LOCATION + 3) * SPI_FLASH_SEC_SIZE, 49 | (uint32 *)&saveFlag, sizeof(SAVE_FLAG)); 50 | if (saveFlag.flag == 0) { 51 | spi_flash_read((CFG_LOCATION + 0) * SPI_FLASH_SEC_SIZE, 52 | (uint32 *)&sysCfg, sizeof(SYSCFG)); 53 | } else { 54 | spi_flash_read((CFG_LOCATION + 1) * SPI_FLASH_SEC_SIZE, 55 | (uint32 *)&sysCfg, sizeof(SYSCFG)); 56 | } 57 | if(sysCfg.cfg_holder != CFG_HOLDER){ 58 | os_memset(&sysCfg, 0x00, sizeof sysCfg); 59 | 60 | 61 | sysCfg.cfg_holder = CFG_HOLDER; 62 | 63 | sysCfg.device_id = system_get_chip_id(); 64 | 65 | os_sprintf(sysCfg.ap_ssid, AP_SSID, sysCfg.device_id); 66 | os_sprintf(sysCfg.ap_pwd, "%s", AP_PASS); 67 | sysCfg.ap_type = AP_TYPE; 68 | 69 | os_sprintf(sysCfg.sta_ssid, "%s", STA_SSID); 70 | os_sprintf(sysCfg.sta_pwd, "%s", STA_PASS); 71 | sysCfg.sta_type = STA_TYPE; 72 | 73 | os_sprintf(sysCfg.mqtt_host, "%s", MQTT_HOST); 74 | sysCfg.mqtt_port = MQTT_PORT; 75 | 76 | os_sprintf(sysCfg.ota_host, "%s", OTA_HOST); 77 | sysCfg.ota_port = OTA_PORT; 78 | 79 | os_sprintf(sysCfg.ota_key, "%s", KEY); 80 | INFO(" new config\r\n"); 81 | 82 | CFG_Save(); 83 | } 84 | 85 | } 86 | -------------------------------------------------------------------------------- /user/ntp.c: -------------------------------------------------------------------------------- 1 | #include "osapi.h" 2 | #include "mem.h" 3 | #include "espconn.h" 4 | #include "debug.h" 5 | #include "time.h" 6 | 7 | void ntp_send_request(); 8 | 9 | #define NTP_PACKET_SIZE 48 // NTP time stamp is in the first 48 bytes of the message 10 | #define NTP_OFFSET 2208988800UL 11 | 12 | uint8 ntp_server[4] = {192, 168, 2, 160}; 13 | uint8 packetBuffer[NTP_PACKET_SIZE]; //buffer to hold incoming and outgoing packets 14 | struct espconn *pCon; 15 | 16 | 17 | unsigned long ntp_get_time() 18 | { 19 | pCon = (struct espconn *)os_zalloc(sizeof(struct espconn)); 20 | pCon->type = ESPCONN_UDP; 21 | pCon->state = ESPCONN_NONE; 22 | pCon->proto.udp = (esp_udp *)os_zalloc(sizeof(esp_udp)); 23 | pCon->proto.udp->local_port = espconn_port(); 24 | pCon->proto.udp->remote_port = 123; 25 | ntp_send_request(); 26 | } 27 | 28 | void ntp_udpclient_recv(void *arg, char *pdata, unsigned short len); 29 | void ICACHE_FLASH_ATTR 30 | ntp_udpclient_sent_cb(void *arg) 31 | { 32 | //Causing Crash. To be fixed 33 | //espconn_delete(pCon); 34 | //os_free(pCon->proto.udp); 35 | //os_free(pCon); 36 | } 37 | 38 | void ICACHE_FLASH_ATTR 39 | ntp_udpclient_recv(void *arg, char *pdata, unsigned short len) 40 | { 41 | struct tm *dt; 42 | char timestr[11]; 43 | // this is NTP time (seconds since Jan 1 1900): 44 | unsigned long timestamp = pdata[40] << 24 | pdata[41] << 16 | 45 | pdata[42] << 8 | pdata[43]; 46 | timestamp = timestamp - NTP_OFFSET; 47 | dt = localtime((time_t *) ×tamp); 48 | os_sprintf(timestr, "%d:%d:%d", dt->tm_hour, dt->tm_min, dt->tm_sec); 49 | OLED_Print(4, 2, timestr, 1); 50 | } 51 | 52 | void ntp_send_request() 53 | { 54 | // set all bytes in the buffer to 0 55 | os_memcpy(pCon->proto.udp->remote_ip, ntp_server, 4); 56 | memset(packetBuffer, 0, NTP_PACKET_SIZE); 57 | // Initialize values needed to form NTP request 58 | // (see URL above for details on the packets) 59 | packetBuffer[0] = 0b11100011; // LI, Version, Mode 60 | packetBuffer[1] = 0; // Stratum, or type of clock 61 | packetBuffer[2] = 6; // Polling Interval 62 | packetBuffer[3] = 0xEC; // Peer Clock Precision 63 | // 8 bytes of zero for Root Delay & Root Dispersion 64 | packetBuffer[12] = 49; 65 | packetBuffer[13] = 0x4E; 66 | packetBuffer[14] = 49; 67 | packetBuffer[15] = 52; 68 | 69 | // all NTP fields have been given values, now 70 | // you can send a packet requesting a timestamp: 71 | espconn_create(pCon); 72 | espconn_regist_recvcb(pCon, ntp_udpclient_recv); 73 | espconn_regist_sentcb(pCon, ntp_udpclient_sent_cb); 74 | espconn_sent(pCon, packetBuffer, NTP_PACKET_SIZE); 75 | } 76 | -------------------------------------------------------------------------------- /mqtt/modules/wifi.c: -------------------------------------------------------------------------------- 1 | /* 2 | * wifi.c 3 | * 4 | * Created on: Dec 30, 2014 5 | * Author: Minh 6 | */ 7 | #include "wifi.h" 8 | #include "user_interface.h" 9 | #include "osapi.h" 10 | #include "espconn.h" 11 | #include "os_type.h" 12 | #include "mem.h" 13 | #include "mqtt_msg.h" 14 | #include "debug.h" 15 | #include "user_config.h" 16 | #include "config.h" 17 | 18 | static ETSTimer WiFiLinker; 19 | WifiCallback wifiCb = NULL; 20 | static uint8_t wifiStatus = STATION_IDLE, lastWifiStatus = STATION_IDLE; 21 | static void ICACHE_FLASH_ATTR wifi_check_ip(void *arg) 22 | { 23 | struct ip_info ipConfig; 24 | 25 | os_timer_disarm(&WiFiLinker); 26 | wifi_get_ip_info(STATION_IF, &ipConfig); 27 | wifiStatus = wifi_station_get_connect_status(); 28 | if (wifiStatus == STATION_GOT_IP && ipConfig.ip.addr != 0) 29 | { 30 | 31 | os_timer_setfn(&WiFiLinker, (os_timer_func_t *)wifi_check_ip, NULL); 32 | os_timer_arm(&WiFiLinker, 2000, 0); 33 | 34 | 35 | } 36 | else 37 | { 38 | if(wifi_station_get_connect_status() == STATION_WRONG_PASSWORD) 39 | { 40 | 41 | INFO("STATION_WRONG_PASSWORD\r\n"); 42 | wifi_station_connect(); 43 | 44 | 45 | } 46 | else if(wifi_station_get_connect_status() == STATION_NO_AP_FOUND) 47 | { 48 | 49 | INFO("STATION_NO_AP_FOUND\r\n"); 50 | wifi_station_connect(); 51 | 52 | 53 | } 54 | else if(wifi_station_get_connect_status() == STATION_CONNECT_FAIL) 55 | { 56 | 57 | INFO("STATION_CONNECT_FAIL\r\n"); 58 | wifi_station_connect(); 59 | 60 | } 61 | else 62 | { 63 | INFO("STATION_IDLE\r\n"); 64 | } 65 | 66 | os_timer_setfn(&WiFiLinker, (os_timer_func_t *)wifi_check_ip, NULL); 67 | os_timer_arm(&WiFiLinker, 500, 0); 68 | } 69 | if(wifiStatus != lastWifiStatus){ 70 | lastWifiStatus = wifiStatus; 71 | if(wifiCb) 72 | wifiCb(wifiStatus); 73 | } 74 | } 75 | 76 | void ICACHE_FLASH_ATTR WIFI_Connect(uint8_t* ssid, uint8_t* pass, WifiCallback cb) 77 | { 78 | struct station_config stationConf; 79 | 80 | INFO("WIFI_INIT\r\n"); 81 | wifi_set_opmode(STATION_MODE); 82 | wifi_station_set_auto_connect(FALSE); 83 | wifiCb = cb; 84 | 85 | os_memset(&stationConf, 0, sizeof(struct station_config)); 86 | 87 | os_sprintf(stationConf.ssid, "%s", ssid); 88 | os_sprintf(stationConf.password, "%s", pass); 89 | 90 | wifi_station_set_config(&stationConf); 91 | 92 | os_timer_disarm(&WiFiLinker); 93 | os_timer_setfn(&WiFiLinker, (os_timer_func_t *)wifi_check_ip, NULL); 94 | os_timer_arm(&WiFiLinker, 1000, 0); 95 | 96 | wifi_station_set_auto_connect(TRUE); 97 | wifi_station_connect(); 98 | } 99 | 100 | -------------------------------------------------------------------------------- /include/driver/uart.h: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /mqtt/include/driver/uart.h: -------------------------------------------------------------------------------- 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 | #endif 101 | 102 | -------------------------------------------------------------------------------- /mqtt/mqtt/proto.c: -------------------------------------------------------------------------------- 1 | #include "proto.h" 2 | #include "ringbuf.h" 3 | I8 ICACHE_FLASH_ATTR PROTO_Init(PROTO_PARSER *parser, PROTO_PARSE_CALLBACK *completeCallback, U8 *buf, U16 bufSize) 4 | { 5 | parser->buf = buf; 6 | parser->bufSize = bufSize; 7 | parser->dataLen = 0; 8 | parser->callback = completeCallback; 9 | parser->isEsc = 0; 10 | return 0; 11 | } 12 | 13 | I8 ICACHE_FLASH_ATTR PROTO_ParseByte(PROTO_PARSER *parser, U8 value) 14 | { 15 | switch(value){ 16 | case 0x7D: 17 | parser->isEsc = 1; 18 | break; 19 | 20 | case 0x7E: 21 | parser->dataLen = 0; 22 | parser->isEsc = 0; 23 | parser->isBegin = 1; 24 | break; 25 | 26 | case 0x7F: 27 | if (parser->callback != NULL) 28 | parser->callback(); 29 | parser->isBegin = 0; 30 | return 0; 31 | break; 32 | 33 | default: 34 | if(parser->isBegin == 0) break; 35 | 36 | if(parser->isEsc){ 37 | value ^= 0x20; 38 | parser->isEsc = 0; 39 | } 40 | 41 | if(parser->dataLen < parser->bufSize) 42 | parser->buf[parser->dataLen++] = value; 43 | 44 | break; 45 | } 46 | return -1; 47 | } 48 | 49 | I8 ICACHE_FLASH_ATTR PROTO_Parse(PROTO_PARSER *parser, U8 *buf, U16 len) 50 | { 51 | while(len--) 52 | PROTO_ParseByte(parser, *buf++); 53 | 54 | return 0; 55 | } 56 | I16 ICACHE_FLASH_ATTR PROTO_ParseRb(RINGBUF* rb, U8 *bufOut, U16* len, U16 maxBufLen) 57 | { 58 | U8 c; 59 | 60 | PROTO_PARSER proto; 61 | PROTO_Init(&proto, NULL, bufOut, maxBufLen); 62 | while(RINGBUF_Get(rb, &c) == 0){ 63 | if(PROTO_ParseByte(&proto, c) == 0){ 64 | *len = proto.dataLen; 65 | return 0; 66 | } 67 | } 68 | return -1; 69 | } 70 | I16 ICACHE_FLASH_ATTR PROTO_Add(U8 *buf, const U8 *packet, I16 bufSize) 71 | { 72 | U16 i = 2; 73 | U16 len = *(U16*) packet; 74 | 75 | if (bufSize < 1) return -1; 76 | 77 | *buf++ = 0x7E; 78 | bufSize--; 79 | 80 | while (len--) { 81 | switch (*packet) { 82 | case 0x7D: 83 | case 0x7E: 84 | case 0x7F: 85 | if (bufSize < 2) return -1; 86 | *buf++ = 0x7D; 87 | *buf++ = *packet++ ^ 0x20; 88 | i += 2; 89 | bufSize -= 2; 90 | break; 91 | default: 92 | if (bufSize < 1) return -1; 93 | *buf++ = *packet++; 94 | i++; 95 | bufSize--; 96 | break; 97 | } 98 | } 99 | 100 | if (bufSize < 1) return -1; 101 | *buf++ = 0x7F; 102 | 103 | return i; 104 | } 105 | 106 | I16 ICACHE_FLASH_ATTR PROTO_AddRb(RINGBUF *rb, const U8 *packet, I16 len) 107 | { 108 | U16 i = 2; 109 | if(RINGBUF_Put(rb, 0x7E) == -1) return -1; 110 | while (len--) { 111 | switch (*packet) { 112 | case 0x7D: 113 | case 0x7E: 114 | case 0x7F: 115 | if(RINGBUF_Put(rb, 0x7D) == -1) return -1; 116 | if(RINGBUF_Put(rb, *packet++ ^ 0x20) == -1) return -1; 117 | i += 2; 118 | break; 119 | default: 120 | if(RINGBUF_Put(rb, *packet++) == -1) return -1; 121 | i++; 122 | break; 123 | } 124 | } 125 | if(RINGBUF_Put(rb, 0x7F) == -1) return -1; 126 | 127 | return i; 128 | } 129 | 130 | -------------------------------------------------------------------------------- /mqtt/modules/config.c: -------------------------------------------------------------------------------- 1 | /* 2 | /* config.c 3 | * 4 | * Copyright (c) 2014-2015, Tuan PM 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 are met: 9 | * 10 | * * Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * * 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 | * * Neither the name of Redis nor the names of its contributors may be used 16 | * to endorse or promote products derived from this software without 17 | * specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | * AND 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 COPYRIGHT OWNER OR CONTRIBUTORS BE 23 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | * POSSIBILITY OF SUCH DAMAGE. 30 | */ 31 | #include "ets_sys.h" 32 | #include "os_type.h" 33 | #include "mem.h" 34 | #include "osapi.h" 35 | #include "user_interface.h" 36 | 37 | #include "mqtt.h" 38 | #include "config.h" 39 | #include "user_config.h" 40 | #include "debug.h" 41 | 42 | SYSCFG sysCfg; 43 | SAVE_FLAG saveFlag; 44 | 45 | void ICACHE_FLASH_ATTR 46 | CFG_Save() 47 | { 48 | spi_flash_read((CFG_LOCATION + 3) * SPI_FLASH_SEC_SIZE, 49 | (uint32 *)&saveFlag, sizeof(SAVE_FLAG)); 50 | 51 | if (saveFlag.flag == 0) { 52 | spi_flash_erase_sector(CFG_LOCATION + 1); 53 | spi_flash_write((CFG_LOCATION + 1) * SPI_FLASH_SEC_SIZE, 54 | (uint32 *)&sysCfg, sizeof(SYSCFG)); 55 | saveFlag.flag = 1; 56 | spi_flash_erase_sector(CFG_LOCATION + 3); 57 | spi_flash_write((CFG_LOCATION + 3) * SPI_FLASH_SEC_SIZE, 58 | (uint32 *)&saveFlag, sizeof(SAVE_FLAG)); 59 | } else { 60 | spi_flash_erase_sector(CFG_LOCATION + 0); 61 | spi_flash_write((CFG_LOCATION + 0) * SPI_FLASH_SEC_SIZE, 62 | (uint32 *)&sysCfg, sizeof(SYSCFG)); 63 | saveFlag.flag = 0; 64 | spi_flash_erase_sector(CFG_LOCATION + 3); 65 | spi_flash_write((CFG_LOCATION + 3) * SPI_FLASH_SEC_SIZE, 66 | (uint32 *)&saveFlag, sizeof(SAVE_FLAG)); 67 | } 68 | } 69 | 70 | void ICACHE_FLASH_ATTR 71 | CFG_Load() 72 | { 73 | 74 | INFO("\r\nload ...\r\n"); 75 | spi_flash_read((CFG_LOCATION + 3) * SPI_FLASH_SEC_SIZE, 76 | (uint32 *)&saveFlag, sizeof(SAVE_FLAG)); 77 | if (saveFlag.flag == 0) { 78 | spi_flash_read((CFG_LOCATION + 0) * SPI_FLASH_SEC_SIZE, 79 | (uint32 *)&sysCfg, sizeof(SYSCFG)); 80 | } else { 81 | spi_flash_read((CFG_LOCATION + 1) * SPI_FLASH_SEC_SIZE, 82 | (uint32 *)&sysCfg, sizeof(SYSCFG)); 83 | } 84 | if(sysCfg.cfg_holder != CFG_HOLDER){ 85 | os_memset(&sysCfg, 0x00, sizeof sysCfg); 86 | 87 | 88 | sysCfg.cfg_holder = CFG_HOLDER; 89 | 90 | os_sprintf(sysCfg.sta_ssid, "%s", STA_SSID); 91 | os_sprintf(sysCfg.sta_pwd, "%s", STA_PASS); 92 | sysCfg.sta_type = STA_TYPE; 93 | 94 | os_sprintf(sysCfg.device_id, MQTT_CLIENT_ID, system_get_chip_id()); 95 | os_sprintf(sysCfg.mqtt_host, "%s", MQTT_HOST); 96 | sysCfg.mqtt_port = MQTT_PORT; 97 | os_sprintf(sysCfg.mqtt_user, "%s", MQTT_USER); 98 | os_sprintf(sysCfg.mqtt_pass, "%s", MQTT_PASS); 99 | 100 | sysCfg.security = DEFAULT_SECURITY; /* default non ssl */ 101 | 102 | sysCfg.mqtt_keepalive = MQTT_KEEPALIVE; 103 | 104 | INFO(" default configuration\r\n"); 105 | 106 | CFG_Save(); 107 | } 108 | 109 | } 110 | -------------------------------------------------------------------------------- /mqtt/user/user_main.c: -------------------------------------------------------------------------------- 1 | /* main.c -- MQTT client example 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 "ets_sys.h" 31 | #include "driver/uart.h" 32 | #include "osapi.h" 33 | #include "mqtt.h" 34 | #include "wifi.h" 35 | #include "config.h" 36 | #include "debug.h" 37 | #include "gpio.h" 38 | #include "user_interface.h" 39 | #include "mem.h" 40 | 41 | MQTT_Client mqttClient; 42 | 43 | void wifiConnectCb(uint8_t status) 44 | { 45 | if(status == STATION_GOT_IP){ 46 | MQTT_Connect(&mqttClient); 47 | } else { 48 | MQTT_Disconnect(&mqttClient); 49 | } 50 | } 51 | void mqttConnectedCb(uint32_t *args) 52 | { 53 | MQTT_Client* client = (MQTT_Client*)args; 54 | INFO("MQTT: Connected\r\n"); 55 | MQTT_Subscribe(client, "/mqtt/topic/0", 0); 56 | MQTT_Subscribe(client, "/mqtt/topic/1", 1); 57 | MQTT_Subscribe(client, "/mqtt/topic/2", 2); 58 | 59 | MQTT_Publish(client, "/mqtt/topic/0", "hello0", 6, 0, 0); 60 | MQTT_Publish(client, "/mqtt/topic/1", "hello1", 6, 1, 0); 61 | MQTT_Publish(client, "/mqtt/topic/2", "hello2", 6, 2, 0); 62 | 63 | } 64 | 65 | void mqttDisconnectedCb(uint32_t *args) 66 | { 67 | MQTT_Client* client = (MQTT_Client*)args; 68 | INFO("MQTT: Disconnected\r\n"); 69 | } 70 | 71 | void mqttPublishedCb(uint32_t *args) 72 | { 73 | MQTT_Client* client = (MQTT_Client*)args; 74 | INFO("MQTT: Published\r\n"); 75 | } 76 | 77 | void mqttDataCb(uint32_t *args, const char* topic, uint32_t topic_len, const char *data, uint32_t data_len) 78 | { 79 | char *topicBuf = (char*)os_zalloc(topic_len+1), 80 | *dataBuf = (char*)os_zalloc(data_len+1); 81 | 82 | MQTT_Client* client = (MQTT_Client*)args; 83 | 84 | os_memcpy(topicBuf, topic, topic_len); 85 | topicBuf[topic_len] = 0; 86 | 87 | os_memcpy(dataBuf, data, data_len); 88 | dataBuf[data_len] = 0; 89 | 90 | INFO("Receive topic: %s, data: %s \r\n", topicBuf, dataBuf); 91 | os_free(topicBuf); 92 | os_free(dataBuf); 93 | } 94 | 95 | 96 | void user_init(void) 97 | { 98 | uart_init(BIT_RATE_115200, BIT_RATE_115200); 99 | os_delay_us(1000000); 100 | 101 | CFG_Load(); 102 | 103 | MQTT_InitConnection(&mqttClient, sysCfg.mqtt_host, sysCfg.mqtt_port, sysCfg.security); 104 | //MQTT_InitConnection(&mqttClient, "192.168.11.122", 1880, 0); 105 | 106 | MQTT_InitClient(&mqttClient, sysCfg.device_id, sysCfg.mqtt_user, sysCfg.mqtt_pass, sysCfg.mqtt_keepalive, 1); 107 | //MQTT_InitClient(&mqttClient, "client_id", "user", "pass", 120, 1); 108 | 109 | MQTT_InitLWT(&mqttClient, "/lwt", "offline", 0, 0); 110 | MQTT_OnConnected(&mqttClient, mqttConnectedCb); 111 | MQTT_OnDisconnected(&mqttClient, mqttDisconnectedCb); 112 | MQTT_OnPublished(&mqttClient, mqttPublishedCb); 113 | MQTT_OnData(&mqttClient, mqttDataCb); 114 | 115 | WIFI_Connect(sysCfg.sta_ssid, sysCfg.sta_pwd, wifiConnectCb); 116 | 117 | INFO("\r\nSystem started ...\r\n"); 118 | } 119 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Changelog 2 | # Changed the variables to include the header file directory 3 | # Added global var for the XTENSA tool root 4 | # 5 | # This make file still needs some work. 6 | # 7 | # 8 | # Output directors to store intermediate compiled files 9 | # relative to the project directory 10 | BUILD_BASE = build 11 | FW_BASE = firmware 12 | 13 | # Base directory for the compiler 14 | #XTENSA_TOOLS_ROOT ?= /opt/Espressif/crosstool-NG/builds/xtensa-lx106-elf/bin 15 | XTENSA_TOOLS_ROOT ?= ../esp-open-sdk/xtensa-lx106-elf/bin 16 | 17 | # base directory of the ESP8266 SDK package, absolute 18 | #SDK_BASE ?= /opt/Espressif/ESP8266_SDK 19 | SDK_BASE ?= ../esp-open-sdk/sdk/ 20 | 21 | #Esptool.py path and port 22 | ESPTOOL ?= esptool.py 23 | ESPPORT ?= /dev/ttyUSB2 24 | 25 | # name for the target project 26 | TARGET = app 27 | 28 | # which modules (subdirectories) of the project to include in compiling 29 | MODULES = driver user 30 | EXTRA_INCDIR = include $(SDK_BASE)/../include 31 | 32 | # libraries used in this project, mainly provided by the SDK 33 | LIBS = c gcc hal phy pp net80211 lwip wpa upgrade main 34 | 35 | # compiler flags using during compilation of source files 36 | CFLAGS = -Os -g -O2 -Wpointer-arith -Wundef -Werror -Wl,-EL -fno-inline-functions -nostdlib -mlongcalls -mtext-section-literals -D__ets__ -DICACHE_FLASH 37 | 38 | # linker flags used to generate the main object file 39 | LDFLAGS = -nostdlib -Wl,--no-check-sections -u call_user_start -Wl,-static 40 | 41 | # linker script used for the above linkier step 42 | LD_SCRIPT = eagle.app.v6.ld 43 | 44 | # various paths from the SDK used in this project 45 | SDK_LIBDIR = lib 46 | SDK_LDDIR = ld 47 | SDK_INCDIR = include include/json 48 | 49 | # we create two different files for uploading into the flash 50 | # these are the names and options to generate them 51 | FW_FILE_1 = 0x00000 52 | FW_FILE_1_ARGS = -bo $@ -bs .text -bs .data -bs .rodata -bc -ec 53 | FW_FILE_2 = 0x40000 54 | FW_FILE_2_ARGS = -es .irom0.text $@ -ec 55 | 56 | # select which tools to use as compiler, librarian and linker 57 | CC := $(XTENSA_TOOLS_ROOT)/xtensa-lx106-elf-gcc 58 | AR := $(XTENSA_TOOLS_ROOT)/xtensa-lx106-elf-ar 59 | LD := $(XTENSA_TOOLS_ROOT)/xtensa-lx106-elf-gcc 60 | 61 | #### 62 | #### no user configurable options below here 63 | #### 64 | FW_TOOL ?= $(ESPTOOL) 65 | SRC_DIR := $(MODULES) 66 | BUILD_DIR := $(addprefix $(BUILD_BASE)/,$(MODULES)) 67 | 68 | SDK_LIBDIR := $(addprefix $(SDK_BASE)/,$(SDK_LIBDIR)) 69 | SDK_INCDIR := $(addprefix -I$(SDK_BASE)/,$(SDK_INCDIR)) 70 | 71 | SRC := $(foreach sdir,$(SRC_DIR),$(wildcard $(sdir)/*.c)) 72 | OBJ := $(patsubst %.c,$(BUILD_BASE)/%.o,$(SRC)) 73 | LIBS := $(addprefix -l,$(LIBS)) 74 | APP_AR := $(addprefix $(BUILD_BASE)/,$(TARGET)_app.a) 75 | TARGET_OUT := $(addprefix $(BUILD_BASE)/,$(TARGET).out) 76 | 77 | LD_SCRIPT := $(addprefix -T$(SDK_BASE)/$(SDK_LDDIR)/,$(LD_SCRIPT)) 78 | 79 | INCDIR := $(addprefix -I,$(SRC_DIR)) 80 | EXTRA_INCDIR := $(addprefix -I,$(EXTRA_INCDIR)) 81 | MODULE_INCDIR := $(addsuffix /include,$(INCDIR)) 82 | 83 | FW_FILE_1 := $(addprefix $(FW_BASE)/,$(FW_FILE_1).bin) 84 | FW_FILE_2 := $(addprefix $(FW_BASE)/,$(FW_FILE_2).bin) 85 | 86 | V ?= $(VERBOSE) 87 | ifeq ("$(V)","1") 88 | Q := 89 | vecho := @true 90 | else 91 | Q := @ 92 | vecho := @echo 93 | endif 94 | 95 | vpath %.c $(SRC_DIR) 96 | 97 | define compile-objects 98 | $1/%.o: %.c 99 | $(vecho) "CC $$<" 100 | $(Q) $(CC) $(INCDIR) $(MODULE_INCDIR) $(EXTRA_INCDIR) $(SDK_INCDIR) $(CFLAGS) -c $$< -o $$@ 101 | endef 102 | 103 | .PHONY: all checkdirs clean 104 | 105 | all: checkdirs $(TARGET_OUT) $(FW_FILE_1) $(FW_FILE_2) 106 | 107 | $(FW_FILE_1): $(TARGET_OUT) 108 | $(vecho) "FW $@" 109 | $(FW_TOOL) elf2image $< -o $(FW_BASE)/ 110 | 111 | $(FW_FILE_2): $(TARGET_OUT) 112 | $(vecho) "FW $@" 113 | $(FW_TOOL) elf2image $< -o $(FW_BASE)/ 114 | 115 | $(TARGET_OUT): $(APP_AR) 116 | $(vecho) "LD $@" 117 | $(Q) $(LD) -L$(SDK_LIBDIR) $(LD_SCRIPT) $(LDFLAGS) -Wl,--start-group $(LIBS) $(APP_AR) -Wl,--end-group -o $@ 118 | 119 | $(APP_AR): $(OBJ) 120 | $(vecho) "AR $@" 121 | $(Q) $(AR) cru $@ $^ 122 | 123 | checkdirs: $(BUILD_DIR) $(FW_BASE) 124 | 125 | $(BUILD_DIR): 126 | $(Q) mkdir -p $@ 127 | 128 | firmware: 129 | $(Q) mkdir -p $@ 130 | 131 | flash: firmware/0x00000.bin firmware/0x40000.bin 132 | $(ESPTOOL) --port $(ESPPORT) write_flash 0x00000 firmware/0x00000.bin 0x40000 firmware/0x40000.bin 133 | 134 | test: flash 135 | screen $(ESPPORT) 115200 136 | 137 | clean: 138 | $(Q) rm -f $(APP_AR) 139 | $(Q) rm -f $(TARGET_OUT) 140 | $(Q) rm -rf $(BUILD_DIR) 141 | $(Q) rm -rf $(BUILD_BASE) 142 | $(Q) rm -f $(FW_FILE_1) 143 | $(Q) rm -f $(FW_FILE_2) 144 | $(Q) rm -rf $(FW_BASE) 145 | 146 | $(foreach bdir,$(BUILD_DIR),$(eval $(call compile-objects,$(bdir)))) 147 | -------------------------------------------------------------------------------- /Makefile.linux: -------------------------------------------------------------------------------- 1 | # Changelog 2 | # Changed the variables to include the header file directory 3 | # Added global var for the XTENSA tool root 4 | # 5 | # This make file still needs some work. 6 | # 7 | # 8 | # Output directors to store intermediate compiled files 9 | # relative to the project directory 10 | BUILD_BASE = build 11 | FW_BASE = firmware 12 | 13 | # Base directory for the compiler 14 | #XTENSA_TOOLS_ROOT ?= /opt/Espressif/crosstool-NG/builds/xtensa-lx106-elf/bin 15 | XTENSA_TOOLS_ROOT ?= ../esp-open-sdk/xtensa-lx106-elf/bin 16 | 17 | # base directory of the ESP8266 SDK package, absolute 18 | #SDK_BASE ?= /opt/Espressif/ESP8266_SDK 19 | SDK_BASE ?= ../esp-open-sdk/sdk/ 20 | 21 | #Esptool.py path and port 22 | ESPTOOL ?= esptool.py 23 | ESPPORT ?= /dev/ttyUSB2 24 | 25 | # name for the target project 26 | TARGET = app 27 | 28 | # which modules (subdirectories) of the project to include in compiling 29 | MODULES = driver user 30 | EXTRA_INCDIR = include $(SDK_BASE)/../include 31 | 32 | # libraries used in this project, mainly provided by the SDK 33 | LIBS = c gcc hal phy pp net80211 lwip wpa upgrade main 34 | 35 | # compiler flags using during compilation of source files 36 | CFLAGS = -Os -g -O2 -Wpointer-arith -Wundef -Werror -Wl,-EL -fno-inline-functions -nostdlib -mlongcalls -mtext-section-literals -D__ets__ -DICACHE_FLASH 37 | 38 | # linker flags used to generate the main object file 39 | LDFLAGS = -nostdlib -Wl,--no-check-sections -u call_user_start -Wl,-static 40 | 41 | # linker script used for the above linkier step 42 | LD_SCRIPT = eagle.app.v6.ld 43 | 44 | # various paths from the SDK used in this project 45 | SDK_LIBDIR = lib 46 | SDK_LDDIR = ld 47 | SDK_INCDIR = include include/json 48 | 49 | # we create two different files for uploading into the flash 50 | # these are the names and options to generate them 51 | FW_FILE_1 = 0x00000 52 | FW_FILE_1_ARGS = -bo $@ -bs .text -bs .data -bs .rodata -bc -ec 53 | FW_FILE_2 = 0x40000 54 | FW_FILE_2_ARGS = -es .irom0.text $@ -ec 55 | 56 | # select which tools to use as compiler, librarian and linker 57 | CC := $(XTENSA_TOOLS_ROOT)/xtensa-lx106-elf-gcc 58 | AR := $(XTENSA_TOOLS_ROOT)/xtensa-lx106-elf-ar 59 | LD := $(XTENSA_TOOLS_ROOT)/xtensa-lx106-elf-gcc 60 | 61 | #### 62 | #### no user configurable options below here 63 | #### 64 | FW_TOOL ?= ../esptool/esptool 65 | SRC_DIR := $(MODULES) 66 | BUILD_DIR := $(addprefix $(BUILD_BASE)/,$(MODULES)) 67 | 68 | SDK_LIBDIR := $(addprefix $(SDK_BASE)/,$(SDK_LIBDIR)) 69 | SDK_INCDIR := $(addprefix -I$(SDK_BASE)/,$(SDK_INCDIR)) 70 | 71 | SRC := $(foreach sdir,$(SRC_DIR),$(wildcard $(sdir)/*.c)) 72 | OBJ := $(patsubst %.c,$(BUILD_BASE)/%.o,$(SRC)) 73 | LIBS := $(addprefix -l,$(LIBS)) 74 | APP_AR := $(addprefix $(BUILD_BASE)/,$(TARGET)_app.a) 75 | TARGET_OUT := $(addprefix $(BUILD_BASE)/,$(TARGET).out) 76 | 77 | LD_SCRIPT := $(addprefix -T$(SDK_BASE)/$(SDK_LDDIR)/,$(LD_SCRIPT)) 78 | 79 | INCDIR := $(addprefix -I,$(SRC_DIR)) 80 | EXTRA_INCDIR := $(addprefix -I,$(EXTRA_INCDIR)) 81 | MODULE_INCDIR := $(addsuffix /include,$(INCDIR)) 82 | 83 | FW_FILE_1 := $(addprefix $(FW_BASE)/,$(FW_FILE_1).bin) 84 | FW_FILE_2 := $(addprefix $(FW_BASE)/,$(FW_FILE_2).bin) 85 | 86 | V ?= $(VERBOSE) 87 | ifeq ("$(V)","1") 88 | Q := 89 | vecho := @true 90 | else 91 | Q := @ 92 | vecho := @echo 93 | endif 94 | 95 | vpath %.c $(SRC_DIR) 96 | 97 | define compile-objects 98 | $1/%.o: %.c 99 | $(vecho) "CC $$<" 100 | $(Q) $(CC) $(INCDIR) $(MODULE_INCDIR) $(EXTRA_INCDIR) $(SDK_INCDIR) $(CFLAGS) -c $$< -o $$@ 101 | endef 102 | 103 | .PHONY: all checkdirs clean 104 | 105 | all: checkdirs $(TARGET_OUT) $(FW_FILE_1) $(FW_FILE_2) 106 | 107 | $(FW_FILE_1): $(TARGET_OUT) 108 | $(vecho) "FW $@" 109 | $(Q) $(FW_TOOL) -eo $(TARGET_OUT) $(FW_FILE_1_ARGS) 110 | 111 | $(FW_FILE_2): $(TARGET_OUT) 112 | $(vecho) "FW $@" 113 | $(Q) $(FW_TOOL) -eo $(TARGET_OUT) $(FW_FILE_2_ARGS) 114 | 115 | $(TARGET_OUT): $(APP_AR) 116 | $(vecho) "LD $@" 117 | $(Q) $(LD) -L$(SDK_LIBDIR) $(LD_SCRIPT) $(LDFLAGS) -Wl,--start-group $(LIBS) $(APP_AR) -Wl,--end-group -o $@ 118 | 119 | $(APP_AR): $(OBJ) 120 | $(vecho) "AR $@" 121 | $(Q) $(AR) cru $@ $^ 122 | 123 | checkdirs: $(BUILD_DIR) $(FW_BASE) 124 | 125 | $(BUILD_DIR): 126 | $(Q) mkdir -p $@ 127 | 128 | firmware: 129 | $(Q) mkdir -p $@ 130 | 131 | flash: firmware/0x00000.bin firmware/0x40000.bin 132 | $(ESPTOOL) --port $(ESPPORT) write_flash 0x00000 firmware/0x00000.bin 0x40000 firmware/0x40000.bin 133 | 134 | test: flash 135 | screen $(ESPPORT) 115200 136 | 137 | clean: 138 | $(Q) rm -f $(APP_AR) 139 | $(Q) rm -f $(TARGET_OUT) 140 | $(Q) rm -rf $(BUILD_DIR) 141 | $(Q) rm -rf $(BUILD_BASE) 142 | $(Q) rm -f $(FW_FILE_1) 143 | $(Q) rm -f $(FW_FILE_2) 144 | $(Q) rm -rf $(FW_BASE) 145 | 146 | $(foreach bdir,$(BUILD_DIR),$(eval $(call compile-objects,$(bdir)))) 147 | -------------------------------------------------------------------------------- /Makefile.mac: -------------------------------------------------------------------------------- 1 | # Changelog 2 | # Changed the variables to include the header file directory 3 | # Added global var for the XTENSA tool root 4 | # 5 | # This make file still needs some work. 6 | # 7 | # 8 | # Output directors to store intermediate compiled files 9 | # relative to the project directory 10 | BUILD_BASE = build 11 | FW_BASE = firmware 12 | 13 | # Base directory for the compiler 14 | XTENSA_TOOLS_ROOT ?= /esptools/esp-open-sdk/xtensa-lx106-elf/bin 15 | 16 | # base directory of the ESP8266 SDK package, absolute 17 | SDK_BASE ?= /esptools/esp-open-sdk/sdk 18 | 19 | #Esptool.py path and port 20 | ESPTOOL ?= /esptools/esp-open-sdk/esptool/esptool.py 21 | ESPPORT ?= /dev/ttyUSB0 22 | 23 | # name for the target project 24 | TARGET = app 25 | 26 | # which modules (subdirectories) of the project to include in compiling 27 | MODULES = driver mqtt user 28 | EXTRA_INCDIR = include $(SDK_BASE)/../include 29 | 30 | # libraries used in this project, mainly provided by the SDK 31 | LIBS = c gcc hal phy pp net80211 lwip wpa upgrade main ssl 32 | 33 | # compiler flags using during compilation of source files 34 | CFLAGS = -Os -g -O2 -Wpointer-arith -Wundef -Werror -Wl,-EL -fno-inline-functions -nostdlib -mlongcalls -mtext-section-literals -D__ets__ -DICACHE_FLASH 35 | 36 | # linker flags used to generate the main object file 37 | LDFLAGS = -nostdlib -Wl,--no-check-sections -u call_user_start -Wl,-static 38 | 39 | # linker script used for the above linkier step 40 | LD_SCRIPT = eagle.app.v6.ld 41 | 42 | # various paths from the SDK used in this project 43 | SDK_LIBDIR = lib 44 | SDK_LDDIR = ld 45 | SDK_INCDIR = include include/json 46 | 47 | # we create two different files for uploading into the flash 48 | # these are the names and options to generate them 49 | FW_FILE_1 = 0x00000 50 | FW_FILE_1_ARGS = -bo $@ -bs .text -bs .data -bs .rodata -bc -ec 51 | FW_FILE_2 = 0x40000 52 | FW_FILE_2_ARGS = -es .irom0.text $@ -ec 53 | 54 | # select which tools to use as compiler, librarian and linker 55 | CC := $(XTENSA_TOOLS_ROOT)/xtensa-lx106-elf-gcc 56 | AR := $(XTENSA_TOOLS_ROOT)/xtensa-lx106-elf-ar 57 | LD := $(XTENSA_TOOLS_ROOT)/xtensa-lx106-elf-gcc 58 | 59 | #### 60 | #### no user configurable options below here 61 | #### 62 | FW_TOOL ?= /esptools/esp-open-sdk/esptool-ck/esptool 63 | SRC_DIR := $(MODULES) 64 | BUILD_DIR := $(addprefix $(BUILD_BASE)/,$(MODULES)) 65 | 66 | SDK_LIBDIR := $(addprefix $(SDK_BASE)/,$(SDK_LIBDIR)) 67 | SDK_INCDIR := $(addprefix -I$(SDK_BASE)/,$(SDK_INCDIR)) 68 | 69 | SRC := $(foreach sdir,$(SRC_DIR),$(wildcard $(sdir)/*.c)) 70 | OBJ := $(patsubst %.c,$(BUILD_BASE)/%.o,$(SRC)) 71 | LIBS := $(addprefix -l,$(LIBS)) 72 | APP_AR := $(addprefix $(BUILD_BASE)/,$(TARGET)_app.a) 73 | TARGET_OUT := $(addprefix $(BUILD_BASE)/,$(TARGET).out) 74 | 75 | LD_SCRIPT := $(addprefix -T$(SDK_BASE)/$(SDK_LDDIR)/,$(LD_SCRIPT)) 76 | 77 | INCDIR := $(addprefix -I,$(SRC_DIR)) 78 | EXTRA_INCDIR := $(addprefix -I,$(EXTRA_INCDIR)) 79 | MODULE_INCDIR := $(addsuffix /include,$(INCDIR)) 80 | 81 | FW_FILE_1 := $(addprefix $(FW_BASE)/,$(FW_FILE_1).bin) 82 | FW_FILE_2 := $(addprefix $(FW_BASE)/,$(FW_FILE_2).bin) 83 | BLANKER := $(addprefix $(SDK_BASE)/,bin/blank.bin) 84 | 85 | V ?= $(VERBOSE) 86 | ifeq ("$(V)","1") 87 | Q := 88 | vecho := @true 89 | else 90 | Q := @ 91 | vecho := @echo 92 | endif 93 | 94 | vpath %.c $(SRC_DIR) 95 | 96 | define compile-objects 97 | $1/%.o: %.c 98 | $(vecho) "CC $$<" 99 | $(Q) $(CC) $(INCDIR) $(MODULE_INCDIR) $(EXTRA_INCDIR) $(SDK_INCDIR) $(CFLAGS) -c $$< -o $$@ 100 | endef 101 | 102 | .PHONY: all checkdirs clean 103 | 104 | all: checkdirs $(TARGET_OUT) $(FW_FILE_1) $(FW_FILE_2) 105 | 106 | $(FW_FILE_1): $(TARGET_OUT) 107 | $(vecho) "FW $@" 108 | $(Q) $(FW_TOOL) -eo $(TARGET_OUT) $(FW_FILE_1_ARGS) 109 | 110 | $(FW_FILE_2): $(TARGET_OUT) 111 | $(vecho) "FW $@" 112 | $(Q) $(FW_TOOL) -eo $(TARGET_OUT) $(FW_FILE_2_ARGS) 113 | 114 | $(TARGET_OUT): $(APP_AR) 115 | $(vecho) "LD $@" 116 | $(Q) $(LD) -L$(SDK_LIBDIR) $(LD_SCRIPT) $(LDFLAGS) -Wl,--start-group $(LIBS) $(APP_AR) -Wl,--end-group -o $@ 117 | 118 | $(APP_AR): $(OBJ) 119 | $(vecho) "AR $@" 120 | $(Q) $(AR) cru $@ $^ 121 | 122 | checkdirs: $(BUILD_DIR) $(FW_BASE) 123 | 124 | $(BUILD_DIR): 125 | $(Q) mkdir -p $@ 126 | 127 | firmware: 128 | $(Q) mkdir -p $@ 129 | 130 | flash: firmware/0x00000.bin firmware/0x40000.bin 131 | $(PYTHON) $(ESPTOOL) -p $(ESPPORT) write_flash 0x00000 firmware/0x00000.bin 0x3C000 $(BLANKER) 0x40000 firmware/0x40000.bin 132 | 133 | test: flash 134 | screen $(ESPPORT) 115200 135 | 136 | clean: 137 | $(Q) rm -f $(APP_AR) 138 | $(Q) rm -f $(TARGET_OUT) 139 | $(Q) rm -rf $(BUILD_DIR) 140 | $(Q) rm -rf $(BUILD_BASE) 141 | $(Q) rm -f $(FW_FILE_1) 142 | $(Q) rm -f $(FW_FILE_2) 143 | $(Q) rm -rf $(FW_BASE) 144 | 145 | $(foreach bdir,$(BUILD_DIR),$(eval $(call compile-objects,$(bdir)))) 146 | -------------------------------------------------------------------------------- /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 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 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 = 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 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 | -------------------------------------------------------------------------------- /Makefile.windows: -------------------------------------------------------------------------------- 1 | # Changelog 2 | # Changed the variables to include the header file directory 3 | # Added global var for the XTENSA tool root 4 | # 5 | # This make file still needs some work. 6 | # 7 | # 8 | # Output directors to store intermediate compiled files 9 | # relative to the project directory 10 | BUILD_BASE = build 11 | FW_BASE = firmware 12 | FLAVOR = release 13 | #FLAVOR = debug 14 | 15 | # Base directory for the compiler 16 | XTENSA_TOOLS_ROOT ?= c:/Espressif/xtensa-lx106-elf/bin 17 | 18 | # base directory of the ESP8266 SDK package, absolute 19 | SDK_BASE ?= c:/Espressif/ESP8266_SDK 20 | 21 | #Esptool.py path and port 22 | PYTHON ?= C:\Python27\python.exe 23 | ESPTOOL ?= c:\Espressif\utils\esptool.py 24 | ESPPORT ?= COM2 25 | 26 | # name for the target project 27 | TARGET = app 28 | 29 | # which modules (subdirectories) of the project to include in compiling 30 | MODULES = driver user 31 | EXTRA_INCDIR = include $(SDK_BASE)/../include 32 | 33 | # libraries used in this project, mainly provided by the SDK 34 | LIBS = c gcc hal phy pp net80211 lwip wpa upgrade main 35 | 36 | # compiler flags using during compilation of source files 37 | CFLAGS = -Os -Wpointer-arith -Wundef -Werror -Wl,-EL -fno-inline-functions -nostdlib -mlongcalls -mtext-section-literals -D__ets__ -DICACHE_FLASH 38 | 39 | # linker flags used to generate the main object file 40 | LDFLAGS = -nostdlib -Wl,--no-check-sections -u call_user_start -Wl,-static 41 | 42 | ifeq ($(FLAVOR),debug) 43 | CFLAGS += -g -O2 44 | LDFLAGS += -g -O2 45 | endif 46 | 47 | ifeq ($(FLAVOR),release) 48 | CFLAGS += -g -O0 49 | LDFLAGS += -g -O0 50 | endif 51 | 52 | # linker script used for the above linkier step 53 | LD_SCRIPT = eagle.app.v6.ld 54 | 55 | # various paths from the SDK used in this project 56 | SDK_LIBDIR = lib 57 | SDK_LDDIR = ld 58 | SDK_INCDIR = include include/json 59 | 60 | # we create two different files for uploading into the flash 61 | # these are the names and options to generate them 62 | FW_FILE_1 = 0x00000 63 | FW_FILE_1_ARGS = -bo $@ -bs .text -bs .data -bs .rodata -bc -ec 64 | FW_FILE_2 = 0x40000 65 | FW_FILE_2_ARGS = -es .irom0.text $@ -ec 66 | 67 | # select which tools to use as compiler, librarian and linker 68 | CC := $(XTENSA_TOOLS_ROOT)/xtensa-lx106-elf-gcc 69 | AR := $(XTENSA_TOOLS_ROOT)/xtensa-lx106-elf-ar 70 | LD := $(XTENSA_TOOLS_ROOT)/xtensa-lx106-elf-gcc 71 | 72 | #### 73 | #### no user configurable options below here 74 | #### 75 | FW_TOOL ?= $(XTENSA_TOOLS_ROOT)/esptool 76 | SRC_DIR := $(MODULES) 77 | BUILD_DIR := $(addprefix $(BUILD_BASE)/,$(MODULES)) 78 | 79 | SDK_LIBDIR := $(addprefix $(SDK_BASE)/,$(SDK_LIBDIR)) 80 | SDK_INCDIR := $(addprefix -I$(SDK_BASE)/,$(SDK_INCDIR)) 81 | 82 | SRC := $(foreach sdir,$(SRC_DIR),$(wildcard $(sdir)/*.c)) 83 | OBJ := $(patsubst %.c,$(BUILD_BASE)/%.o,$(SRC)) 84 | LIBS := $(addprefix -l,$(LIBS)) 85 | APP_AR := $(addprefix $(BUILD_BASE)/,$(TARGET)_app.a) 86 | TARGET_OUT := $(addprefix $(BUILD_BASE)/,$(TARGET).out) 87 | 88 | LD_SCRIPT := $(addprefix -T$(SDK_BASE)/$(SDK_LDDIR)/,$(LD_SCRIPT)) 89 | 90 | INCDIR := $(addprefix -I,$(SRC_DIR)) 91 | EXTRA_INCDIR := $(addprefix -I,$(EXTRA_INCDIR)) 92 | MODULE_INCDIR := $(addsuffix /include,$(INCDIR)) 93 | 94 | FW_FILE_1 := $(addprefix $(FW_BASE)/,$(FW_FILE_1).bin) 95 | FW_FILE_2 := $(addprefix $(FW_BASE)/,$(FW_FILE_2).bin) 96 | 97 | V ?= $(VERBOSE) 98 | ifeq ("$(V)","1") 99 | Q := 100 | vecho := @true 101 | else 102 | Q := @ 103 | vecho := @echo 104 | endif 105 | 106 | vpath %.c $(SRC_DIR) 107 | 108 | define compile-objects 109 | $1/%.o: %.c 110 | $(vecho) "CC $$<" 111 | $(Q) $(CC) $(INCDIR) $(MODULE_INCDIR) $(EXTRA_INCDIR) $(SDK_INCDIR) $(CFLAGS) -c $$< -o $$@ 112 | endef 113 | 114 | .PHONY: all checkdirs clean 115 | 116 | all: checkdirs $(TARGET_OUT) $(FW_FILE_1) $(FW_FILE_2) 117 | 118 | $(FW_FILE_1): $(TARGET_OUT) 119 | $(vecho) "FW $@" 120 | $(Q) $(FW_TOOL) -eo $(TARGET_OUT) $(FW_FILE_1_ARGS) 121 | 122 | $(FW_FILE_2): $(TARGET_OUT) 123 | $(vecho) "FW $@" 124 | $(Q) $(FW_TOOL) -eo $(TARGET_OUT) $(FW_FILE_2_ARGS) 125 | 126 | $(TARGET_OUT): $(APP_AR) 127 | $(vecho) "LD $@" 128 | $(Q) $(LD) -L$(SDK_LIBDIR) $(LD_SCRIPT) $(LDFLAGS) -Wl,--start-group $(LIBS) $(APP_AR) -Wl,--end-group -o $@ 129 | 130 | $(APP_AR): $(OBJ) 131 | $(vecho) "AR $@" 132 | $(Q) $(AR) cru $@ $^ 133 | 134 | checkdirs: $(BUILD_DIR) $(FW_BASE) 135 | 136 | $(BUILD_DIR): 137 | $(Q) mkdir -p $@ 138 | 139 | firmware: 140 | $(Q) mkdir -p $@ 141 | 142 | flash: firmware/0x00000.bin firmware/0x40000.bin 143 | $(PYTHON) $(ESPTOOL) -p $(ESPPORT) write_flash 0x00000 firmware/0x00000.bin 0x40000 firmware/0x40000.bin 144 | 145 | test: flash 146 | screen $(ESPPORT) 115200 147 | 148 | rebuild: clean all 149 | 150 | clean: 151 | $(Q) rm -f $(APP_AR) 152 | $(Q) rm -f $(TARGET_OUT) 153 | $(Q) rm -rf $(BUILD_DIR) 154 | $(Q) rm -rf $(BUILD_BASE) 155 | $(Q) rm -f $(FW_FILE_1) 156 | $(Q) rm -f $(FW_FILE_2) 157 | $(Q) rm -rf $(FW_BASE) 158 | 159 | $(foreach bdir,$(BUILD_DIR),$(eval $(call compile-objects,$(bdir)))) 160 | -------------------------------------------------------------------------------- /mqtt/mqtt/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 = 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 | -------------------------------------------------------------------------------- /user/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 | /* 7 6 5 4 3 2 1 0*/ 46 | /*| --- Message Type---- | DUP Flag | QoS Level | Retain | 47 | /* Remaining Length */ 48 | 49 | 50 | enum mqtt_message_type 51 | { 52 | MQTT_MSG_TYPE_CONNECT = 1, 53 | MQTT_MSG_TYPE_CONNACK = 2, 54 | MQTT_MSG_TYPE_PUBLISH = 3, 55 | MQTT_MSG_TYPE_PUBACK = 4, 56 | MQTT_MSG_TYPE_PUBREC = 5, 57 | MQTT_MSG_TYPE_PUBREL = 6, 58 | MQTT_MSG_TYPE_PUBCOMP = 7, 59 | MQTT_MSG_TYPE_SUBSCRIBE = 8, 60 | MQTT_MSG_TYPE_SUBACK = 9, 61 | MQTT_MSG_TYPE_UNSUBSCRIBE = 10, 62 | MQTT_MSG_TYPE_UNSUBACK = 11, 63 | MQTT_MSG_TYPE_PINGREQ = 12, 64 | MQTT_MSG_TYPE_PINGRESP = 13, 65 | MQTT_MSG_TYPE_DISCONNECT = 14 66 | }; 67 | 68 | typedef struct mqtt_message 69 | { 70 | uint8_t* data; 71 | uint16_t length; 72 | 73 | } mqtt_message_t; 74 | 75 | typedef struct mqtt_connection 76 | { 77 | mqtt_message_t message; 78 | 79 | uint16_t message_id; 80 | uint8_t* buffer; 81 | uint16_t buffer_length; 82 | 83 | } mqtt_connection_t; 84 | 85 | typedef struct mqtt_connect_info 86 | { 87 | const char* client_id; 88 | const char* username; 89 | const char* password; 90 | const char* will_topic; 91 | const char* will_message; 92 | int keepalive; 93 | int will_qos; 94 | int will_retain; 95 | int clean_session; 96 | 97 | } mqtt_connect_info_t; 98 | 99 | 100 | static inline int mqtt_get_type(uint8_t* buffer) { return (buffer[0] & 0xf0) >> 4; } 101 | static inline int mqtt_get_dup(uint8_t* buffer) { return (buffer[0] & 0x08) >> 3; } 102 | static inline int mqtt_get_qos(uint8_t* buffer) { return (buffer[0] & 0x06) >> 1; } 103 | static inline int mqtt_get_retain(uint8_t* buffer) { return (buffer[0] & 0x01); } 104 | 105 | void mqtt_msg_init(mqtt_connection_t* connection, uint8_t* buffer, uint16_t buffer_length); 106 | int mqtt_get_total_length(uint8_t* buffer, uint16_t length); 107 | const char* mqtt_get_publish_topic(uint8_t* buffer, uint16_t* length); 108 | const char* mqtt_get_publish_data(uint8_t* buffer, uint16_t* length); 109 | uint16_t mqtt_get_id(uint8_t* buffer, uint16_t length); 110 | 111 | mqtt_message_t* mqtt_msg_connect(mqtt_connection_t* connection, mqtt_connect_info_t* info); 112 | mqtt_message_t* mqtt_msg_publish(mqtt_connection_t* connection, const char* topic, const char* data, int data_length, int qos, int retain, uint16_t* message_id); 113 | mqtt_message_t* mqtt_msg_puback(mqtt_connection_t* connection, uint16_t message_id); 114 | mqtt_message_t* mqtt_msg_pubrec(mqtt_connection_t* connection, uint16_t message_id); 115 | mqtt_message_t* mqtt_msg_pubrel(mqtt_connection_t* connection, uint16_t message_id); 116 | mqtt_message_t* mqtt_msg_pubcomp(mqtt_connection_t* connection, uint16_t message_id); 117 | mqtt_message_t* mqtt_msg_subscribe(mqtt_connection_t* connection, const char* topic, int qos, uint16_t* message_id); 118 | mqtt_message_t* mqtt_msg_unsubscribe(mqtt_connection_t* connection, const char* topic, uint16_t* message_id); 119 | mqtt_message_t* mqtt_msg_pingreq(mqtt_connection_t* connection); 120 | mqtt_message_t* mqtt_msg_pingresp(mqtt_connection_t* connection); 121 | mqtt_message_t* mqtt_msg_disconnect(mqtt_connection_t* connection); 122 | 123 | 124 | #ifdef __cplusplus 125 | } 126 | #endif 127 | 128 | #endif /* MQTT_MSG_H */ 129 | 130 | -------------------------------------------------------------------------------- /include/driver/uart_register.h: -------------------------------------------------------------------------------- 1 | //Generated at 2012-07-03 18:44:06 2 | /* 3 | * Copyright (c) 2010 - 2011 Espressif System 4 | * 5 | */ 6 | 7 | #ifndef UART_REGISTER_H_INCLUDED 8 | #define UART_REGISTER_H_INCLUDED 9 | #define REG_UART_BASE( i ) (0x60000000+(i)*0xf00) 10 | //version value:32'h062000 11 | 12 | #define UART_FIFO( i ) (REG_UART_BASE( i ) + 0x0) 13 | #define UART_RXFIFO_RD_BYTE 0x000000FF 14 | #define UART_RXFIFO_RD_BYTE_S 0 15 | 16 | #define UART_INT_RAW( i ) (REG_UART_BASE( i ) + 0x4) 17 | #define UART_RXFIFO_TOUT_INT_RAW (BIT(8)) 18 | #define UART_BRK_DET_INT_RAW (BIT(7)) 19 | #define UART_CTS_CHG_INT_RAW (BIT(6)) 20 | #define UART_DSR_CHG_INT_RAW (BIT(5)) 21 | #define UART_RXFIFO_OVF_INT_RAW (BIT(4)) 22 | #define UART_FRM_ERR_INT_RAW (BIT(3)) 23 | #define UART_PARITY_ERR_INT_RAW (BIT(2)) 24 | #define UART_TXFIFO_EMPTY_INT_RAW (BIT(1)) 25 | #define UART_RXFIFO_FULL_INT_RAW (BIT(0)) 26 | 27 | #define UART_INT_ST( i ) (REG_UART_BASE( i ) + 0x8) 28 | #define UART_RXFIFO_TOUT_INT_ST (BIT(8)) 29 | #define UART_BRK_DET_INT_ST (BIT(7)) 30 | #define UART_CTS_CHG_INT_ST (BIT(6)) 31 | #define UART_DSR_CHG_INT_ST (BIT(5)) 32 | #define UART_RXFIFO_OVF_INT_ST (BIT(4)) 33 | #define UART_FRM_ERR_INT_ST (BIT(3)) 34 | #define UART_PARITY_ERR_INT_ST (BIT(2)) 35 | #define UART_TXFIFO_EMPTY_INT_ST (BIT(1)) 36 | #define UART_RXFIFO_FULL_INT_ST (BIT(0)) 37 | 38 | #define UART_INT_ENA( i ) (REG_UART_BASE( i ) + 0xC) 39 | #define UART_RXFIFO_TOUT_INT_ENA (BIT(8)) 40 | #define UART_BRK_DET_INT_ENA (BIT(7)) 41 | #define UART_CTS_CHG_INT_ENA (BIT(6)) 42 | #define UART_DSR_CHG_INT_ENA (BIT(5)) 43 | #define UART_RXFIFO_OVF_INT_ENA (BIT(4)) 44 | #define UART_FRM_ERR_INT_ENA (BIT(3)) 45 | #define UART_PARITY_ERR_INT_ENA (BIT(2)) 46 | #define UART_TXFIFO_EMPTY_INT_ENA (BIT(1)) 47 | #define UART_RXFIFO_FULL_INT_ENA (BIT(0)) 48 | 49 | #define UART_INT_CLR( i ) (REG_UART_BASE( i ) + 0x10) 50 | #define UART_RXFIFO_TOUT_INT_CLR (BIT(8)) 51 | #define UART_BRK_DET_INT_CLR (BIT(7)) 52 | #define UART_CTS_CHG_INT_CLR (BIT(6)) 53 | #define UART_DSR_CHG_INT_CLR (BIT(5)) 54 | #define UART_RXFIFO_OVF_INT_CLR (BIT(4)) 55 | #define UART_FRM_ERR_INT_CLR (BIT(3)) 56 | #define UART_PARITY_ERR_INT_CLR (BIT(2)) 57 | #define UART_TXFIFO_EMPTY_INT_CLR (BIT(1)) 58 | #define UART_RXFIFO_FULL_INT_CLR (BIT(0)) 59 | 60 | #define UART_CLKDIV( i ) (REG_UART_BASE( i ) + 0x14) 61 | #define UART_CLKDIV_CNT 0x000FFFFF 62 | #define UART_CLKDIV_S 0 63 | 64 | #define UART_AUTOBAUD( i ) (REG_UART_BASE( i ) + 0x18) 65 | #define UART_GLITCH_FILT 0x000000FF 66 | #define UART_GLITCH_FILT_S 8 67 | #define UART_AUTOBAUD_EN (BIT(0)) 68 | 69 | #define UART_STATUS( i ) (REG_UART_BASE( i ) + 0x1C) 70 | #define UART_TXD (BIT(31)) 71 | #define UART_RTSN (BIT(30)) 72 | #define UART_DTRN (BIT(29)) 73 | #define UART_TXFIFO_CNT 0x000000FF 74 | #define UART_TXFIFO_CNT_S 16 75 | #define UART_RXD (BIT(15)) 76 | #define UART_CTSN (BIT(14)) 77 | #define UART_DSRN (BIT(13)) 78 | #define UART_RXFIFO_CNT 0x000000FF 79 | #define UART_RXFIFO_CNT_S 0 80 | 81 | #define UART_CONF0( i ) (REG_UART_BASE( i ) + 0x20) 82 | #define UART_TXFIFO_RST (BIT(18)) 83 | #define UART_RXFIFO_RST (BIT(17)) 84 | #define UART_IRDA_EN (BIT(16)) 85 | #define UART_TX_FLOW_EN (BIT(15)) 86 | #define UART_LOOPBACK (BIT(14)) 87 | #define UART_IRDA_RX_INV (BIT(13)) 88 | #define UART_IRDA_TX_INV (BIT(12)) 89 | #define UART_IRDA_WCTL (BIT(11)) 90 | #define UART_IRDA_TX_EN (BIT(10)) 91 | #define UART_IRDA_DPLX (BIT(9)) 92 | #define UART_TXD_BRK (BIT(8)) 93 | #define UART_SW_DTR (BIT(7)) 94 | #define UART_SW_RTS (BIT(6)) 95 | #define UART_STOP_BIT_NUM 0x00000003 96 | #define UART_STOP_BIT_NUM_S 4 97 | #define UART_BIT_NUM 0x00000003 98 | #define UART_BIT_NUM_S 2 99 | #define UART_PARITY_EN (BIT(1)) 100 | #define UART_PARITY (BIT(0)) 101 | 102 | #define UART_CONF1( i ) (REG_UART_BASE( i ) + 0x24) 103 | #define UART_RX_TOUT_EN (BIT(31)) 104 | #define UART_RX_TOUT_THRHD 0x0000007F 105 | #define UART_RX_TOUT_THRHD_S 24 106 | #define UART_RX_FLOW_EN (BIT(23)) 107 | #define UART_RX_FLOW_THRHD 0x0000007F 108 | #define UART_RX_FLOW_THRHD_S 16 109 | #define UART_TXFIFO_EMPTY_THRHD 0x0000007F 110 | #define UART_TXFIFO_EMPTY_THRHD_S 8 111 | #define UART_RXFIFO_FULL_THRHD 0x0000007F 112 | #define UART_RXFIFO_FULL_THRHD_S 0 113 | 114 | #define UART_LOWPULSE( i ) (REG_UART_BASE( i ) + 0x28) 115 | #define UART_LOWPULSE_MIN_CNT 0x000FFFFF 116 | #define UART_LOWPULSE_MIN_CNT_S 0 117 | 118 | #define UART_HIGHPULSE( i ) (REG_UART_BASE( i ) + 0x2C) 119 | #define UART_HIGHPULSE_MIN_CNT 0x000FFFFF 120 | #define UART_HIGHPULSE_MIN_CNT_S 0 121 | 122 | #define UART_PULSE_NUM( i ) (REG_UART_BASE( i ) + 0x30) 123 | #define UART_PULSE_NUM_CNT 0x0003FF 124 | #define UART_PULSE_NUM_CNT_S 0 125 | 126 | #define UART_DATE( i ) (REG_UART_BASE( i ) + 0x78) 127 | #define UART_ID( i ) (REG_UART_BASE( i ) + 0x7C) 128 | #endif // UART_REGISTER_H_INCLUDED 129 | -------------------------------------------------------------------------------- /mqtt/include/driver/uart_register.h: -------------------------------------------------------------------------------- 1 | //Generated at 2012-07-03 18:44:06 2 | /* 3 | * Copyright (c) 2010 - 2011 Espressif System 4 | * 5 | */ 6 | 7 | #ifndef UART_REGISTER_H_INCLUDED 8 | #define UART_REGISTER_H_INCLUDED 9 | #define REG_UART_BASE( i ) (0x60000000+(i)*0xf00) 10 | //version value:32'h062000 11 | 12 | #define UART_FIFO( i ) (REG_UART_BASE( i ) + 0x0) 13 | #define UART_RXFIFO_RD_BYTE 0x000000FF 14 | #define UART_RXFIFO_RD_BYTE_S 0 15 | 16 | #define UART_INT_RAW( i ) (REG_UART_BASE( i ) + 0x4) 17 | #define UART_RXFIFO_TOUT_INT_RAW (BIT(8)) 18 | #define UART_BRK_DET_INT_RAW (BIT(7)) 19 | #define UART_CTS_CHG_INT_RAW (BIT(6)) 20 | #define UART_DSR_CHG_INT_RAW (BIT(5)) 21 | #define UART_RXFIFO_OVF_INT_RAW (BIT(4)) 22 | #define UART_FRM_ERR_INT_RAW (BIT(3)) 23 | #define UART_PARITY_ERR_INT_RAW (BIT(2)) 24 | #define UART_TXFIFO_EMPTY_INT_RAW (BIT(1)) 25 | #define UART_RXFIFO_FULL_INT_RAW (BIT(0)) 26 | 27 | #define UART_INT_ST( i ) (REG_UART_BASE( i ) + 0x8) 28 | #define UART_RXFIFO_TOUT_INT_ST (BIT(8)) 29 | #define UART_BRK_DET_INT_ST (BIT(7)) 30 | #define UART_CTS_CHG_INT_ST (BIT(6)) 31 | #define UART_DSR_CHG_INT_ST (BIT(5)) 32 | #define UART_RXFIFO_OVF_INT_ST (BIT(4)) 33 | #define UART_FRM_ERR_INT_ST (BIT(3)) 34 | #define UART_PARITY_ERR_INT_ST (BIT(2)) 35 | #define UART_TXFIFO_EMPTY_INT_ST (BIT(1)) 36 | #define UART_RXFIFO_FULL_INT_ST (BIT(0)) 37 | 38 | #define UART_INT_ENA( i ) (REG_UART_BASE( i ) + 0xC) 39 | #define UART_RXFIFO_TOUT_INT_ENA (BIT(8)) 40 | #define UART_BRK_DET_INT_ENA (BIT(7)) 41 | #define UART_CTS_CHG_INT_ENA (BIT(6)) 42 | #define UART_DSR_CHG_INT_ENA (BIT(5)) 43 | #define UART_RXFIFO_OVF_INT_ENA (BIT(4)) 44 | #define UART_FRM_ERR_INT_ENA (BIT(3)) 45 | #define UART_PARITY_ERR_INT_ENA (BIT(2)) 46 | #define UART_TXFIFO_EMPTY_INT_ENA (BIT(1)) 47 | #define UART_RXFIFO_FULL_INT_ENA (BIT(0)) 48 | 49 | #define UART_INT_CLR( i ) (REG_UART_BASE( i ) + 0x10) 50 | #define UART_RXFIFO_TOUT_INT_CLR (BIT(8)) 51 | #define UART_BRK_DET_INT_CLR (BIT(7)) 52 | #define UART_CTS_CHG_INT_CLR (BIT(6)) 53 | #define UART_DSR_CHG_INT_CLR (BIT(5)) 54 | #define UART_RXFIFO_OVF_INT_CLR (BIT(4)) 55 | #define UART_FRM_ERR_INT_CLR (BIT(3)) 56 | #define UART_PARITY_ERR_INT_CLR (BIT(2)) 57 | #define UART_TXFIFO_EMPTY_INT_CLR (BIT(1)) 58 | #define UART_RXFIFO_FULL_INT_CLR (BIT(0)) 59 | 60 | #define UART_CLKDIV( i ) (REG_UART_BASE( i ) + 0x14) 61 | #define UART_CLKDIV_CNT 0x000FFFFF 62 | #define UART_CLKDIV_S 0 63 | 64 | #define UART_AUTOBAUD( i ) (REG_UART_BASE( i ) + 0x18) 65 | #define UART_GLITCH_FILT 0x000000FF 66 | #define UART_GLITCH_FILT_S 8 67 | #define UART_AUTOBAUD_EN (BIT(0)) 68 | 69 | #define UART_STATUS( i ) (REG_UART_BASE( i ) + 0x1C) 70 | #define UART_TXD (BIT(31)) 71 | #define UART_RTSN (BIT(30)) 72 | #define UART_DTRN (BIT(29)) 73 | #define UART_TXFIFO_CNT 0x000000FF 74 | #define UART_TXFIFO_CNT_S 16 75 | #define UART_RXD (BIT(15)) 76 | #define UART_CTSN (BIT(14)) 77 | #define UART_DSRN (BIT(13)) 78 | #define UART_RXFIFO_CNT 0x000000FF 79 | #define UART_RXFIFO_CNT_S 0 80 | 81 | #define UART_CONF0( i ) (REG_UART_BASE( i ) + 0x20) 82 | #define UART_TXFIFO_RST (BIT(18)) 83 | #define UART_RXFIFO_RST (BIT(17)) 84 | #define UART_IRDA_EN (BIT(16)) 85 | #define UART_TX_FLOW_EN (BIT(15)) 86 | #define UART_LOOPBACK (BIT(14)) 87 | #define UART_IRDA_RX_INV (BIT(13)) 88 | #define UART_IRDA_TX_INV (BIT(12)) 89 | #define UART_IRDA_WCTL (BIT(11)) 90 | #define UART_IRDA_TX_EN (BIT(10)) 91 | #define UART_IRDA_DPLX (BIT(9)) 92 | #define UART_TXD_BRK (BIT(8)) 93 | #define UART_SW_DTR (BIT(7)) 94 | #define UART_SW_RTS (BIT(6)) 95 | #define UART_STOP_BIT_NUM 0x00000003 96 | #define UART_STOP_BIT_NUM_S 4 97 | #define UART_BIT_NUM 0x00000003 98 | #define UART_BIT_NUM_S 2 99 | #define UART_PARITY_EN (BIT(1)) 100 | #define UART_PARITY (BIT(0)) 101 | 102 | #define UART_CONF1( i ) (REG_UART_BASE( i ) + 0x24) 103 | #define UART_RX_TOUT_EN (BIT(31)) 104 | #define UART_RX_TOUT_THRHD 0x0000007F 105 | #define UART_RX_TOUT_THRHD_S 24 106 | #define UART_RX_FLOW_EN (BIT(23)) 107 | #define UART_RX_FLOW_THRHD 0x0000007F 108 | #define UART_RX_FLOW_THRHD_S 16 109 | #define UART_TXFIFO_EMPTY_THRHD 0x0000007F 110 | #define UART_TXFIFO_EMPTY_THRHD_S 8 111 | #define UART_RXFIFO_FULL_THRHD 0x0000007F 112 | #define UART_RXFIFO_FULL_THRHD_S 0 113 | 114 | #define UART_LOWPULSE( i ) (REG_UART_BASE( i ) + 0x28) 115 | #define UART_LOWPULSE_MIN_CNT 0x000FFFFF 116 | #define UART_LOWPULSE_MIN_CNT_S 0 117 | 118 | #define UART_HIGHPULSE( i ) (REG_UART_BASE( i ) + 0x2C) 119 | #define UART_HIGHPULSE_MIN_CNT 0x000FFFFF 120 | #define UART_HIGHPULSE_MIN_CNT_S 0 121 | 122 | #define UART_PULSE_NUM( i ) (REG_UART_BASE( i ) + 0x30) 123 | #define UART_PULSE_NUM_CNT 0x0003FF 124 | #define UART_PULSE_NUM_CNT_S 0 125 | 126 | #define UART_DATE( i ) (REG_UART_BASE( i ) + 0x78) 127 | #define UART_ID( i ) (REG_UART_BASE( i ) + 0x7C) 128 | #endif // UART_REGISTER_H_INCLUDED 129 | -------------------------------------------------------------------------------- /mqtt/mqtt/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 | /* 7 6 5 4 3 2 1 0*/ 46 | /*| --- Message Type---- | DUP Flag | QoS Level | Retain | 47 | /* Remaining Length */ 48 | 49 | 50 | enum mqtt_message_type 51 | { 52 | MQTT_MSG_TYPE_CONNECT = 1, 53 | MQTT_MSG_TYPE_CONNACK = 2, 54 | MQTT_MSG_TYPE_PUBLISH = 3, 55 | MQTT_MSG_TYPE_PUBACK = 4, 56 | MQTT_MSG_TYPE_PUBREC = 5, 57 | MQTT_MSG_TYPE_PUBREL = 6, 58 | MQTT_MSG_TYPE_PUBCOMP = 7, 59 | MQTT_MSG_TYPE_SUBSCRIBE = 8, 60 | MQTT_MSG_TYPE_SUBACK = 9, 61 | MQTT_MSG_TYPE_UNSUBSCRIBE = 10, 62 | MQTT_MSG_TYPE_UNSUBACK = 11, 63 | MQTT_MSG_TYPE_PINGREQ = 12, 64 | MQTT_MSG_TYPE_PINGRESP = 13, 65 | MQTT_MSG_TYPE_DISCONNECT = 14 66 | }; 67 | 68 | typedef struct mqtt_message 69 | { 70 | uint8_t* data; 71 | uint16_t length; 72 | 73 | } mqtt_message_t; 74 | 75 | typedef struct mqtt_connection 76 | { 77 | mqtt_message_t message; 78 | 79 | uint16_t message_id; 80 | uint8_t* buffer; 81 | uint16_t buffer_length; 82 | 83 | } mqtt_connection_t; 84 | 85 | typedef struct mqtt_connect_info 86 | { 87 | char* client_id; 88 | char* username; 89 | char* password; 90 | char* will_topic; 91 | char* will_message; 92 | int keepalive; 93 | int will_qos; 94 | int will_retain; 95 | int clean_session; 96 | 97 | } mqtt_connect_info_t; 98 | 99 | 100 | static inline int ICACHE_FLASH_ATTR mqtt_get_type(uint8_t* buffer) { return (buffer[0] & 0xf0) >> 4; } 101 | static inline int ICACHE_FLASH_ATTR mqtt_get_dup(uint8_t* buffer) { return (buffer[0] & 0x08) >> 3; } 102 | static inline int ICACHE_FLASH_ATTR mqtt_get_qos(uint8_t* buffer) { return (buffer[0] & 0x06) >> 1; } 103 | static inline int ICACHE_FLASH_ATTR mqtt_get_retain(uint8_t* buffer) { return (buffer[0] & 0x01); } 104 | 105 | void ICACHE_FLASH_ATTR mqtt_msg_init(mqtt_connection_t* connection, uint8_t* buffer, uint16_t buffer_length); 106 | int ICACHE_FLASH_ATTR mqtt_get_total_length(uint8_t* buffer, uint16_t length); 107 | const char* ICACHE_FLASH_ATTR mqtt_get_publish_topic(uint8_t* buffer, uint16_t* length); 108 | const char* ICACHE_FLASH_ATTR mqtt_get_publish_data(uint8_t* buffer, uint16_t* length); 109 | uint16_t ICACHE_FLASH_ATTR mqtt_get_id(uint8_t* buffer, uint16_t length); 110 | 111 | mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_connect(mqtt_connection_t* connection, mqtt_connect_info_t* info); 112 | 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); 113 | mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_puback(mqtt_connection_t* connection, uint16_t message_id); 114 | mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_pubrec(mqtt_connection_t* connection, uint16_t message_id); 115 | mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_pubrel(mqtt_connection_t* connection, uint16_t message_id); 116 | mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_pubcomp(mqtt_connection_t* connection, uint16_t message_id); 117 | mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_subscribe(mqtt_connection_t* connection, const char* topic, int qos, uint16_t* message_id); 118 | mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_unsubscribe(mqtt_connection_t* connection, const char* topic, uint16_t* message_id); 119 | mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_pingreq(mqtt_connection_t* connection); 120 | mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_pingresp(mqtt_connection_t* connection); 121 | mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_disconnect(mqtt_connection_t* connection); 122 | 123 | 124 | #ifdef __cplusplus 125 | } 126 | #endif 127 | 128 | #endif /* MQTT_MSG_H */ 129 | 130 | -------------------------------------------------------------------------------- /mqtt/mqtt/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 | #include "mqtt_msg.h" 33 | #include "user_interface.h" 34 | 35 | #include "queue.h" 36 | typedef struct mqtt_event_data_t 37 | { 38 | uint8_t type; 39 | const char* topic; 40 | const char* data; 41 | uint16_t topic_length; 42 | uint16_t data_length; 43 | uint16_t data_offset; 44 | } mqtt_event_data_t; 45 | 46 | typedef struct mqtt_state_t 47 | { 48 | uint16_t port; 49 | int auto_reconnect; 50 | mqtt_connect_info_t* connect_info; 51 | uint8_t* in_buffer; 52 | uint8_t* out_buffer; 53 | int in_buffer_length; 54 | int out_buffer_length; 55 | uint16_t message_length; 56 | uint16_t message_length_read; 57 | mqtt_message_t* outbound_message; 58 | mqtt_connection_t mqtt_connection; 59 | uint16_t pending_msg_id; 60 | int pending_msg_type; 61 | int pending_publish_qos; 62 | } mqtt_state_t; 63 | 64 | typedef enum { 65 | WIFI_INIT, 66 | WIFI_CONNECTING, 67 | WIFI_CONNECTING_ERROR, 68 | WIFI_CONNECTED, 69 | DNS_RESOLVE, 70 | TCP_DISCONNECTED, 71 | TCP_RECONNECT_REQ, 72 | TCP_RECONNECT, 73 | TCP_CONNECTING, 74 | TCP_CONNECTING_ERROR, 75 | TCP_CONNECTED, 76 | MQTT_CONNECT_SEND, 77 | MQTT_CONNECT_SENDING, 78 | MQTT_SUBSCIBE_SEND, 79 | MQTT_SUBSCIBE_SENDING, 80 | MQTT_DATA, 81 | MQTT_PUBLISH_RECV, 82 | MQTT_PUBLISHING 83 | } tConnState; 84 | 85 | typedef void (*MqttCallback)(uint32_t *args); 86 | typedef void (*MqttDataCallback)(uint32_t *args, const char* topic, uint32_t topic_len, const char *data, uint32_t lengh); 87 | 88 | typedef struct { 89 | struct espconn *pCon; 90 | uint8_t security; 91 | uint8_t* host; 92 | uint32_t port; 93 | ip_addr_t ip; 94 | mqtt_state_t mqtt_state; 95 | mqtt_connect_info_t connect_info; 96 | MqttCallback connectedCb; 97 | MqttCallback disconnectedCb; 98 | MqttCallback publishedCb; 99 | MqttDataCallback dataCb; 100 | ETSTimer mqttTimer; 101 | uint32_t keepAliveTick; 102 | uint32_t reconnectTick; 103 | uint32_t sendTimeout; 104 | tConnState connState; 105 | QUEUE msgQueue; 106 | void* user_data; 107 | } MQTT_Client; 108 | 109 | #define SEC_NONSSL 0 110 | #define SEC_SSL 1 111 | 112 | #define MQTT_FLAG_CONNECTED 1 113 | #define MQTT_FLAG_READY 2 114 | #define MQTT_FLAG_EXIT 4 115 | 116 | #define MQTT_EVENT_TYPE_NONE 0 117 | #define MQTT_EVENT_TYPE_CONNECTED 1 118 | #define MQTT_EVENT_TYPE_DISCONNECTED 2 119 | #define MQTT_EVENT_TYPE_SUBSCRIBED 3 120 | #define MQTT_EVENT_TYPE_UNSUBSCRIBED 4 121 | #define MQTT_EVENT_TYPE_PUBLISH 5 122 | #define MQTT_EVENT_TYPE_PUBLISHED 6 123 | #define MQTT_EVENT_TYPE_EXITED 7 124 | #define MQTT_EVENT_TYPE_PUBLISH_CONTINUATION 8 125 | 126 | void ICACHE_FLASH_ATTR MQTT_InitConnection(MQTT_Client *mqttClient, uint8_t* host, uint32 port, uint8_t security); 127 | void ICACHE_FLASH_ATTR MQTT_InitClient(MQTT_Client *mqttClient, uint8_t* client_id, uint8_t* client_user, uint8_t* client_pass, uint32_t keepAliveTime, uint8_t cleanSession); 128 | void ICACHE_FLASH_ATTR MQTT_InitLWT(MQTT_Client *mqttClient, uint8_t* will_topic, uint8_t* will_msg, uint8_t will_qos, uint8_t will_retain); 129 | void ICACHE_FLASH_ATTR MQTT_OnConnected(MQTT_Client *mqttClient, MqttCallback connectedCb); 130 | void ICACHE_FLASH_ATTR MQTT_OnDisconnected(MQTT_Client *mqttClient, MqttCallback disconnectedCb); 131 | void ICACHE_FLASH_ATTR MQTT_OnPublished(MQTT_Client *mqttClient, MqttCallback publishedCb); 132 | void ICACHE_FLASH_ATTR MQTT_OnData(MQTT_Client *mqttClient, MqttDataCallback dataCb); 133 | BOOL ICACHE_FLASH_ATTR MQTT_Subscribe(MQTT_Client *client, char* topic, uint8_t qos); 134 | void ICACHE_FLASH_ATTR MQTT_Connect(MQTT_Client *mqttClient); 135 | void ICACHE_FLASH_ATTR MQTT_Disconnect(MQTT_Client *mqttClient); 136 | BOOL ICACHE_FLASH_ATTR MQTT_Publish(MQTT_Client *client, const char* topic, const char* data, int data_length, int qos, int retain); 137 | 138 | #endif /* USER_AT_MQTT_H_ */ 139 | -------------------------------------------------------------------------------- /driver/i2c_oled.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Oryginal by: 3 | * Author : Aaron Lee 4 | * Version: 1.00 5 | * Date : 2014.3.24 6 | * Email : hello14blog@gmail.com 7 | * Modification: none 8 | * Mod by reaper7 9 | * found at http://bbs.espressif.com/viewtopic.php?f=15&t=31 10 | */ 11 | 12 | #include "driver/i2c.h" 13 | #include "driver/i2c_oled.h" 14 | #include "driver/i2c_oled_fonts.h" 15 | #include "osapi.h" 16 | 17 | #define MAX_SMALL_FONTS 21 //SMALL FONTS 18 | #define MAX_BIG_FONTS 16 //BIG FONTS 19 | 20 | static bool oledstat = false; 21 | 22 | bool ICACHE_FLASH_ATTR 23 | OLED_writeReg(uint8_t reg_addr,uint8_t val) 24 | { 25 | i2c_start(); 26 | i2c_writeByte(OLED_ADDRESS); 27 | if(!i2c_check_ack()) { 28 | i2c_stop(); 29 | return 0; 30 | } 31 | i2c_writeByte(reg_addr); 32 | if(!i2c_check_ack()) { 33 | i2c_stop(); 34 | return 0; 35 | } 36 | i2c_writeByte(val&0xff); 37 | if(!i2c_check_ack()) { 38 | i2c_stop(); 39 | return 0; 40 | } 41 | i2c_stop(); 42 | 43 | if (reg_addr==0x00) 44 | oledstat=true; 45 | 46 | return 1; 47 | } 48 | 49 | void ICACHE_FLASH_ATTR 50 | OLED_writeCmd(unsigned char I2C_Command) 51 | { 52 | OLED_writeReg(0x00,I2C_Command); 53 | } 54 | 55 | void ICACHE_FLASH_ATTR 56 | OLED_writeDat(unsigned char I2C_Data) 57 | { 58 | OLED_writeReg(0x40,I2C_Data); 59 | } 60 | 61 | bool ICACHE_FLASH_ATTR 62 | OLED_Init(void) 63 | { 64 | os_delay_us(60000); 65 | os_delay_us(40000); 66 | 67 | OLED_writeCmd(0xae); // turn off oled panel 68 | OLED_writeCmd(0x00); // set low column address 69 | OLED_writeCmd(0x10); // set high column address 70 | OLED_writeCmd(0x40); // set start line address 71 | OLED_writeCmd(0x81); // set contrast control register 72 | 73 | OLED_writeCmd(0xa0); 74 | OLED_writeCmd(0xc0); 75 | 76 | OLED_writeCmd(0xa6); // set normal display 77 | OLED_writeCmd(0xa8); // set multiplex ratio(1 to 64) 78 | OLED_writeCmd(0x3f); // 1/64 duty 79 | OLED_writeCmd(0xd3); // set display offset 80 | OLED_writeCmd(0x00); // not offset 81 | OLED_writeCmd(0xd5); // set display clock divide ratio/oscillator frequency 82 | OLED_writeCmd(0x80); // set divide ratio 83 | OLED_writeCmd(0xd9); // set pre-charge period 84 | OLED_writeCmd(0xf1); 85 | OLED_writeCmd(0xda); // set com pins hardware configuration 86 | OLED_writeCmd(0x12); 87 | OLED_writeCmd(0xdb); // set vcomh 88 | OLED_writeCmd(0x40); 89 | OLED_writeCmd(0x8d); // set Charge Pump enable/disable 90 | OLED_writeCmd(0x14); // set(0x10) disable 91 | OLED_writeCmd(0xaf); // turn on oled panel 92 | 93 | OLED_Fill(0x00); //OLED CLS 94 | 95 | return oledstat; 96 | } 97 | 98 | void ICACHE_FLASH_ATTR 99 | OLED_SetPos(unsigned char x, unsigned char y) 100 | { 101 | OLED_writeCmd(0xb0+y); 102 | OLED_writeCmd(((x&0xf0)>>4)|0x10); 103 | OLED_writeCmd((x&0x0f)|0x01); 104 | } 105 | 106 | void ICACHE_FLASH_ATTR 107 | OLED_Fill(unsigned char fill_Data) 108 | { 109 | unsigned char m,n; 110 | for(m=0;m<8;m++) 111 | { 112 | OLED_writeCmd(0xb0+m); //page0-page1 113 | OLED_writeCmd(0x00); //low column start address 114 | OLED_writeCmd(0x10); //high column start address 115 | for(n=0;n<132;n++) 116 | { 117 | OLED_writeDat(fill_Data); 118 | } 119 | } 120 | } 121 | 122 | void ICACHE_FLASH_ATTR 123 | OLED_CLS(void) 124 | { 125 | OLED_Fill(0x00); 126 | } 127 | 128 | void ICACHE_FLASH_ATTR 129 | OLED_ON(void) 130 | { 131 | OLED_writeCmd(0X8D); 132 | OLED_writeCmd(0X14); 133 | OLED_writeCmd(0XAF); 134 | } 135 | 136 | void ICACHE_FLASH_ATTR 137 | OLED_OFF(void) 138 | { 139 | OLED_writeCmd(0X8D); 140 | OLED_writeCmd(0X10); 141 | OLED_writeCmd(0XAE); 142 | } 143 | 144 | void ICACHE_FLASH_ATTR 145 | OLED_ShowStr(unsigned char x, unsigned char y, unsigned char ch[], unsigned char TextSize) 146 | { 147 | unsigned char c = 0,i = 0,j = 0; 148 | switch(TextSize) 149 | { 150 | case 1: 151 | { 152 | while(ch[j] != '\0') 153 | { 154 | c = ch[j] - 32; 155 | if(x > 126) 156 | { 157 | x = 0; 158 | y++; 159 | } 160 | OLED_SetPos(x,y); 161 | for(i=0;i<6;i++) 162 | OLED_writeDat(F6x8[c][i]); 163 | x += 6; 164 | j++; 165 | } 166 | }break; 167 | case 2: 168 | { 169 | while(ch[j] != '\0') 170 | { 171 | c = ch[j] - 32; 172 | if(x > 120) 173 | { 174 | x = 0; 175 | y++; 176 | } 177 | OLED_SetPos(x,y); 178 | for(i=0;i<8;i++) 179 | OLED_writeDat(F8X16[c*16+i]); 180 | OLED_SetPos(x,y+1); 181 | for(i=0;i<8;i++) 182 | OLED_writeDat(F8X16[c*16+i+8]); 183 | x += 8; 184 | j++; 185 | } 186 | }break; 187 | } 188 | } 189 | 190 | void ICACHE_FLASH_ATTR 191 | OLED_Print(unsigned char x, unsigned char y, unsigned char ch[], unsigned char TextSize) 192 | { 193 | uint8_t step; 194 | if (TextSize==1) 195 | step = x*6; 196 | else if (TextSize==2) 197 | step = x*8; 198 | else 199 | step = x; 200 | OLED_ShowStr(step,y,ch,TextSize); 201 | } 202 | 203 | void ICACHE_FLASH_ATTR 204 | OLED_Line(unsigned char y, unsigned char ch[], unsigned char TextSize) 205 | { 206 | uint8 step; 207 | uint8 len = strlen(ch); 208 | uint8 maxf = 0; 209 | 210 | y--; 211 | 212 | if (TextSize==1) { 213 | maxf = MAX_SMALL_FONTS; 214 | } 215 | else if (TextSize==2) { 216 | y *= 2; 217 | maxf = MAX_BIG_FONTS; 218 | } 219 | 220 | if ((TextSize>=1) && (TextSize<=2)) { 221 | os_memset(ch+len+1,' ',maxf-len); 222 | os_memset(ch+maxf,'\0',1); 223 | 224 | OLED_ShowStr(0,y,ch,TextSize); 225 | } 226 | } 227 | 228 | void ICACHE_FLASH_ATTR 229 | OLED_DrawBMP(unsigned char x0,unsigned char y0,unsigned char x1,unsigned char y1,unsigned char BMP[]) 230 | { 231 | unsigned int j=0; 232 | unsigned char x,y; 233 | 234 | if(y1%8==0) 235 | y = y1/8; 236 | else 237 | y = y1/8 + 1; 238 | for(y=y0;yAMD64 60 | endif 61 | ifeq ($(PROCESSOR_ARCHITECTURE),x86) 62 | # ->IA32 63 | endif 64 | else 65 | # We are under other system, may be Linux. Assume using gcc. 66 | # Can we use -fdata-sections? 67 | ESPPORT ?= /dev/ttyUSB0 68 | SDK_BASE ?= /esptools/esp-open-sdk/sdk 69 | 70 | CCFLAGS += -Os -ffunction-sections -fno-jump-tables 71 | AR = xtensa-lx106-elf-ar 72 | CC = xtensa-lx106-elf-gcc 73 | LD = xtensa-lx106-elf-gcc 74 | NM = xtensa-lx106-elf-nm 75 | CPP = xtensa-lx106-elf-cpp 76 | OBJCOPY = xtensa-lx106-elf-objcopy 77 | UNAME_S := $(shell uname -s) 78 | 79 | ifeq ($(UNAME_S),Linux) 80 | # LINUX 81 | endif 82 | ifeq ($(UNAME_S),Darwin) 83 | # OSX 84 | endif 85 | UNAME_P := $(shell uname -p) 86 | ifeq ($(UNAME_P),x86_64) 87 | # ->AMD64 88 | endif 89 | ifneq ($(filter %86,$(UNAME_P)),) 90 | # ->IA32 91 | endif 92 | ifneq ($(filter arm%,$(UNAME_P)),) 93 | # ->ARM 94 | endif 95 | endif 96 | ############################################################# 97 | 98 | 99 | # which modules (subdirectories) of the project to include in compiling 100 | MODULES = driver mqtt user modules 101 | EXTRA_INCDIR = include $(SDK_BASE)/../include 102 | 103 | # libraries used in this project, mainly provided by the SDK 104 | LIBS = c gcc hal phy pp net80211 lwip wpa main ssl 105 | 106 | # compiler flags using during compilation of source files 107 | CFLAGS = -Os -Wpointer-arith -Wundef -Werror -Wl,-EL -fno-inline-functions -nostdlib -mlongcalls -mtext-section-literals -D__ets__ -DICACHE_FLASH 108 | 109 | # linker flags used to generate the main object file 110 | LDFLAGS = -nostdlib -Wl,--no-check-sections -u call_user_start -Wl,-static 111 | 112 | ifeq ($(FLAVOR),debug) 113 | CFLAGS += -g -O0 114 | LDFLAGS += -g -O0 115 | endif 116 | 117 | ifeq ($(FLAVOR),release) 118 | CFLAGS += -g -O2 119 | LDFLAGS += -g -O2 120 | endif 121 | 122 | 123 | 124 | # various paths from the SDK used in this project 125 | SDK_LIBDIR = lib 126 | SDK_LDDIR = ld 127 | SDK_INCDIR = include include/json 128 | 129 | #### 130 | #### no user configurable options below here 131 | #### 132 | FW_TOOL ?= $(ESPTOOL) 133 | SRC_DIR := $(MODULES) 134 | BUILD_DIR := $(addprefix $(BUILD_BASE)/,$(MODULES)) 135 | 136 | SDK_LIBDIR := $(addprefix $(SDK_BASE)/,$(SDK_LIBDIR)) 137 | SDK_INCDIR := $(addprefix -I$(SDK_BASE)/,$(SDK_INCDIR)) 138 | 139 | SRC := $(foreach sdir,$(SRC_DIR),$(wildcard $(sdir)/*.c)) 140 | OBJ := $(patsubst %.c,$(BUILD_BASE)/%.o,$(SRC)) 141 | LIBS := $(addprefix -l,$(LIBS)) 142 | APP_AR := $(addprefix $(BUILD_BASE)/,$(TARGET)_app.a) 143 | TARGET_OUT := $(addprefix $(BUILD_BASE)/,$(TARGET).out) 144 | 145 | LD_SCRIPT := $(addprefix -T$(SDK_BASE)/$(SDK_LDDIR)/,$(LD_SCRIPT)) 146 | 147 | INCDIR := $(addprefix -I,$(SRC_DIR)) 148 | EXTRA_INCDIR := $(addprefix -I,$(EXTRA_INCDIR)) 149 | MODULE_INCDIR := $(addsuffix /include,$(INCDIR)) 150 | 151 | FW_FILE_1 := $(addprefix $(FW_BASE)/,$(FW_1).bin) 152 | FW_FILE_2 := $(addprefix $(FW_BASE)/,$(FW_2).bin) 153 | 154 | V ?= $(VERBOSE) 155 | ifeq ("$(V)","1") 156 | Q := 157 | vecho := @true 158 | else 159 | Q := @ 160 | vecho := @echo 161 | endif 162 | 163 | vpath %.c $(SRC_DIR) 164 | 165 | define compile-objects 166 | $1/%.o: %.c 167 | $(vecho) "CC $$<" 168 | $(Q) $(CC) $(INCDIR) $(MODULE_INCDIR) $(EXTRA_INCDIR) $(SDK_INCDIR) $(CFLAGS) -c $$< -o $$@ 169 | endef 170 | 171 | .PHONY: all checkdirs clean 172 | 173 | all: checkdirs $(TARGET_OUT) $(FW_FILE_1) $(FW_FILE_2) 174 | 175 | $(FW_FILE_1): $(TARGET_OUT) 176 | $(vecho) "FW $@" 177 | $(ESPTOOL) elf2image $< -o $(FW_BASE)/ 178 | 179 | $(FW_FILE_2): $(TARGET_OUT) 180 | $(vecho) "FW $@" 181 | $(ESPTOOL) elf2image $< -o $(FW_BASE)/ 182 | 183 | $(TARGET_OUT): $(APP_AR) 184 | $(vecho) "LD $@" 185 | $(Q) $(LD) -L$(SDK_LIBDIR) $(LD_SCRIPT) $(LDFLAGS) -Wl,--start-group $(LIBS) $(APP_AR) -Wl,--end-group -o $@ 186 | 187 | $(APP_AR): $(OBJ) 188 | $(vecho) "AR $@" 189 | $(Q) $(AR) cru $@ $^ 190 | 191 | checkdirs: $(BUILD_DIR) $(FW_BASE) 192 | 193 | $(BUILD_DIR): 194 | $(Q) mkdir -p $@ 195 | 196 | firmware: 197 | $(Q) mkdir -p $@ 198 | 199 | flash: $(FW_FILE_1) $(FW_FILE_2) 200 | $(ESPTOOL) -p $(ESPPORT) write_flash $(FW_1) $(FW_FILE_1) $(FW_2) $(FW_FILE_2) 201 | 202 | test: flash 203 | screen $(ESPPORT) 115200 204 | 205 | rebuild: clean all 206 | 207 | clean: 208 | $(Q) rm -f $(APP_AR) 209 | $(Q) rm -f $(TARGET_OUT) 210 | $(Q) rm -rf $(BUILD_DIR) 211 | $(Q) rm -rf $(BUILD_BASE) 212 | $(Q) rm -f $(FW_FILE_1) 213 | $(Q) rm -f $(FW_FILE_2) 214 | $(Q) rm -rf $(FW_BASE) 215 | 216 | $(foreach bdir,$(BUILD_DIR),$(eval $(call compile-objects,$(bdir)))) 217 | -------------------------------------------------------------------------------- /driver/i2c.c: -------------------------------------------------------------------------------- 1 | /* 2 | I2C driver for the ESP8266 3 | Copyright (C) 2014 Rudy Hardeman (zarya) 4 | 5 | This program is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License along 16 | with this program; if not, write to the Free Software Foundation, Inc., 17 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 18 | */ 19 | 20 | #include "ets_sys.h" 21 | #include "osapi.h" 22 | #include "gpio.h" 23 | #include "driver/i2c.h" 24 | 25 | /** 26 | * Set SDA to state 27 | */ 28 | LOCAL void ICACHE_FLASH_ATTR 29 | i2c_sda(uint8 state) 30 | { 31 | state &= 0x01; 32 | //Set SDA line to state 33 | if (state) 34 | gpio_output_set(1 << I2C_SDA_PIN, 0, 1 << I2C_SDA_PIN, 0); 35 | else 36 | gpio_output_set(0, 1 << I2C_SDA_PIN, 1 << I2C_SDA_PIN, 0); 37 | } 38 | 39 | /** 40 | * Set SCK to state 41 | */ 42 | LOCAL void ICACHE_FLASH_ATTR 43 | i2c_sck(uint8 state) 44 | { 45 | //Set SCK line to state 46 | if (state) 47 | gpio_output_set(1 << I2C_SCK_PIN, 0, 1 << I2C_SCK_PIN, 0); 48 | else 49 | gpio_output_set(0, 1 << I2C_SCK_PIN, 1 << I2C_SCK_PIN, 0); 50 | } 51 | 52 | /** 53 | * I2C init function 54 | * This sets up the GPIO io 55 | */ 56 | void ICACHE_FLASH_ATTR 57 | i2c_init(void) 58 | { 59 | //Disable interrupts 60 | ETS_GPIO_INTR_DISABLE(); 61 | 62 | //Set pin functions 63 | PIN_FUNC_SELECT(I2C_SDA_MUX, I2C_SDA_FUNC); 64 | PIN_FUNC_SELECT(I2C_SCK_MUX, I2C_SCK_FUNC); 65 | 66 | //Set SDA as open drain 67 | GPIO_REG_WRITE( 68 | GPIO_PIN_ADDR(GPIO_ID_PIN(I2C_SDA_PIN)), 69 | GPIO_REG_READ(GPIO_PIN_ADDR(GPIO_ID_PIN(I2C_SDA_PIN))) | 70 | GPIO_PIN_PAD_DRIVER_SET(GPIO_PAD_DRIVER_ENABLE) 71 | ); 72 | 73 | GPIO_REG_WRITE(GPIO_ENABLE_ADDRESS, GPIO_REG_READ(GPIO_ENABLE_ADDRESS) | (1 << I2C_SDA_PIN)); 74 | 75 | //Set SCK as open drain 76 | GPIO_REG_WRITE( 77 | GPIO_PIN_ADDR(GPIO_ID_PIN(I2C_SCK_PIN)), 78 | GPIO_REG_READ(GPIO_PIN_ADDR(GPIO_ID_PIN(I2C_SCK_PIN))) | 79 | GPIO_PIN_PAD_DRIVER_SET(GPIO_PAD_DRIVER_ENABLE) 80 | ); 81 | 82 | GPIO_REG_WRITE(GPIO_ENABLE_ADDRESS, GPIO_REG_READ(GPIO_ENABLE_ADDRESS) | (1 << I2C_SCK_PIN)); 83 | 84 | //Turn interrupt back on 85 | ETS_GPIO_INTR_ENABLE(); 86 | 87 | i2c_sda(1); 88 | i2c_sck(1); 89 | return; 90 | } 91 | 92 | /** 93 | * I2C Start signal 94 | */ 95 | void ICACHE_FLASH_ATTR 96 | i2c_start(void) 97 | { 98 | i2c_sda(1); 99 | i2c_sck(1); 100 | os_delay_us(I2C_SLEEP_TIME); 101 | i2c_sda(0); 102 | os_delay_us(I2C_SLEEP_TIME); 103 | i2c_sck(0); 104 | os_delay_us(I2C_SLEEP_TIME); 105 | } 106 | 107 | /** 108 | * I2C Stop signal 109 | */ 110 | void ICACHE_FLASH_ATTR 111 | i2c_stop(void) 112 | { 113 | os_delay_us(I2C_SLEEP_TIME); 114 | i2c_sck(1); 115 | os_delay_us(I2C_SLEEP_TIME); 116 | i2c_sda(1); 117 | os_delay_us(I2C_SLEEP_TIME); 118 | } 119 | 120 | /** 121 | * Send I2C ACK to the bus 122 | * uint8 state 1 or 0 123 | * 1 for ACK 124 | * 0 for NACK 125 | */ 126 | void ICACHE_FLASH_ATTR 127 | i2c_send_ack(uint8 state) 128 | { 129 | i2c_sck(0); 130 | os_delay_us(I2C_SLEEP_TIME); 131 | //Set SDA 132 | // HIGH for NACK 133 | // LOW for ACK 134 | i2c_sda((state?0:1)); 135 | 136 | //Pulse the SCK 137 | i2c_sck(0); 138 | os_delay_us(I2C_SLEEP_TIME); 139 | i2c_sck(1); 140 | os_delay_us(I2C_SLEEP_TIME); 141 | i2c_sck(0); 142 | os_delay_us(I2C_SLEEP_TIME); 143 | 144 | i2c_sda(1); 145 | os_delay_us(I2C_SLEEP_TIME); 146 | } 147 | 148 | /** 149 | * Receive I2C ACK from the bus 150 | * returns 1 or 0 151 | * 1 for ACK 152 | * 0 for NACK 153 | */ 154 | uint8 ICACHE_FLASH_ATTR 155 | i2c_check_ack(void) 156 | { 157 | uint8 ack; 158 | i2c_sda(1); 159 | os_delay_us(I2C_SLEEP_TIME); 160 | i2c_sck(0); 161 | os_delay_us(I2C_SLEEP_TIME); 162 | i2c_sck(1); 163 | os_delay_us(I2C_SLEEP_TIME); 164 | 165 | //Get SDA pin status 166 | ack = i2c_read(); 167 | 168 | os_delay_us(I2C_SLEEP_TIME); 169 | i2c_sck(0); 170 | os_delay_us(I2C_SLEEP_TIME); 171 | i2c_sda(0); 172 | os_delay_us(I2C_SLEEP_TIME); 173 | 174 | return (ack?0:1); 175 | } 176 | 177 | /** 178 | * Receive byte from the I2C bus 179 | * returns the byte 180 | */ 181 | uint8 ICACHE_FLASH_ATTR 182 | i2c_readByte(void) 183 | { 184 | uint8 data = 0; 185 | uint8 data_bit; 186 | uint8 i; 187 | 188 | i2c_sda(1); 189 | 190 | for (i = 0; i < 8; i++) 191 | { 192 | os_delay_us(I2C_SLEEP_TIME); 193 | i2c_sck(0); 194 | os_delay_us(I2C_SLEEP_TIME); 195 | 196 | i2c_sck(1); 197 | os_delay_us(I2C_SLEEP_TIME); 198 | 199 | data_bit = i2c_read(); 200 | os_delay_us(I2C_SLEEP_TIME); 201 | 202 | data_bit <<= (7 - i); 203 | data |= data_bit; 204 | } 205 | i2c_sck(0); 206 | os_delay_us(I2C_SLEEP_TIME); 207 | 208 | return data; 209 | } 210 | 211 | /** 212 | * Write byte to I2C bus 213 | * uint8 data: to byte to be writen 214 | */ 215 | void ICACHE_FLASH_ATTR 216 | i2c_writeByte(uint8 data) 217 | { 218 | uint8 data_bit; 219 | sint8 i; 220 | 221 | os_delay_us(I2C_SLEEP_TIME); 222 | 223 | for (i = 7; i >= 0; i--) { 224 | data_bit = data >> i; 225 | i2c_sda(data_bit); 226 | os_delay_us(I2C_SLEEP_TIME); 227 | i2c_sck(1); 228 | os_delay_us(I2C_SLEEP_TIME); 229 | i2c_sck(0); 230 | os_delay_us(I2C_SLEEP_TIME); 231 | } 232 | } 233 | -------------------------------------------------------------------------------- /mqtt/README.md: -------------------------------------------------------------------------------- 1 | **esp_mqtt** 2 | ========== 3 | ![](https://travis-ci.org/tuanpmt/esp_mqtt.svg?branch=master) 4 | 5 | This is MQTT client library for ESP8266, port from: [MQTT client library for Contiki](https://github.com/esar/contiki-mqtt) (thanks) 6 | 7 | 8 | 9 | **Features:** 10 | 11 | * Support subscribing, publishing, authentication, will messages, keep alive pings and all 3 QoS levels (it should be a fully functional client). 12 | * Support multiple connection (to multiple hosts). 13 | * Support SSL connection (max 1024 bit key size) 14 | * Easy to setup and use 15 | 16 | **Compile:** 17 | 18 | Make sure to add PYTHON PATH and compile PATH to Eclipse environment variable if using Eclipse 19 | 20 | for Windows: 21 | 22 | ```bash 23 | git clone https://github.com/tuanpmt/esp_mqtt 24 | cd esp_mqtt 25 | #clean 26 | mingw32-make clean 27 | #make 28 | mingw32-make SDK_BASE="c:/Espressif/ESP8266_SDK" FLAVOR="release" all 29 | #flash 30 | mingw32-make ESPPORT="COM1" flash 31 | ``` 32 | 33 | for Mac or Linux: 34 | 35 | ```bash 36 | git clone https://github.com/tuanpmt/esp_mqtt 37 | cd esp_mqtt 38 | #clean 39 | make clean 40 | #make 41 | make SDK_BASE="/opt/Espressif/ESP8266_SDK" FLAVOR="release" all 42 | #flash 43 | make ESPPORT="/dev/ttyUSB0" flash 44 | ``` 45 | 46 | **Usage** 47 | ```c 48 | #include "ets_sys.h" 49 | #include "driver/uart.h" 50 | #include "osapi.h" 51 | #include "mqtt.h" 52 | #include "wifi.h" 53 | #include "config.h" 54 | #include "debug.h" 55 | #include "gpio.h" 56 | #include "user_interface.h" 57 | #include "mem.h" 58 | 59 | MQTT_Client mqttClient; 60 | 61 | void wifiConnectCb(uint8_t status) 62 | { 63 | if(status == STATION_GOT_IP){ 64 | MQTT_Connect(&mqttClient); 65 | } else { 66 | MQTT_Disconnect(&mqttClient); 67 | } 68 | } 69 | void mqttConnectedCb(uint32_t *args) 70 | { 71 | MQTT_Client* client = (MQTT_Client*)args; 72 | INFO("MQTT: Connected\r\n"); 73 | MQTT_Subscribe(client, "/mqtt/topic/0", 0); 74 | MQTT_Subscribe(client, "/mqtt/topic/1", 1); 75 | MQTT_Subscribe(client, "/mqtt/topic/2", 2); 76 | 77 | MQTT_Publish(client, "/mqtt/topic/0", "hello0", 6, 0, 0); 78 | MQTT_Publish(client, "/mqtt/topic/1", "hello1", 6, 1, 0); 79 | MQTT_Publish(client, "/mqtt/topic/2", "hello2", 6, 2, 0); 80 | 81 | } 82 | 83 | void mqttDisconnectedCb(uint32_t *args) 84 | { 85 | MQTT_Client* client = (MQTT_Client*)args; 86 | INFO("MQTT: Disconnected\r\n"); 87 | } 88 | 89 | void mqttPublishedCb(uint32_t *args) 90 | { 91 | MQTT_Client* client = (MQTT_Client*)args; 92 | INFO("MQTT: Published\r\n"); 93 | } 94 | 95 | void mqttDataCb(uint32_t *args, const char* topic, uint32_t topic_len, const char *data, uint32_t data_len) 96 | { 97 | char *topicBuf = (char*)os_zalloc(topic_len+1), 98 | *dataBuf = (char*)os_zalloc(data_len+1); 99 | 100 | MQTT_Client* client = (MQTT_Client*)args; 101 | 102 | os_memcpy(topicBuf, topic, topic_len); 103 | topicBuf[topic_len] = 0; 104 | 105 | os_memcpy(dataBuf, data, data_len); 106 | dataBuf[data_len] = 0; 107 | 108 | INFO("Receive topic: %s, data: %s \r\n", topicBuf, dataBuf); 109 | os_free(topicBuf); 110 | os_free(dataBuf); 111 | } 112 | 113 | 114 | void user_init(void) 115 | { 116 | uart_init(BIT_RATE_115200, BIT_RATE_115200); 117 | os_delay_us(1000000); 118 | 119 | CFG_Load(); 120 | 121 | MQTT_InitConnection(&mqttClient, sysCfg.mqtt_host, sysCfg.mqtt_port, sysCfg.security); 122 | //MQTT_InitConnection(&mqttClient, "192.168.11.122", 1880, 0); 123 | 124 | MQTT_InitClient(&mqttClient, sysCfg.device_id, sysCfg.mqtt_user, sysCfg.mqtt_pass, sysCfg.mqtt_keepalive, 1); 125 | //MQTT_InitClient(&mqttClient, "client_id", "user", "pass", 120, 1); 126 | 127 | MQTT_InitLWT(&mqttClient, "/lwt", "offline", 0, 0); 128 | MQTT_OnConnected(&mqttClient, mqttConnectedCb); 129 | MQTT_OnDisconnected(&mqttClient, mqttDisconnectedCb); 130 | MQTT_OnPublished(&mqttClient, mqttPublishedCb); 131 | MQTT_OnData(&mqttClient, mqttDataCb); 132 | 133 | WIFI_Connect(sysCfg.sta_ssid, sysCfg.sta_pwd, wifiConnectCb); 134 | 135 | INFO("\r\nSystem started ...\r\n"); 136 | } 137 | 138 | ``` 139 | 140 | **Publish message and Subscribe** 141 | 142 | ```c 143 | /* TRUE if success */ 144 | BOOL MQTT_Subscribe(MQTT_Client *client, char* topic, uint8_t qos); 145 | 146 | BOOL MQTT_Publish(MQTT_Client *client, const char* topic, const char* data, int data_length, int qos, int retain); 147 | 148 | ``` 149 | 150 | **Already support LWT: (Last Will and Testament)** 151 | 152 | ```c 153 | 154 | /* Broker will publish a message with qos = 0, retain = 0, data = "offline" to topic "/lwt" if client don't send keepalive packet */ 155 | MQTT_InitLWT(&mqttClient, "/lwt", "offline", 0, 0); 156 | 157 | ``` 158 | 159 | #Default configuration 160 | 161 | See: **include/user_config.h** 162 | 163 | If you want to load new default configurations, just change the value of CFG_HOLDER in **include/user_config.h** 164 | 165 | **Define protocol name in include/user_config.h** 166 | 167 | ```c 168 | #define PROTOCOL_NAMEv31 /*MQTT version 3.1 compatible with Mosquitto v0.15*/ 169 | //PROTOCOL_NAMEv311 /*MQTT version 3.11 compatible with https://eclipse.org/paho/clients/testing/*/ 170 | ``` 171 | 172 | In the Makefile, it will erase section hold the user configuration at 0x3C000 173 | 174 | ```bash 175 | flash: firmware/0x00000.bin firmware/0x40000.bin 176 | $(PYTHON) $(ESPTOOL) -p $(ESPPORT) write_flash 0x00000 firmware/0x00000.bin 0x3C000 $(BLANKER) 0x40000 firmware/0x40000.bin 177 | ``` 178 | The BLANKER is the blank.bin file you find in your SDKs bin folder. 179 | 180 | **Create SSL Self sign** 181 | 182 | ``` 183 | openssl req -x509 -newkey rsa:1024 -keyout key.pem -out cert.pem -days XXX 184 | ``` 185 | 186 | **SSL Mqtt broker for test** 187 | 188 | ```javascript 189 | var mosca = require('mosca') 190 | var SECURE_KEY = __dirname + '/key.pem'; 191 | var SECURE_CERT = __dirname + '/cert.pem'; 192 | var ascoltatore = { 193 | //using ascoltatore 194 | type: 'mongo', 195 | url: 'mongodb://localhost:27017/mqtt', 196 | pubsubCollection: 'ascoltatori', 197 | mongo: {} 198 | }; 199 | 200 | var moscaSettings = { 201 | port: 1880, 202 | stats: false, 203 | backend: ascoltatore, 204 | persistence: { 205 | factory: mosca.persistence.Mongo, 206 | url: 'mongodb://localhost:27017/mqtt' 207 | }, 208 | secure : { 209 | keyPath: SECURE_KEY, 210 | certPath: SECURE_CERT, 211 | port: 1883 212 | } 213 | }; 214 | 215 | var server = new mosca.Server(moscaSettings); 216 | server.on('ready', setup); 217 | 218 | server.on('clientConnected', function(client) { 219 | console.log('client connected', client.id); 220 | }); 221 | 222 | // fired when a message is received 223 | server.on('published', function(packet, client) { 224 | console.log('Published', packet.payload); 225 | }); 226 | 227 | // fired when the mqtt server is ready 228 | function setup() { 229 | console.log('Mosca server is up and running') 230 | } 231 | ``` 232 | 233 | **Example projects using esp_mqtt:**
234 | - [https://github.com/eadf/esp_mqtt_lcd](https://github.com/eadf/esp_mqtt_lcd) 235 | 236 | **Limited:**
237 | - Not fully supported retransmit for QoS1 and QoS2 238 | 239 | **Status:** *Pre release.* 240 | 241 | [https://github.com/tuanpmt/esp_mqtt/releases](https://github.com/tuanpmt/esp_mqtt/releases) 242 | 243 | [MQTT Broker for test](https://github.com/mcollina/mosca) 244 | 245 | [MQTT Client for test](https://chrome.google.com/webstore/detail/mqttlens/hemojaaeigabkbcookmlgmdigohjobjm?hl=en) 246 | 247 | **Contributing:** 248 | 249 | ***Feel free to contribute to the project in any way you like!*** 250 | 251 | **Requried:** 252 | 253 | SDK esp_iot_sdk_v0.9.4_14_12_19 or higher 254 | 255 | **Authors:** 256 | [Tuan PM](https://twitter.com/TuanPMT) 257 | 258 | **Donations** 259 | 260 | Invite me to a coffee 261 | [![Donate](https://www.paypalobjects.com/en_US/GB/i/btn/btn_donateCC_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=JR9RVLFC4GE6J) 262 | 263 | 264 | **LICENSE - "MIT License"** 265 | 266 | Copyright (c) 2014-2015 Tuan PM, https://twitter.com/TuanPMT 267 | 268 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 269 | 270 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 271 | 272 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 273 | -------------------------------------------------------------------------------- /driver/uart.c: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * Copyright 2013-2014 Espressif Systems (Wuxi) 3 | * 4 | * FileName: uart.c 5 | * 6 | * Description: Two UART mode configration and interrupt handler. 7 | * Check your hardware connection while use this mode. 8 | * 9 | * Modification history: 10 | * 2014/3/12, v1.0 create this file. 11 | *******************************************************************************/ 12 | #include "ets_sys.h" 13 | #include "osapi.h" 14 | #include "driver/uart.h" 15 | #include "osapi.h" 16 | #include "driver/uart_register.h" 17 | //#include "ssc.h" 18 | #include "at.h" 19 | 20 | // UartDev is defined and initialized in rom code. 21 | extern UartDevice UartDev; 22 | //extern os_event_t at_recvTaskQueue[at_recvTaskQueueLen]; 23 | 24 | LOCAL void uart0_rx_intr_handler(void *para); 25 | 26 | /****************************************************************************** 27 | * FunctionName : uart_config 28 | * Description : Internal used function 29 | * UART0 used for data TX/RX, RX buffer size is 0x100, interrupt enabled 30 | * UART1 just used for debug output 31 | * Parameters : uart_no, use UART0 or UART1 defined ahead 32 | * Returns : NONE 33 | *******************************************************************************/ 34 | LOCAL void ICACHE_FLASH_ATTR 35 | uart_config(uint8 uart_no) 36 | { 37 | if (uart_no == UART1) 38 | { 39 | PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO2_U, FUNC_U1TXD_BK); 40 | } 41 | else 42 | { 43 | /* rcv_buff size if 0x100 */ 44 | ETS_UART_INTR_ATTACH(uart0_rx_intr_handler, &(UartDev.rcv_buff)); 45 | PIN_PULLUP_DIS(PERIPHS_IO_MUX_U0TXD_U); 46 | PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_U0TXD); 47 | PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, FUNC_U0RTS); 48 | } 49 | 50 | uart_div_modify(uart_no, UART_CLK_FREQ / (UartDev.baut_rate)); 51 | 52 | WRITE_PERI_REG(UART_CONF0(uart_no), UartDev.exist_parity 53 | | UartDev.parity 54 | | (UartDev.stop_bits << UART_STOP_BIT_NUM_S) 55 | | (UartDev.data_bits << UART_BIT_NUM_S)); 56 | 57 | //clear rx and tx fifo,not ready 58 | SET_PERI_REG_MASK(UART_CONF0(uart_no), UART_RXFIFO_RST | UART_TXFIFO_RST); 59 | CLEAR_PERI_REG_MASK(UART_CONF0(uart_no), UART_RXFIFO_RST | UART_TXFIFO_RST); 60 | 61 | //set rx fifo trigger 62 | // WRITE_PERI_REG(UART_CONF1(uart_no), 63 | // ((UartDev.rcv_buff.TrigLvl & UART_RXFIFO_FULL_THRHD) << UART_RXFIFO_FULL_THRHD_S) | 64 | // ((96 & UART_TXFIFO_EMPTY_THRHD) << UART_TXFIFO_EMPTY_THRHD_S) | 65 | // UART_RX_FLOW_EN); 66 | if (uart_no == UART0) 67 | { 68 | //set rx fifo trigger 69 | WRITE_PERI_REG(UART_CONF1(uart_no), 70 | ((0x10 & UART_RXFIFO_FULL_THRHD) << UART_RXFIFO_FULL_THRHD_S) | 71 | ((0x10 & UART_RX_FLOW_THRHD) << UART_RX_FLOW_THRHD_S) | 72 | UART_RX_FLOW_EN | 73 | (0x02 & UART_RX_TOUT_THRHD) << UART_RX_TOUT_THRHD_S | 74 | UART_RX_TOUT_EN); 75 | SET_PERI_REG_MASK(UART_INT_ENA(uart_no), UART_RXFIFO_TOUT_INT_ENA | 76 | UART_FRM_ERR_INT_ENA); 77 | } 78 | else 79 | { 80 | WRITE_PERI_REG(UART_CONF1(uart_no), 81 | ((UartDev.rcv_buff.TrigLvl & UART_RXFIFO_FULL_THRHD) << UART_RXFIFO_FULL_THRHD_S)); 82 | } 83 | 84 | //clear all interrupt 85 | WRITE_PERI_REG(UART_INT_CLR(uart_no), 0xffff); 86 | //enable rx_interrupt 87 | SET_PERI_REG_MASK(UART_INT_ENA(uart_no), UART_RXFIFO_FULL_INT_ENA); 88 | } 89 | 90 | /****************************************************************************** 91 | * FunctionName : uart1_tx_one_char 92 | * Description : Internal used function 93 | * Use uart1 interface to transfer one char 94 | * Parameters : uint8 TxChar - character to tx 95 | * Returns : OK 96 | *******************************************************************************/ 97 | LOCAL STATUS 98 | uart_tx_one_char(uint8 uart, uint8 TxChar) 99 | { 100 | while (true) 101 | { 102 | uint32 fifo_cnt = READ_PERI_REG(UART_STATUS(uart)) & (UART_TXFIFO_CNT<> UART_TXFIFO_CNT_S & UART_TXFIFO_CNT) < 126) { 104 | break; 105 | } 106 | } 107 | 108 | WRITE_PERI_REG(UART_FIFO(uart) , TxChar); 109 | return OK; 110 | } 111 | 112 | /****************************************************************************** 113 | * FunctionName : uart1_write_char 114 | * Description : Internal used function 115 | * Do some special deal while tx char is '\r' or '\n' 116 | * Parameters : char c - character to tx 117 | * Returns : NONE 118 | *******************************************************************************/ 119 | LOCAL void ICACHE_FLASH_ATTR 120 | uart1_write_char(char c) 121 | { 122 | if (c == '\n') 123 | { 124 | uart_tx_one_char(UART1, '\r'); 125 | uart_tx_one_char(UART1, '\n'); 126 | } 127 | else if (c == '\r') 128 | { 129 | } 130 | else 131 | { 132 | uart_tx_one_char(UART1, c); 133 | } 134 | } 135 | /****************************************************************************** 136 | * FunctionName : uart0_tx_buffer 137 | * Description : use uart0 to transfer buffer 138 | * Parameters : uint8 *buf - point to send buffer 139 | * uint16 len - buffer len 140 | * Returns : 141 | *******************************************************************************/ 142 | void ICACHE_FLASH_ATTR 143 | uart0_tx_buffer(uint8 *buf, uint16 len) 144 | { 145 | uint16 i; 146 | 147 | for (i = 0; i < len; i++) 148 | { 149 | uart_tx_one_char(UART0, buf[i]); 150 | } 151 | } 152 | 153 | /****************************************************************************** 154 | * FunctionName : uart0_sendStr 155 | * Description : use uart0 to transfer buffer 156 | * Parameters : uint8 *buf - point to send buffer 157 | * uint16 len - buffer len 158 | * Returns : 159 | *******************************************************************************/ 160 | void ICACHE_FLASH_ATTR 161 | uart0_sendStr(const char *str) 162 | { 163 | while(*str) 164 | { 165 | uart_tx_one_char(UART0, *str++); 166 | } 167 | } 168 | 169 | /****************************************************************************** 170 | * FunctionName : uart0_rx_intr_handler 171 | * Description : Internal used function 172 | * UART0 interrupt handler, add self handle code inside 173 | * Parameters : void *para - point to ETS_UART_INTR_ATTACH's arg 174 | * Returns : NONE 175 | *******************************************************************************/ 176 | //extern void at_recvTask(void); 177 | 178 | LOCAL void 179 | uart0_rx_intr_handler(void *para) 180 | { 181 | /* uart0 and uart1 intr combine togther, when interrupt occur, see reg 0x3ff20020, bit2, bit0 represents 182 | * uart1 and uart0 respectively 183 | */ 184 | // RcvMsgBuff *pRxBuff = (RcvMsgBuff *)para; 185 | uint8 RcvChar; 186 | uint8 uart_no = UART0;//UartDev.buff_uart_no; 187 | 188 | // if (UART_RXFIFO_FULL_INT_ST != (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_RXFIFO_FULL_INT_ST)) 189 | // { 190 | // return; 191 | // } 192 | // if (UART_RXFIFO_FULL_INT_ST == (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_RXFIFO_FULL_INT_ST)) 193 | // { 194 | //// at_recvTask(); 195 | // RcvChar = READ_PERI_REG(UART_FIFO(uart_no)) & 0xFF; 196 | // system_os_post(at_recvTaskPrio, NULL, RcvChar); 197 | // WRITE_PERI_REG(UART_INT_CLR(uart_no), UART_RXFIFO_FULL_INT_CLR); 198 | // } 199 | if(UART_FRM_ERR_INT_ST == (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_FRM_ERR_INT_ST)) 200 | { 201 | os_printf("FRM_ERR\r\n"); 202 | WRITE_PERI_REG(UART_INT_CLR(uart_no), UART_FRM_ERR_INT_CLR); 203 | } 204 | 205 | if(UART_RXFIFO_FULL_INT_ST == (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_RXFIFO_FULL_INT_ST)) 206 | { 207 | // os_printf("fifo full\r\n"); 208 | ETS_UART_INTR_DISABLE();///////// 209 | 210 | system_os_post(at_recvTaskPrio, 0, 0); 211 | 212 | // WRITE_PERI_REG(UART_INT_CLR(uart_no), UART_RXFIFO_FULL_INT_CLR); 213 | // while (READ_PERI_REG(UART_STATUS(uart_no)) & (UART_RXFIFO_CNT << UART_RXFIFO_CNT_S)) 214 | // { 215 | //// at_recvTask(); 216 | // RcvChar = READ_PERI_REG(UART_FIFO(uart_no)) & 0xFF; 217 | // system_os_post(at_recvTaskPrio, NULL, RcvChar); 218 | // } 219 | } 220 | else if(UART_RXFIFO_TOUT_INT_ST == (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_RXFIFO_TOUT_INT_ST)) 221 | { 222 | ETS_UART_INTR_DISABLE();///////// 223 | 224 | system_os_post(at_recvTaskPrio, 0, 0); 225 | 226 | // WRITE_PERI_REG(UART_INT_CLR(uart_no), UART_RXFIFO_TOUT_INT_CLR); 227 | //// os_printf("rx time over\r\n"); 228 | // while (READ_PERI_REG(UART_STATUS(uart_no)) & (UART_RXFIFO_CNT << UART_RXFIFO_CNT_S)) 229 | // { 230 | //// os_printf("process recv\r\n"); 231 | //// at_recvTask(); 232 | // RcvChar = READ_PERI_REG(UART_FIFO(uart_no)) & 0xFF; 233 | // system_os_post(at_recvTaskPrio, NULL, RcvChar); 234 | // } 235 | } 236 | 237 | // WRITE_PERI_REG(UART_INT_CLR(uart_no), UART_RXFIFO_FULL_INT_CLR); 238 | 239 | // if (READ_PERI_REG(UART_STATUS(uart_no)) & (UART_RXFIFO_CNT << UART_RXFIFO_CNT_S)) 240 | // { 241 | // RcvChar = READ_PERI_REG(UART_FIFO(uart_no)) & 0xFF; 242 | // at_recvTask(); 243 | // *(pRxBuff->pWritePos) = RcvChar; 244 | 245 | // system_os_post(at_recvTaskPrio, NULL, RcvChar); 246 | 247 | // //insert here for get one command line from uart 248 | // if (RcvChar == '\r') 249 | // { 250 | // pRxBuff->BuffState = WRITE_OVER; 251 | // } 252 | // 253 | // pRxBuff->pWritePos++; 254 | // 255 | // if (pRxBuff->pWritePos == (pRxBuff->pRcvMsgBuff + RX_BUFF_SIZE)) 256 | // { 257 | // // overflow ...we may need more error handle here. 258 | // pRxBuff->pWritePos = pRxBuff->pRcvMsgBuff ; 259 | // } 260 | // } 261 | } 262 | 263 | /****************************************************************************** 264 | * FunctionName : uart_init 265 | * Description : user interface for init uart 266 | * Parameters : UartBautRate uart0_br - uart0 bautrate 267 | * UartBautRate uart1_br - uart1 bautrate 268 | * Returns : NONE 269 | *******************************************************************************/ 270 | void ICACHE_FLASH_ATTR 271 | uart_init(UartBautRate uart0_br, UartBautRate uart1_br) 272 | { 273 | // rom use 74880 baut_rate, here reinitialize 274 | UartDev.baut_rate = uart0_br; 275 | uart_config(UART0); 276 | UartDev.baut_rate = uart1_br; 277 | uart_config(UART1); 278 | ETS_UART_INTR_ENABLE(); 279 | 280 | // install uart1 putc callback 281 | os_install_putc1((void *)uart1_write_char); 282 | } 283 | 284 | void ICACHE_FLASH_ATTR 285 | uart_reattach() 286 | { 287 | uart_init(BIT_RATE_74880, BIT_RATE_74880); 288 | // ETS_UART_INTR_ATTACH(uart_rx_intr_handler_ssc, &(UartDev.rcv_buff)); 289 | // ETS_UART_INTR_ENABLE(); 290 | } 291 | -------------------------------------------------------------------------------- /mqtt/driver/uart.c: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * Copyright 2013-2014 Espressif Systems (Wuxi) 3 | * 4 | * FileName: uart.c 5 | * 6 | * Description: Two UART mode configration and interrupt handler. 7 | * Check your hardware connection while use this mode. 8 | * 9 | * Modification history: 10 | * 2014/3/12, v1.0 create this file. 11 | *******************************************************************************/ 12 | #include "ets_sys.h" 13 | #include "osapi.h" 14 | #include "driver/uart.h" 15 | #include "osapi.h" 16 | #include "driver/uart_register.h" 17 | //#include "ssc.h" 18 | 19 | 20 | // UartDev is defined and initialized in rom code. 21 | extern UartDevice UartDev; 22 | //extern os_event_t at_recvTaskQueue[at_recvTaskQueueLen]; 23 | 24 | LOCAL void uart0_rx_intr_handler(void *para); 25 | 26 | /****************************************************************************** 27 | * FunctionName : uart_config 28 | * Description : Internal used function 29 | * UART0 used for data TX/RX, RX buffer size is 0x100, interrupt enabled 30 | * UART1 just used for debug output 31 | * Parameters : uart_no, use UART0 or UART1 defined ahead 32 | * Returns : NONE 33 | *******************************************************************************/ 34 | LOCAL void ICACHE_FLASH_ATTR 35 | uart_config(uint8 uart_no) 36 | { 37 | if (uart_no == UART1) 38 | { 39 | PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO2_U, FUNC_U1TXD_BK); 40 | } 41 | else 42 | { 43 | /* rcv_buff size if 0x100 */ 44 | ETS_UART_INTR_ATTACH(uart0_rx_intr_handler, &(UartDev.rcv_buff)); 45 | PIN_PULLUP_DIS(PERIPHS_IO_MUX_U0TXD_U); 46 | PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_U0TXD); 47 | PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, FUNC_U0RTS); 48 | } 49 | 50 | uart_div_modify(uart_no, UART_CLK_FREQ / (UartDev.baut_rate)); 51 | 52 | WRITE_PERI_REG(UART_CONF0(uart_no), UartDev.exist_parity 53 | | UartDev.parity 54 | | (UartDev.stop_bits << UART_STOP_BIT_NUM_S) 55 | | (UartDev.data_bits << UART_BIT_NUM_S)); 56 | 57 | //clear rx and tx fifo,not ready 58 | SET_PERI_REG_MASK(UART_CONF0(uart_no), UART_RXFIFO_RST | UART_TXFIFO_RST); 59 | CLEAR_PERI_REG_MASK(UART_CONF0(uart_no), UART_RXFIFO_RST | UART_TXFIFO_RST); 60 | 61 | //set rx fifo trigger 62 | // WRITE_PERI_REG(UART_CONF1(uart_no), 63 | // ((UartDev.rcv_buff.TrigLvl & UART_RXFIFO_FULL_THRHD) << UART_RXFIFO_FULL_THRHD_S) | 64 | // ((96 & UART_TXFIFO_EMPTY_THRHD) << UART_TXFIFO_EMPTY_THRHD_S) | 65 | // UART_RX_FLOW_EN); 66 | if (uart_no == UART0) 67 | { 68 | //set rx fifo trigger 69 | WRITE_PERI_REG(UART_CONF1(uart_no), 70 | ((0x10 & UART_RXFIFO_FULL_THRHD) << UART_RXFIFO_FULL_THRHD_S) | 71 | ((0x10 & UART_RX_FLOW_THRHD) << UART_RX_FLOW_THRHD_S) | 72 | UART_RX_FLOW_EN | 73 | (0x02 & UART_RX_TOUT_THRHD) << UART_RX_TOUT_THRHD_S | 74 | UART_RX_TOUT_EN); 75 | SET_PERI_REG_MASK(UART_INT_ENA(uart_no), UART_RXFIFO_TOUT_INT_ENA | 76 | UART_FRM_ERR_INT_ENA); 77 | } 78 | else 79 | { 80 | WRITE_PERI_REG(UART_CONF1(uart_no), 81 | ((UartDev.rcv_buff.TrigLvl & UART_RXFIFO_FULL_THRHD) << UART_RXFIFO_FULL_THRHD_S)); 82 | } 83 | 84 | //clear all interrupt 85 | WRITE_PERI_REG(UART_INT_CLR(uart_no), 0xffff); 86 | //enable rx_interrupt 87 | SET_PERI_REG_MASK(UART_INT_ENA(uart_no), UART_RXFIFO_FULL_INT_ENA); 88 | } 89 | 90 | /****************************************************************************** 91 | * FunctionName : uart1_tx_one_char 92 | * Description : Internal used function 93 | * Use uart1 interface to transfer one char 94 | * Parameters : uint8 TxChar - character to tx 95 | * Returns : OK 96 | *******************************************************************************/ 97 | LOCAL STATUS 98 | uart_tx_one_char(uint8 uart, uint8 TxChar) 99 | { 100 | while (true) 101 | { 102 | uint32 fifo_cnt = READ_PERI_REG(UART_STATUS(uart)) & (UART_TXFIFO_CNT<> UART_TXFIFO_CNT_S & UART_TXFIFO_CNT) < 126) { 104 | break; 105 | } 106 | } 107 | 108 | WRITE_PERI_REG(UART_FIFO(uart) , TxChar); 109 | return OK; 110 | } 111 | 112 | /****************************************************************************** 113 | * FunctionName : uart1_write_char 114 | * Description : Internal used function 115 | * Do some special deal while tx char is '\r' or '\n' 116 | * Parameters : char c - character to tx 117 | * Returns : NONE 118 | *******************************************************************************/ 119 | void ICACHE_FLASH_ATTR 120 | uart1_write_char(char c) 121 | { 122 | if (c == '\n') 123 | { 124 | uart_tx_one_char(UART1, '\r'); 125 | uart_tx_one_char(UART1, '\n'); 126 | } 127 | else if (c == '\r') 128 | { 129 | } 130 | else 131 | { 132 | uart_tx_one_char(UART1, c); 133 | } 134 | } 135 | 136 | void ICACHE_FLASH_ATTR 137 | uart0_write_char(char c) 138 | { 139 | if (c == '\n') 140 | { 141 | uart_tx_one_char(UART0, '\r'); 142 | uart_tx_one_char(UART0, '\n'); 143 | } 144 | else if (c == '\r') 145 | { 146 | } 147 | else 148 | { 149 | uart_tx_one_char(UART0, c); 150 | } 151 | } 152 | /****************************************************************************** 153 | * FunctionName : uart0_tx_buffer 154 | * Description : use uart0 to transfer buffer 155 | * Parameters : uint8 *buf - point to send buffer 156 | * uint16 len - buffer len 157 | * Returns : 158 | *******************************************************************************/ 159 | void ICACHE_FLASH_ATTR 160 | uart0_tx_buffer(uint8 *buf, uint16 len) 161 | { 162 | uint16 i; 163 | 164 | for (i = 0; i < len; i++) 165 | { 166 | uart_tx_one_char(UART0, buf[i]); 167 | } 168 | } 169 | 170 | /****************************************************************************** 171 | * FunctionName : uart0_sendStr 172 | * Description : use uart0 to transfer buffer 173 | * Parameters : uint8 *buf - point to send buffer 174 | * uint16 len - buffer len 175 | * Returns : 176 | *******************************************************************************/ 177 | void ICACHE_FLASH_ATTR 178 | uart0_sendStr(const char *str) 179 | { 180 | while(*str) 181 | { 182 | uart_tx_one_char(UART0, *str++); 183 | } 184 | } 185 | 186 | /****************************************************************************** 187 | * FunctionName : uart0_rx_intr_handler 188 | * Description : Internal used function 189 | * UART0 interrupt handler, add self handle code inside 190 | * Parameters : void *para - point to ETS_UART_INTR_ATTACH's arg 191 | * Returns : NONE 192 | *******************************************************************************/ 193 | //extern void at_recvTask(void); 194 | 195 | LOCAL void 196 | uart0_rx_intr_handler(void *para) 197 | { 198 | /* uart0 and uart1 intr combine togther, when interrupt occur, see reg 0x3ff20020, bit2, bit0 represents 199 | * uart1 and uart0 respectively 200 | */ 201 | // RcvMsgBuff *pRxBuff = (RcvMsgBuff *)para; 202 | uint8 RcvChar; 203 | uint8 uart_no = UART0;//UartDev.buff_uart_no; 204 | 205 | // if (UART_RXFIFO_FULL_INT_ST != (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_RXFIFO_FULL_INT_ST)) 206 | // { 207 | // return; 208 | // } 209 | // if (UART_RXFIFO_FULL_INT_ST == (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_RXFIFO_FULL_INT_ST)) 210 | // { 211 | //// at_recvTask(); 212 | // RcvChar = READ_PERI_REG(UART_FIFO(uart_no)) & 0xFF; 213 | // system_os_post(at_recvTaskPrio, NULL, RcvChar); 214 | // WRITE_PERI_REG(UART_INT_CLR(uart_no), UART_RXFIFO_FULL_INT_CLR); 215 | // } 216 | if(UART_FRM_ERR_INT_ST == (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_FRM_ERR_INT_ST)) 217 | { 218 | os_printf("FRM_ERR\r\n"); 219 | WRITE_PERI_REG(UART_INT_CLR(uart_no), UART_FRM_ERR_INT_CLR); 220 | } 221 | 222 | if(UART_RXFIFO_FULL_INT_ST == (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_RXFIFO_FULL_INT_ST)) 223 | { 224 | // os_printf("fifo full\r\n"); 225 | ETS_UART_INTR_DISABLE();///////// 226 | 227 | //system_os_post(at_recvTaskPrio, 0, 0); 228 | 229 | // WRITE_PERI_REG(UART_INT_CLR(uart_no), UART_RXFIFO_FULL_INT_CLR); 230 | // while (READ_PERI_REG(UART_STATUS(uart_no)) & (UART_RXFIFO_CNT << UART_RXFIFO_CNT_S)) 231 | // { 232 | //// at_recvTask(); 233 | // RcvChar = READ_PERI_REG(UART_FIFO(uart_no)) & 0xFF; 234 | // system_os_post(at_recvTaskPrio, NULL, RcvChar); 235 | // } 236 | } 237 | else if(UART_RXFIFO_TOUT_INT_ST == (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_RXFIFO_TOUT_INT_ST)) 238 | { 239 | ETS_UART_INTR_DISABLE();///////// 240 | 241 | //system_os_post(at_recvTaskPrio, 0, 0); 242 | 243 | // WRITE_PERI_REG(UART_INT_CLR(uart_no), UART_RXFIFO_TOUT_INT_CLR); 244 | //// os_printf("rx time over\r\n"); 245 | // while (READ_PERI_REG(UART_STATUS(uart_no)) & (UART_RXFIFO_CNT << UART_RXFIFO_CNT_S)) 246 | // { 247 | //// os_printf("process recv\r\n"); 248 | //// at_recvTask(); 249 | // RcvChar = READ_PERI_REG(UART_FIFO(uart_no)) & 0xFF; 250 | // system_os_post(at_recvTaskPrio, NULL, RcvChar); 251 | // } 252 | } 253 | 254 | // WRITE_PERI_REG(UART_INT_CLR(uart_no), UART_RXFIFO_FULL_INT_CLR); 255 | 256 | // if (READ_PERI_REG(UART_STATUS(uart_no)) & (UART_RXFIFO_CNT << UART_RXFIFO_CNT_S)) 257 | // { 258 | // RcvChar = READ_PERI_REG(UART_FIFO(uart_no)) & 0xFF; 259 | // at_recvTask(); 260 | // *(pRxBuff->pWritePos) = RcvChar; 261 | 262 | // system_os_post(at_recvTaskPrio, NULL, RcvChar); 263 | 264 | // //insert here for get one command line from uart 265 | // if (RcvChar == '\r') 266 | // { 267 | // pRxBuff->BuffState = WRITE_OVER; 268 | // } 269 | // 270 | // pRxBuff->pWritePos++; 271 | // 272 | // if (pRxBuff->pWritePos == (pRxBuff->pRcvMsgBuff + RX_BUFF_SIZE)) 273 | // { 274 | // // overflow ...we may need more error handle here. 275 | // pRxBuff->pWritePos = pRxBuff->pRcvMsgBuff ; 276 | // } 277 | // } 278 | } 279 | 280 | /****************************************************************************** 281 | * FunctionName : uart_init 282 | * Description : user interface for init uart 283 | * Parameters : UartBautRate uart0_br - uart0 bautrate 284 | * UartBautRate uart1_br - uart1 bautrate 285 | * Returns : NONE 286 | *******************************************************************************/ 287 | void ICACHE_FLASH_ATTR 288 | uart_init(UartBautRate uart0_br, UartBautRate uart1_br) 289 | { 290 | // rom use 74880 baut_rate, here reinitialize 291 | UartDev.baut_rate = uart0_br; 292 | uart_config(UART0); 293 | UartDev.baut_rate = uart1_br; 294 | uart_config(UART1); 295 | ETS_UART_INTR_ENABLE(); 296 | 297 | // install uart1 putc callback 298 | os_install_putc1((void *)uart0_write_char); 299 | } 300 | 301 | void ICACHE_FLASH_ATTR 302 | uart_reattach() 303 | { 304 | uart_init(BIT_RATE_74880, BIT_RATE_74880); 305 | // ETS_UART_INTR_ATTACH(uart_rx_intr_handler_ssc, &(UartDev.rcv_buff)); 306 | // ETS_UART_INTR_ENABLE(); 307 | } 308 | -------------------------------------------------------------------------------- /include/driver/i2c_oled_fonts.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Oryginal by: 3 | * Author : Aaron Lee 4 | * Version: 1.00 5 | * Date : 2014.3.24 6 | * Email : hello14blog@gmail.com 7 | * Modification: none 8 | * Mod by reaper7 9 | * found at http://bbs.espressif.com/viewtopic.php?f=15&t=31 10 | */ 11 | 12 | const unsigned char F6x8[][6] = 13 | { 14 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,// sp 15 | 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00,// ! 16 | 0x00, 0x00, 0x07, 0x00, 0x07, 0x00,// " 17 | 0x00, 0x14, 0x7f, 0x14, 0x7f, 0x14,// # 18 | 0x00, 0x24, 0x2a, 0x7f, 0x2a, 0x12,// $ 19 | 0x00, 0x62, 0x64, 0x08, 0x13, 0x23,// % 20 | 0x00, 0x36, 0x49, 0x55, 0x22, 0x50,// & 21 | 0x00, 0x00, 0x05, 0x03, 0x00, 0x00,// ' 22 | 0x00, 0x00, 0x1c, 0x22, 0x41, 0x00,// ( 23 | 0x00, 0x00, 0x41, 0x22, 0x1c, 0x00,// ) 24 | 0x00, 0x14, 0x08, 0x3E, 0x08, 0x14,// * 25 | 0x00, 0x08, 0x08, 0x3E, 0x08, 0x08,// + 26 | 0x00, 0x00, 0x00, 0xA0, 0x60, 0x00,// , 27 | 0x00, 0x08, 0x08, 0x08, 0x08, 0x08,// - 28 | 0x00, 0x00, 0x60, 0x60, 0x00, 0x00,// . 29 | 0x00, 0x20, 0x10, 0x08, 0x04, 0x02,// / 30 | 0x00, 0x3E, 0x51, 0x49, 0x45, 0x3E,// 0 31 | 0x00, 0x00, 0x42, 0x7F, 0x40, 0x00,// 1 32 | 0x00, 0x42, 0x61, 0x51, 0x49, 0x46,// 2 33 | 0x00, 0x21, 0x41, 0x45, 0x4B, 0x31,// 3 34 | 0x00, 0x18, 0x14, 0x12, 0x7F, 0x10,// 4 35 | 0x00, 0x27, 0x45, 0x45, 0x45, 0x39,// 5 36 | 0x00, 0x3C, 0x4A, 0x49, 0x49, 0x30,// 6 37 | 0x00, 0x01, 0x71, 0x09, 0x05, 0x03,// 7 38 | 0x00, 0x36, 0x49, 0x49, 0x49, 0x36,// 8 39 | 0x00, 0x06, 0x49, 0x49, 0x29, 0x1E,// 9 40 | 0x00, 0x00, 0x36, 0x36, 0x00, 0x00,// : 41 | 0x00, 0x00, 0x56, 0x36, 0x00, 0x00,// ; 42 | 0x00, 0x08, 0x14, 0x22, 0x41, 0x00,// < 43 | 0x00, 0x14, 0x14, 0x14, 0x14, 0x14,// = 44 | 0x00, 0x00, 0x41, 0x22, 0x14, 0x08,// > 45 | 0x00, 0x02, 0x01, 0x51, 0x09, 0x06,// ? 46 | 0x00, 0x32, 0x49, 0x59, 0x51, 0x3E,// @ 47 | 0x00, 0x7C, 0x12, 0x11, 0x12, 0x7C,// A 48 | 0x00, 0x7F, 0x49, 0x49, 0x49, 0x36,// B 49 | 0x00, 0x3E, 0x41, 0x41, 0x41, 0x22,// C 50 | 0x00, 0x7F, 0x41, 0x41, 0x22, 0x1C,// D 51 | 0x00, 0x7F, 0x49, 0x49, 0x49, 0x41,// E 52 | 0x00, 0x7F, 0x09, 0x09, 0x09, 0x01,// F 53 | 0x00, 0x3E, 0x41, 0x49, 0x49, 0x7A,// G 54 | 0x00, 0x7F, 0x08, 0x08, 0x08, 0x7F,// H 55 | 0x00, 0x00, 0x41, 0x7F, 0x41, 0x00,// I 56 | 0x00, 0x20, 0x40, 0x41, 0x3F, 0x01,// J 57 | 0x00, 0x7F, 0x08, 0x14, 0x22, 0x41,// K 58 | 0x00, 0x7F, 0x40, 0x40, 0x40, 0x40,// L 59 | 0x00, 0x7F, 0x02, 0x0C, 0x02, 0x7F,// M 60 | 0x00, 0x7F, 0x04, 0x08, 0x10, 0x7F,// N 61 | 0x00, 0x3E, 0x41, 0x41, 0x41, 0x3E,// O 62 | 0x00, 0x7F, 0x09, 0x09, 0x09, 0x06,// P 63 | 0x00, 0x3E, 0x41, 0x51, 0x21, 0x5E,// Q 64 | 0x00, 0x7F, 0x09, 0x19, 0x29, 0x46,// R 65 | 0x00, 0x46, 0x49, 0x49, 0x49, 0x31,// S 66 | 0x00, 0x01, 0x01, 0x7F, 0x01, 0x01,// T 67 | 0x00, 0x3F, 0x40, 0x40, 0x40, 0x3F,// U 68 | 0x00, 0x1F, 0x20, 0x40, 0x20, 0x1F,// V 69 | 0x00, 0x3F, 0x40, 0x38, 0x40, 0x3F,// W 70 | 0x00, 0x63, 0x14, 0x08, 0x14, 0x63,// X 71 | 0x00, 0x07, 0x08, 0x70, 0x08, 0x07,// Y 72 | 0x00, 0x61, 0x51, 0x49, 0x45, 0x43,// Z 73 | 0x00, 0x00, 0x7F, 0x41, 0x41, 0x00,// [ 74 | 0x00, 0x55, 0x2A, 0x55, 0x2A, 0x55,// 55 75 | 0x00, 0x00, 0x41, 0x41, 0x7F, 0x00,// ] 76 | 0x00, 0x04, 0x02, 0x01, 0x02, 0x04,// ^ 77 | 0x00, 0x40, 0x40, 0x40, 0x40, 0x40,// _ 78 | 0x00, 0x00, 0x01, 0x02, 0x04, 0x00,// ' 79 | 0x00, 0x20, 0x54, 0x54, 0x54, 0x78,// a 80 | 0x00, 0x7F, 0x48, 0x44, 0x44, 0x38,// b 81 | 0x00, 0x38, 0x44, 0x44, 0x44, 0x20,// c 82 | 0x00, 0x38, 0x44, 0x44, 0x48, 0x7F,// d 83 | 0x00, 0x38, 0x54, 0x54, 0x54, 0x18,// e 84 | 0x00, 0x08, 0x7E, 0x09, 0x01, 0x02,// f 85 | 0x00, 0x18, 0xA4, 0xA4, 0xA4, 0x7C,// g 86 | 0x00, 0x7F, 0x08, 0x04, 0x04, 0x78,// h 87 | 0x00, 0x00, 0x44, 0x7D, 0x40, 0x00,// i 88 | 0x00, 0x40, 0x80, 0x84, 0x7D, 0x00,// j 89 | 0x00, 0x7F, 0x10, 0x28, 0x44, 0x00,// k 90 | 0x00, 0x00, 0x41, 0x7F, 0x40, 0x00,// l 91 | 0x00, 0x7C, 0x04, 0x18, 0x04, 0x78,// m 92 | 0x00, 0x7C, 0x08, 0x04, 0x04, 0x78,// n 93 | 0x00, 0x38, 0x44, 0x44, 0x44, 0x38,// o 94 | 0x00, 0xFC, 0x24, 0x24, 0x24, 0x18,// p 95 | 0x00, 0x18, 0x24, 0x24, 0x18, 0xFC,// q 96 | 0x00, 0x7C, 0x08, 0x04, 0x04, 0x08,// r 97 | 0x00, 0x48, 0x54, 0x54, 0x54, 0x20,// s 98 | 0x00, 0x04, 0x3F, 0x44, 0x40, 0x20,// t 99 | 0x00, 0x3C, 0x40, 0x40, 0x20, 0x7C,// u 100 | 0x00, 0x1C, 0x20, 0x40, 0x20, 0x1C,// v 101 | 0x00, 0x3C, 0x40, 0x30, 0x40, 0x3C,// w 102 | 0x00, 0x44, 0x28, 0x10, 0x28, 0x44,// x 103 | 0x00, 0x1C, 0xA0, 0xA0, 0xA0, 0x7C,// y 104 | 0x00, 0x44, 0x64, 0x54, 0x4C, 0x44,// z 105 | 0x14, 0x14, 0x14, 0x14, 0x14, 0x14,// horiz lines 106 | }; 107 | 108 | const unsigned char F8X16[]= 109 | { 110 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,// 0 111 | 0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x33,0x30,0x00,0x00,0x00,//! 1 112 | 0x00,0x10,0x0C,0x06,0x10,0x0C,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//" 2 113 | 0x40,0xC0,0x78,0x40,0xC0,0x78,0x40,0x00,0x04,0x3F,0x04,0x04,0x3F,0x04,0x04,0x00,//# 3 114 | 0x00,0x70,0x88,0xFC,0x08,0x30,0x00,0x00,0x00,0x18,0x20,0xFF,0x21,0x1E,0x00,0x00,//$ 4 115 | 0xF0,0x08,0xF0,0x00,0xE0,0x18,0x00,0x00,0x00,0x21,0x1C,0x03,0x1E,0x21,0x1E,0x00,//% 5 116 | 0x00,0xF0,0x08,0x88,0x70,0x00,0x00,0x00,0x1E,0x21,0x23,0x24,0x19,0x27,0x21,0x10,//& 6 117 | 0x10,0x16,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//' 7 118 | 0x00,0x00,0x00,0xE0,0x18,0x04,0x02,0x00,0x00,0x00,0x00,0x07,0x18,0x20,0x40,0x00,//( 8 119 | 0x00,0x02,0x04,0x18,0xE0,0x00,0x00,0x00,0x00,0x40,0x20,0x18,0x07,0x00,0x00,0x00,//) 9 120 | 0x40,0x40,0x80,0xF0,0x80,0x40,0x40,0x00,0x02,0x02,0x01,0x0F,0x01,0x02,0x02,0x00,//* 10 121 | 0x00,0x00,0x00,0xF0,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x1F,0x01,0x01,0x01,0x00,//+ 11 122 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xB0,0x70,0x00,0x00,0x00,0x00,0x00,//, 12 123 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,//- 13 124 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,0x00,0x00,//. 14 125 | 0x00,0x00,0x00,0x00,0x80,0x60,0x18,0x04,0x00,0x60,0x18,0x06,0x01,0x00,0x00,0x00,/// 15 126 | 0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x0F,0x10,0x20,0x20,0x10,0x0F,0x00,//0 16 127 | 0x00,0x10,0x10,0xF8,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//1 17 128 | 0x00,0x70,0x08,0x08,0x08,0x88,0x70,0x00,0x00,0x30,0x28,0x24,0x22,0x21,0x30,0x00,//2 18 129 | 0x00,0x30,0x08,0x88,0x88,0x48,0x30,0x00,0x00,0x18,0x20,0x20,0x20,0x11,0x0E,0x00,//3 19 130 | 0x00,0x00,0xC0,0x20,0x10,0xF8,0x00,0x00,0x00,0x07,0x04,0x24,0x24,0x3F,0x24,0x00,//4 20 131 | 0x00,0xF8,0x08,0x88,0x88,0x08,0x08,0x00,0x00,0x19,0x21,0x20,0x20,0x11,0x0E,0x00,//5 21 132 | 0x00,0xE0,0x10,0x88,0x88,0x18,0x00,0x00,0x00,0x0F,0x11,0x20,0x20,0x11,0x0E,0x00,//6 22 133 | 0x00,0x38,0x08,0x08,0xC8,0x38,0x08,0x00,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x00,//7 23 134 | 0x00,0x70,0x88,0x08,0x08,0x88,0x70,0x00,0x00,0x1C,0x22,0x21,0x21,0x22,0x1C,0x00,//8 24 135 | 0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x00,0x31,0x22,0x22,0x11,0x0F,0x00,//9 25 136 | 0x00,0x00,0x00,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,//: 26 137 | 0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x60,0x00,0x00,0x00,0x00,//; 27 138 | 0x00,0x00,0x80,0x40,0x20,0x10,0x08,0x00,0x00,0x01,0x02,0x04,0x08,0x10,0x20,0x00,//< 28 139 | 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x00,//= 29 140 | 0x00,0x08,0x10,0x20,0x40,0x80,0x00,0x00,0x00,0x20,0x10,0x08,0x04,0x02,0x01,0x00,//> 30 141 | 0x00,0x70,0x48,0x08,0x08,0x08,0xF0,0x00,0x00,0x00,0x00,0x30,0x36,0x01,0x00,0x00,//? 31 142 | 0xC0,0x30,0xC8,0x28,0xE8,0x10,0xE0,0x00,0x07,0x18,0x27,0x24,0x23,0x14,0x0B,0x00,//@ 32 143 | 0x00,0x00,0xC0,0x38,0xE0,0x00,0x00,0x00,0x20,0x3C,0x23,0x02,0x02,0x27,0x38,0x20,//A 33 144 | 0x08,0xF8,0x88,0x88,0x88,0x70,0x00,0x00,0x20,0x3F,0x20,0x20,0x20,0x11,0x0E,0x00,//B 34 145 | 0xC0,0x30,0x08,0x08,0x08,0x08,0x38,0x00,0x07,0x18,0x20,0x20,0x20,0x10,0x08,0x00,//C 35 146 | 0x08,0xF8,0x08,0x08,0x08,0x10,0xE0,0x00,0x20,0x3F,0x20,0x20,0x20,0x10,0x0F,0x00,//D 36 147 | 0x08,0xF8,0x88,0x88,0xE8,0x08,0x10,0x00,0x20,0x3F,0x20,0x20,0x23,0x20,0x18,0x00,//E 37 148 | 0x08,0xF8,0x88,0x88,0xE8,0x08,0x10,0x00,0x20,0x3F,0x20,0x00,0x03,0x00,0x00,0x00,//F 38 149 | 0xC0,0x30,0x08,0x08,0x08,0x38,0x00,0x00,0x07,0x18,0x20,0x20,0x22,0x1E,0x02,0x00,//G 39 150 | 0x08,0xF8,0x08,0x00,0x00,0x08,0xF8,0x08,0x20,0x3F,0x21,0x01,0x01,0x21,0x3F,0x20,//H 40 151 | 0x00,0x08,0x08,0xF8,0x08,0x08,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//I 41 152 | 0x00,0x00,0x08,0x08,0xF8,0x08,0x08,0x00,0xC0,0x80,0x80,0x80,0x7F,0x00,0x00,0x00,//J 42 153 | 0x08,0xF8,0x88,0xC0,0x28,0x18,0x08,0x00,0x20,0x3F,0x20,0x01,0x26,0x38,0x20,0x00,//K 43 154 | 0x08,0xF8,0x08,0x00,0x00,0x00,0x00,0x00,0x20,0x3F,0x20,0x20,0x20,0x20,0x30,0x00,//L 44 155 | 0x08,0xF8,0xF8,0x00,0xF8,0xF8,0x08,0x00,0x20,0x3F,0x00,0x3F,0x00,0x3F,0x20,0x00,//M 45 156 | 0x08,0xF8,0x30,0xC0,0x00,0x08,0xF8,0x08,0x20,0x3F,0x20,0x00,0x07,0x18,0x3F,0x00,//N 46 157 | 0xE0,0x10,0x08,0x08,0x08,0x10,0xE0,0x00,0x0F,0x10,0x20,0x20,0x20,0x10,0x0F,0x00,//O 47 158 | 0x08,0xF8,0x08,0x08,0x08,0x08,0xF0,0x00,0x20,0x3F,0x21,0x01,0x01,0x01,0x00,0x00,//P 48 159 | 0xE0,0x10,0x08,0x08,0x08,0x10,0xE0,0x00,0x0F,0x18,0x24,0x24,0x38,0x50,0x4F,0x00,//Q 49 160 | 0x08,0xF8,0x88,0x88,0x88,0x88,0x70,0x00,0x20,0x3F,0x20,0x00,0x03,0x0C,0x30,0x20,//R 50 161 | 0x00,0x70,0x88,0x08,0x08,0x08,0x38,0x00,0x00,0x38,0x20,0x21,0x21,0x22,0x1C,0x00,//S 51 162 | 0x18,0x08,0x08,0xF8,0x08,0x08,0x18,0x00,0x00,0x00,0x20,0x3F,0x20,0x00,0x00,0x00,//T 52 163 | 0x08,0xF8,0x08,0x00,0x00,0x08,0xF8,0x08,0x00,0x1F,0x20,0x20,0x20,0x20,0x1F,0x00,//U 53 164 | 0x08,0x78,0x88,0x00,0x00,0xC8,0x38,0x08,0x00,0x00,0x07,0x38,0x0E,0x01,0x00,0x00,//V 54 165 | 0xF8,0x08,0x00,0xF8,0x00,0x08,0xF8,0x00,0x03,0x3C,0x07,0x00,0x07,0x3C,0x03,0x00,//W 55 166 | 0x08,0x18,0x68,0x80,0x80,0x68,0x18,0x08,0x20,0x30,0x2C,0x03,0x03,0x2C,0x30,0x20,//X 56 167 | 0x08,0x38,0xC8,0x00,0xC8,0x38,0x08,0x00,0x00,0x00,0x20,0x3F,0x20,0x00,0x00,0x00,//Y 57 168 | 0x10,0x08,0x08,0x08,0xC8,0x38,0x08,0x00,0x20,0x38,0x26,0x21,0x20,0x20,0x18,0x00,//Z 58 169 | 0x00,0x00,0x00,0xFE,0x02,0x02,0x02,0x00,0x00,0x00,0x00,0x7F,0x40,0x40,0x40,0x00,//[ 59 170 | 0x00,0x0C,0x30,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x06,0x38,0xC0,0x00,//\ 60 171 | 0x00,0x02,0x02,0x02,0xFE,0x00,0x00,0x00,0x00,0x40,0x40,0x40,0x7F,0x00,0x00,0x00,//] 61 172 | 0x00,0x00,0x04,0x02,0x02,0x02,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//^ 62 173 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,//_ 63 174 | 0x00,0x02,0x02,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//` 64 175 | 0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x19,0x24,0x22,0x22,0x22,0x3F,0x20,//a 65 176 | 0x08,0xF8,0x00,0x80,0x80,0x00,0x00,0x00,0x00,0x3F,0x11,0x20,0x20,0x11,0x0E,0x00,//b 66 177 | 0x00,0x00,0x00,0x80,0x80,0x80,0x00,0x00,0x00,0x0E,0x11,0x20,0x20,0x20,0x11,0x00,//c 67 178 | 0x00,0x00,0x00,0x80,0x80,0x88,0xF8,0x00,0x00,0x0E,0x11,0x20,0x20,0x10,0x3F,0x20,//d 68 179 | 0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x1F,0x22,0x22,0x22,0x22,0x13,0x00,//e 69 180 | 0x00,0x80,0x80,0xF0,0x88,0x88,0x88,0x18,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//f 70 181 | 0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x6B,0x94,0x94,0x94,0x93,0x60,0x00,//g 71 182 | 0x08,0xF8,0x00,0x80,0x80,0x80,0x00,0x00,0x20,0x3F,0x21,0x00,0x00,0x20,0x3F,0x20,//h 72 183 | 0x00,0x80,0x98,0x98,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//i 73 184 | 0x00,0x00,0x00,0x80,0x98,0x98,0x00,0x00,0x00,0xC0,0x80,0x80,0x80,0x7F,0x00,0x00,//j 74 185 | 0x08,0xF8,0x00,0x00,0x80,0x80,0x80,0x00,0x20,0x3F,0x24,0x02,0x2D,0x30,0x20,0x00,//k 75 186 | 0x00,0x08,0x08,0xF8,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//l 76 187 | 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x20,0x3F,0x20,0x00,0x3F,0x20,0x00,0x3F,//m 77 188 | 0x80,0x80,0x00,0x80,0x80,0x80,0x00,0x00,0x20,0x3F,0x21,0x00,0x00,0x20,0x3F,0x20,//n 78 189 | 0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x1F,0x20,0x20,0x20,0x20,0x1F,0x00,//o 79 190 | 0x80,0x80,0x00,0x80,0x80,0x00,0x00,0x00,0x80,0xFF,0xA1,0x20,0x20,0x11,0x0E,0x00,//p 80 191 | 0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x0E,0x11,0x20,0x20,0xA0,0xFF,0x80,//q 81 192 | 0x80,0x80,0x80,0x00,0x80,0x80,0x80,0x00,0x20,0x20,0x3F,0x21,0x20,0x00,0x01,0x00,//r 82 193 | 0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x33,0x24,0x24,0x24,0x24,0x19,0x00,//s 83 194 | 0x00,0x80,0x80,0xE0,0x80,0x80,0x00,0x00,0x00,0x00,0x00,0x1F,0x20,0x20,0x00,0x00,//t 84 195 | 0x80,0x80,0x00,0x00,0x00,0x80,0x80,0x00,0x00,0x1F,0x20,0x20,0x20,0x10,0x3F,0x20,//u 85 196 | 0x80,0x80,0x80,0x00,0x00,0x80,0x80,0x80,0x00,0x01,0x0E,0x30,0x08,0x06,0x01,0x00,//v 86 197 | 0x80,0x80,0x00,0x80,0x00,0x80,0x80,0x80,0x0F,0x30,0x0C,0x03,0x0C,0x30,0x0F,0x00,//w 87 198 | 0x00,0x80,0x80,0x00,0x80,0x80,0x80,0x00,0x00,0x20,0x31,0x2E,0x0E,0x31,0x20,0x00,//x 88 199 | 0x80,0x80,0x80,0x00,0x00,0x80,0x80,0x80,0x80,0x81,0x8E,0x70,0x18,0x06,0x01,0x00,//y 89 200 | 0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x21,0x30,0x2C,0x22,0x21,0x30,0x00,//z 90 201 | 0x00,0x00,0x00,0x00,0x80,0x7C,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x3F,0x40,0x40,//{ 91 202 | 0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,//| 92 203 | 0x00,0x02,0x02,0x7C,0x80,0x00,0x00,0x00,0x00,0x40,0x40,0x3F,0x00,0x00,0x00,0x00,//} 93 204 | 0x00,0x06,0x01,0x01,0x02,0x02,0x04,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//~ 94 205 | }; 206 | -------------------------------------------------------------------------------- /user/mqtt_msg.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, Stephen Robinson 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 | * 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 2. 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 | * 3. Neither the name of the copyright holder nor the names of its 15 | * contributors may be used to endorse or promote products derived 16 | * from this software without 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 HOLDER 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 | 32 | #include 33 | #include "mqtt_msg.h" 34 | 35 | #define MQTT_MAX_FIXED_HEADER_SIZE 3 36 | 37 | enum mqtt_connect_flag 38 | { 39 | MQTT_CONNECT_FLAG_USERNAME = 1 << 7, 40 | MQTT_CONNECT_FLAG_PASSWORD = 1 << 6, 41 | MQTT_CONNECT_FLAG_WILL_RETAIN = 1 << 5, 42 | MQTT_CONNECT_FLAG_WILL = 1 << 2, 43 | MQTT_CONNECT_FLAG_CLEAN_SESSION = 1 << 1 44 | }; 45 | 46 | struct __attribute((__packed__)) mqtt_connect_variable_header 47 | { 48 | uint8_t lengthMsb; 49 | uint8_t lengthLsb; 50 | uint8_t magic[6]; 51 | uint8_t version; 52 | uint8_t flags; 53 | uint8_t keepaliveMsb; 54 | uint8_t keepaliveLsb; 55 | }; 56 | 57 | static int append_string(mqtt_connection_t* connection, const char* string, int len) 58 | { 59 | if(connection->message.length + len + 2 > connection->buffer_length) 60 | return -1; 61 | 62 | connection->buffer[connection->message.length++] = len >> 8; 63 | connection->buffer[connection->message.length++] = len & 0xff; 64 | memcpy(connection->buffer + connection->message.length, string, len); 65 | connection->message.length += len; 66 | 67 | return len + 2; 68 | } 69 | 70 | static uint16_t append_message_id(mqtt_connection_t* connection, uint16_t message_id) 71 | { 72 | // If message_id is zero then we should assign one, otherwise 73 | // we'll use the one supplied by the caller 74 | while(message_id == 0) 75 | message_id = ++connection->message_id; 76 | 77 | if(connection->message.length + 2 > connection->buffer_length) 78 | return 0; 79 | 80 | connection->buffer[connection->message.length++] = message_id >> 8; 81 | connection->buffer[connection->message.length++] = message_id & 0xff; 82 | 83 | return message_id; 84 | } 85 | 86 | static int init_message(mqtt_connection_t* connection) 87 | { 88 | connection->message.length = MQTT_MAX_FIXED_HEADER_SIZE; 89 | return MQTT_MAX_FIXED_HEADER_SIZE; 90 | } 91 | 92 | static mqtt_message_t* fail_message(mqtt_connection_t* connection) 93 | { 94 | connection->message.data = connection->buffer; 95 | connection->message.length = 0; 96 | return &connection->message; 97 | } 98 | 99 | static mqtt_message_t* fini_message(mqtt_connection_t* connection, int type, int dup, int qos, int retain) 100 | { 101 | int remaining_length = connection->message.length - MQTT_MAX_FIXED_HEADER_SIZE; 102 | 103 | if(remaining_length > 127) 104 | { 105 | connection->buffer[0] = ((type & 0x0f) << 4) | ((dup & 1) << 3) | ((qos & 3) << 1) | (retain & 1); 106 | connection->buffer[1] = 0x80 | (remaining_length % 128); 107 | connection->buffer[2] = remaining_length / 128; 108 | connection->message.length = remaining_length + 3; 109 | connection->message.data = connection->buffer; 110 | } 111 | else 112 | { 113 | connection->buffer[1] = ((type & 0x0f) << 4) | ((dup & 1) << 3) | ((qos & 3) << 1) | (retain & 1); 114 | connection->buffer[2] = remaining_length; 115 | connection->message.length = remaining_length + 2; 116 | connection->message.data = connection->buffer + 1; 117 | } 118 | 119 | return &connection->message; 120 | } 121 | 122 | void mqtt_msg_init(mqtt_connection_t* connection, uint8_t* buffer, uint16_t buffer_length) 123 | { 124 | memset(connection, 0, sizeof(connection)); 125 | connection->buffer = buffer; 126 | connection->buffer_length = buffer_length; 127 | } 128 | 129 | int mqtt_get_total_length(uint8_t* buffer, uint16_t length) 130 | { 131 | int i; 132 | int totlen = 0; 133 | 134 | for(i = 1; i < length; ++i) 135 | { 136 | totlen += (buffer[i] & 0x7f) << (7 * (i - 1)); 137 | if((buffer[i] & 0x80) == 0) 138 | { 139 | ++i; 140 | break; 141 | } 142 | } 143 | totlen += i; 144 | 145 | return totlen; 146 | } 147 | 148 | const char* mqtt_get_publish_topic(uint8_t* buffer, uint16_t* length) 149 | { 150 | int i; 151 | int totlen = 0; 152 | int topiclen; 153 | 154 | for(i = 1; i < *length; ++i) 155 | { 156 | totlen += (buffer[i] & 0x7f) << (7 * (i -1)); 157 | if((buffer[i] & 0x80) == 0) 158 | { 159 | ++i; 160 | break; 161 | } 162 | } 163 | totlen += i; 164 | 165 | if(i + 2 >= *length) 166 | return NULL; 167 | topiclen = buffer[i++] << 8; 168 | topiclen |= buffer[i++]; 169 | 170 | if(i + topiclen >= *length) 171 | return NULL; 172 | 173 | *length = topiclen; 174 | return (const char*)(buffer + i); 175 | } 176 | 177 | const char* mqtt_get_publish_data(uint8_t* buffer, uint16_t* length) 178 | { 179 | int i; 180 | int totlen = 0; 181 | int topiclen; 182 | 183 | for(i = 1; i < *length; ++i) 184 | { 185 | totlen += (buffer[i] & 0x7f) << (7 * (i - 1)); 186 | if((buffer[i] & 0x80) == 0) 187 | { 188 | ++i; 189 | break; 190 | } 191 | } 192 | totlen += i; 193 | 194 | if(i + 2 >= *length) 195 | return NULL; 196 | topiclen = buffer[i++] << 8; 197 | topiclen |= buffer[i++]; 198 | 199 | if(i + topiclen >= *length) 200 | return NULL; 201 | i += topiclen; 202 | 203 | if(mqtt_get_qos(buffer) > 0) 204 | { 205 | if(i + 2 >= *length) 206 | return NULL; 207 | i += 2; 208 | } 209 | 210 | if(totlen < i) 211 | return NULL; 212 | 213 | if(totlen <= *length) 214 | *length = totlen - i; 215 | else 216 | *length = *length - i; 217 | return (const char*)(buffer + i); 218 | } 219 | 220 | uint16_t mqtt_get_id(uint8_t* buffer, uint16_t length) 221 | { 222 | if(length < 1) 223 | return 0; 224 | 225 | switch(mqtt_get_type(buffer)) 226 | { 227 | case MQTT_MSG_TYPE_PUBLISH: 228 | { 229 | int i; 230 | int topiclen; 231 | 232 | for(i = 1; i < length; ++i) 233 | { 234 | if((buffer[i] & 0x80) == 0) 235 | { 236 | ++i; 237 | break; 238 | } 239 | } 240 | 241 | if(i + 2 >= length) 242 | return 0; 243 | topiclen = buffer[i++] << 8; 244 | topiclen |= buffer[i++]; 245 | 246 | if(i + topiclen >= length) 247 | return 0; 248 | i += topiclen; 249 | 250 | if(mqtt_get_qos(buffer) > 0) 251 | { 252 | if(i + 2 >= length) 253 | return 0; 254 | i += 2; 255 | } 256 | 257 | return (buffer[i] << 8) | buffer[i + 1]; 258 | } 259 | case MQTT_MSG_TYPE_PUBACK: 260 | case MQTT_MSG_TYPE_PUBREC: 261 | case MQTT_MSG_TYPE_PUBREL: 262 | case MQTT_MSG_TYPE_PUBCOMP: 263 | case MQTT_MSG_TYPE_SUBACK: 264 | case MQTT_MSG_TYPE_UNSUBACK: 265 | { 266 | // This requires the remaining length to be encoded in 1 byte, 267 | // which it should be. 268 | if(length >= 4 && (buffer[1] & 0x80) == 0) 269 | return (buffer[2] << 8) | buffer[3]; 270 | else 271 | return 0; 272 | } 273 | default: 274 | return 0; 275 | } 276 | } 277 | 278 | mqtt_message_t* mqtt_msg_connect(mqtt_connection_t* connection, mqtt_connect_info_t* info) 279 | { 280 | struct mqtt_connect_variable_header* variable_header; 281 | 282 | init_message(connection); 283 | 284 | if(connection->message.length + sizeof(*variable_header) > connection->buffer_length) 285 | return fail_message(connection); 286 | variable_header = (void*)(connection->buffer + connection->message.length); 287 | connection->message.length += sizeof(*variable_header); 288 | 289 | variable_header->lengthMsb = 0; 290 | variable_header->lengthLsb = 6; 291 | memcpy(variable_header->magic, "MQIsdp", 6); 292 | variable_header->version = 3; 293 | variable_header->flags = 0; 294 | variable_header->keepaliveMsb = info->keepalive >> 8; 295 | variable_header->keepaliveLsb = info->keepalive & 0xff; 296 | 297 | if(info->clean_session) 298 | variable_header->flags |= MQTT_CONNECT_FLAG_CLEAN_SESSION; 299 | 300 | if(info->client_id != NULL && info->client_id[0] != '\0') 301 | { 302 | if(append_string(connection, info->client_id, strlen(info->client_id)) < 0) 303 | return fail_message(connection); 304 | } 305 | else 306 | return fail_message(connection); 307 | 308 | if(info->will_topic != NULL && info->will_topic[0] != '\0') 309 | { 310 | if(append_string(connection, info->will_topic, strlen(info->will_topic)) < 0) 311 | return fail_message(connection); 312 | 313 | if(append_string(connection, info->will_message, strlen(info->will_message)) < 0) 314 | return fail_message(connection); 315 | 316 | variable_header->flags |= MQTT_CONNECT_FLAG_WILL; 317 | if(info->will_retain) 318 | variable_header->flags |= MQTT_CONNECT_FLAG_WILL_RETAIN; 319 | variable_header->flags |= (info->will_qos & 3) << 4; 320 | } 321 | 322 | if(info->username != NULL && info->username[0] != '\0') 323 | { 324 | if(append_string(connection, info->username, strlen(info->username)) < 0) 325 | return fail_message(connection); 326 | 327 | variable_header->flags |= MQTT_CONNECT_FLAG_USERNAME; 328 | } 329 | 330 | if(info->password != NULL && info->password[0] != '\0') 331 | { 332 | if(append_string(connection, info->password, strlen(info->password)) < 0) 333 | return fail_message(connection); 334 | 335 | variable_header->flags |= MQTT_CONNECT_FLAG_PASSWORD; 336 | } 337 | 338 | return fini_message(connection, MQTT_MSG_TYPE_CONNECT, 0, 0, 0); 339 | } 340 | 341 | mqtt_message_t* mqtt_msg_publish(mqtt_connection_t* connection, const char* topic, const char* data, int data_length, int qos, int retain, uint16_t* message_id) 342 | { 343 | init_message(connection); 344 | 345 | if(topic == NULL || topic[0] == '\0') 346 | return fail_message(connection); 347 | 348 | if(append_string(connection, topic, strlen(topic)) < 0) 349 | return fail_message(connection); 350 | 351 | if(qos > 0) 352 | { 353 | if((*message_id = append_message_id(connection, 0)) == 0) 354 | return fail_message(connection); 355 | } 356 | else 357 | *message_id = 0; 358 | 359 | if(connection->message.length + data_length > connection->buffer_length) 360 | return fail_message(connection); 361 | memcpy(connection->buffer + connection->message.length, data, data_length); 362 | connection->message.length += data_length; 363 | 364 | return fini_message(connection, MQTT_MSG_TYPE_PUBLISH, 0, qos, retain); 365 | } 366 | 367 | mqtt_message_t* mqtt_msg_puback(mqtt_connection_t* connection, uint16_t message_id) 368 | { 369 | init_message(connection); 370 | if(append_message_id(connection, message_id) == 0) 371 | return fail_message(connection); 372 | return fini_message(connection, MQTT_MSG_TYPE_PUBACK, 0, 0, 0); 373 | } 374 | 375 | mqtt_message_t* mqtt_msg_pubrec(mqtt_connection_t* connection, uint16_t message_id) 376 | { 377 | init_message(connection); 378 | if(append_message_id(connection, message_id) == 0) 379 | return fail_message(connection); 380 | return fini_message(connection, MQTT_MSG_TYPE_PUBREC, 0, 0, 0); 381 | } 382 | 383 | mqtt_message_t* mqtt_msg_pubrel(mqtt_connection_t* connection, uint16_t message_id) 384 | { 385 | init_message(connection); 386 | if(append_message_id(connection, message_id) == 0) 387 | return fail_message(connection); 388 | return fini_message(connection, MQTT_MSG_TYPE_PUBREL, 0, 1, 0); 389 | } 390 | 391 | mqtt_message_t* mqtt_msg_pubcomp(mqtt_connection_t* connection, uint16_t message_id) 392 | { 393 | init_message(connection); 394 | if(append_message_id(connection, message_id) == 0) 395 | return fail_message(connection); 396 | return fini_message(connection, MQTT_MSG_TYPE_PUBCOMP, 0, 0, 0); 397 | } 398 | 399 | mqtt_message_t* mqtt_msg_subscribe(mqtt_connection_t* connection, const char* topic, int qos, uint16_t* message_id) 400 | { 401 | init_message(connection); 402 | 403 | if(topic == NULL || topic[0] == '\0') 404 | return fail_message(connection); 405 | 406 | if((*message_id = append_message_id(connection, 0)) == 0) 407 | return fail_message(connection); 408 | 409 | if(append_string(connection, topic, strlen(topic)) < 0) 410 | return fail_message(connection); 411 | 412 | if(connection->message.length + 1 > connection->buffer_length) 413 | return fail_message(connection); 414 | connection->buffer[connection->message.length++] = qos; 415 | 416 | return fini_message(connection, MQTT_MSG_TYPE_SUBSCRIBE, 0, 1, 0); 417 | } 418 | 419 | mqtt_message_t* mqtt_msg_unsubscribe(mqtt_connection_t* connection, const char* topic, uint16_t* message_id) 420 | { 421 | init_message(connection); 422 | 423 | if(topic == NULL || topic[0] == '\0') 424 | return fail_message(connection); 425 | 426 | if((*message_id = append_message_id(connection, 0)) == 0) 427 | return fail_message(connection); 428 | 429 | if(append_string(connection, topic, strlen(topic)) < 0) 430 | return fail_message(connection); 431 | 432 | return fini_message(connection, MQTT_MSG_TYPE_SUBSCRIBE, 0, 1, 0); 433 | } 434 | 435 | mqtt_message_t* mqtt_msg_pingreq(mqtt_connection_t* connection) 436 | { 437 | init_message(connection); 438 | return fini_message(connection, MQTT_MSG_TYPE_PINGREQ, 0, 0, 0); 439 | } 440 | 441 | mqtt_message_t* mqtt_msg_pingresp(mqtt_connection_t* connection) 442 | { 443 | init_message(connection); 444 | return fini_message(connection, MQTT_MSG_TYPE_PINGRESP, 0, 0, 0); 445 | } 446 | 447 | mqtt_message_t* mqtt_msg_disconnect(mqtt_connection_t* connection) 448 | { 449 | init_message(connection); 450 | return fini_message(connection, MQTT_MSG_TYPE_DISCONNECT, 0, 0, 0); 451 | } 452 | -------------------------------------------------------------------------------- /mqtt/mqtt/mqtt_msg.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, Stephen Robinson 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 | * 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 2. 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 | * 3. Neither the name of the copyright holder nor the names of its 15 | * contributors may be used to endorse or promote products derived 16 | * from this software without 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 HOLDER 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 | 32 | #include 33 | #include "mqtt_msg.h" 34 | #include "user_config.h" 35 | #define MQTT_MAX_FIXED_HEADER_SIZE 3 36 | 37 | enum mqtt_connect_flag 38 | { 39 | MQTT_CONNECT_FLAG_USERNAME = 1 << 7, 40 | MQTT_CONNECT_FLAG_PASSWORD = 1 << 6, 41 | MQTT_CONNECT_FLAG_WILL_RETAIN = 1 << 5, 42 | MQTT_CONNECT_FLAG_WILL = 1 << 2, 43 | MQTT_CONNECT_FLAG_CLEAN_SESSION = 1 << 1 44 | }; 45 | 46 | struct __attribute((__packed__)) mqtt_connect_variable_header 47 | { 48 | uint8_t lengthMsb; 49 | uint8_t lengthLsb; 50 | #if defined(PROTOCOL_NAMEv31) 51 | uint8_t magic[6]; 52 | #elif defined(PROTOCOL_NAMEv311) 53 | uint8_t magic[4]; 54 | #else 55 | #error "Please define protocol name" 56 | #endif 57 | uint8_t version; 58 | uint8_t flags; 59 | uint8_t keepaliveMsb; 60 | uint8_t keepaliveLsb; 61 | }; 62 | 63 | static int ICACHE_FLASH_ATTR append_string(mqtt_connection_t* connection, const char* string, int len) 64 | { 65 | if(connection->message.length + len + 2 > connection->buffer_length) 66 | return -1; 67 | 68 | connection->buffer[connection->message.length++] = len >> 8; 69 | connection->buffer[connection->message.length++] = len & 0xff; 70 | memcpy(connection->buffer + connection->message.length, string, len); 71 | connection->message.length += len; 72 | 73 | return len + 2; 74 | } 75 | 76 | static uint16_t ICACHE_FLASH_ATTR append_message_id(mqtt_connection_t* connection, uint16_t message_id) 77 | { 78 | // If message_id is zero then we should assign one, otherwise 79 | // we'll use the one supplied by the caller 80 | while(message_id == 0) 81 | message_id = ++connection->message_id; 82 | 83 | if(connection->message.length + 2 > connection->buffer_length) 84 | return 0; 85 | 86 | connection->buffer[connection->message.length++] = message_id >> 8; 87 | connection->buffer[connection->message.length++] = message_id & 0xff; 88 | 89 | return message_id; 90 | } 91 | 92 | static int ICACHE_FLASH_ATTR init_message(mqtt_connection_t* connection) 93 | { 94 | connection->message.length = MQTT_MAX_FIXED_HEADER_SIZE; 95 | return MQTT_MAX_FIXED_HEADER_SIZE; 96 | } 97 | 98 | static mqtt_message_t* ICACHE_FLASH_ATTR fail_message(mqtt_connection_t* connection) 99 | { 100 | connection->message.data = connection->buffer; 101 | connection->message.length = 0; 102 | return &connection->message; 103 | } 104 | 105 | static mqtt_message_t* ICACHE_FLASH_ATTR fini_message(mqtt_connection_t* connection, int type, int dup, int qos, int retain) 106 | { 107 | int remaining_length = connection->message.length - MQTT_MAX_FIXED_HEADER_SIZE; 108 | 109 | if(remaining_length > 127) 110 | { 111 | connection->buffer[0] = ((type & 0x0f) << 4) | ((dup & 1) << 3) | ((qos & 3) << 1) | (retain & 1); 112 | connection->buffer[1] = 0x80 | (remaining_length % 128); 113 | connection->buffer[2] = remaining_length / 128; 114 | connection->message.length = remaining_length + 3; 115 | connection->message.data = connection->buffer; 116 | } 117 | else 118 | { 119 | connection->buffer[1] = ((type & 0x0f) << 4) | ((dup & 1) << 3) | ((qos & 3) << 1) | (retain & 1); 120 | connection->buffer[2] = remaining_length; 121 | connection->message.length = remaining_length + 2; 122 | connection->message.data = connection->buffer + 1; 123 | } 124 | 125 | return &connection->message; 126 | } 127 | 128 | void ICACHE_FLASH_ATTR mqtt_msg_init(mqtt_connection_t* connection, uint8_t* buffer, uint16_t buffer_length) 129 | { 130 | memset(connection, 0, sizeof(connection)); 131 | connection->buffer = buffer; 132 | connection->buffer_length = buffer_length; 133 | } 134 | 135 | int ICACHE_FLASH_ATTR mqtt_get_total_length(uint8_t* buffer, uint16_t length) 136 | { 137 | int i; 138 | int totlen = 0; 139 | 140 | for(i = 1; i < length; ++i) 141 | { 142 | totlen += (buffer[i] & 0x7f) << (7 * (i - 1)); 143 | if((buffer[i] & 0x80) == 0) 144 | { 145 | ++i; 146 | break; 147 | } 148 | } 149 | totlen += i; 150 | 151 | return totlen; 152 | } 153 | 154 | const char* ICACHE_FLASH_ATTR mqtt_get_publish_topic(uint8_t* buffer, uint16_t* length) 155 | { 156 | int i; 157 | int totlen = 0; 158 | int topiclen; 159 | 160 | for(i = 1; i < *length; ++i) 161 | { 162 | totlen += (buffer[i] & 0x7f) << (7 * (i -1)); 163 | if((buffer[i] & 0x80) == 0) 164 | { 165 | ++i; 166 | break; 167 | } 168 | } 169 | totlen += i; 170 | 171 | if(i + 2 >= *length) 172 | return NULL; 173 | topiclen = buffer[i++] << 8; 174 | topiclen |= buffer[i++]; 175 | 176 | if(i + topiclen > *length) 177 | return NULL; 178 | 179 | *length = topiclen; 180 | return (const char*)(buffer + i); 181 | } 182 | 183 | const char* ICACHE_FLASH_ATTR mqtt_get_publish_data(uint8_t* buffer, uint16_t* length) 184 | { 185 | int i; 186 | int totlen = 0; 187 | int topiclen; 188 | 189 | for(i = 1; i < *length; ++i) 190 | { 191 | totlen += (buffer[i] & 0x7f) << (7 * (i - 1)); 192 | if((buffer[i] & 0x80) == 0) 193 | { 194 | ++i; 195 | break; 196 | } 197 | } 198 | totlen += i; 199 | 200 | if(i + 2 >= *length) 201 | return NULL; 202 | topiclen = buffer[i++] << 8; 203 | topiclen |= buffer[i++]; 204 | 205 | if(i + topiclen >= *length){ 206 | *length = 0; 207 | return NULL; 208 | } 209 | i += topiclen; 210 | 211 | if(mqtt_get_qos(buffer) > 0) 212 | { 213 | if(i + 2 >= *length) 214 | return NULL; 215 | i += 2; 216 | } 217 | 218 | if(totlen < i) 219 | return NULL; 220 | 221 | if(totlen <= *length) 222 | *length = totlen - i; 223 | else 224 | *length = *length - i; 225 | return (const char*)(buffer + i); 226 | } 227 | 228 | uint16_t ICACHE_FLASH_ATTR mqtt_get_id(uint8_t* buffer, uint16_t length) 229 | { 230 | if(length < 1) 231 | return 0; 232 | 233 | switch(mqtt_get_type(buffer)) 234 | { 235 | case MQTT_MSG_TYPE_PUBLISH: 236 | { 237 | int i; 238 | int topiclen; 239 | 240 | for(i = 1; i < length; ++i) 241 | { 242 | if((buffer[i] & 0x80) == 0) 243 | { 244 | ++i; 245 | break; 246 | } 247 | } 248 | 249 | if(i + 2 >= length) 250 | return 0; 251 | topiclen = buffer[i++] << 8; 252 | topiclen |= buffer[i++]; 253 | 254 | if(i + topiclen >= length) 255 | return 0; 256 | i += topiclen; 257 | 258 | if(mqtt_get_qos(buffer) > 0) 259 | { 260 | if(i + 2 >= length) 261 | return 0; 262 | //i += 2; 263 | } else { 264 | return 0; 265 | } 266 | 267 | return (buffer[i] << 8) | buffer[i + 1]; 268 | } 269 | case MQTT_MSG_TYPE_PUBACK: 270 | case MQTT_MSG_TYPE_PUBREC: 271 | case MQTT_MSG_TYPE_PUBREL: 272 | case MQTT_MSG_TYPE_PUBCOMP: 273 | case MQTT_MSG_TYPE_SUBACK: 274 | case MQTT_MSG_TYPE_UNSUBACK: 275 | case MQTT_MSG_TYPE_SUBSCRIBE: 276 | { 277 | // This requires the remaining length to be encoded in 1 byte, 278 | // which it should be. 279 | if(length >= 4 && (buffer[1] & 0x80) == 0) 280 | return (buffer[2] << 8) | buffer[3]; 281 | else 282 | return 0; 283 | } 284 | 285 | default: 286 | return 0; 287 | } 288 | } 289 | 290 | mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_connect(mqtt_connection_t* connection, mqtt_connect_info_t* info) 291 | { 292 | struct mqtt_connect_variable_header* variable_header; 293 | 294 | init_message(connection); 295 | 296 | if(connection->message.length + sizeof(*variable_header) > connection->buffer_length) 297 | return fail_message(connection); 298 | variable_header = (void*)(connection->buffer + connection->message.length); 299 | connection->message.length += sizeof(*variable_header); 300 | 301 | variable_header->lengthMsb = 0; 302 | #if defined(PROTOCOL_NAMEv31) 303 | variable_header->lengthLsb = 6; 304 | memcpy(variable_header->magic, "MQIsdp", 6); 305 | variable_header->version = 3; 306 | #elif defined(PROTOCOL_NAMEv311) 307 | variable_header->lengthLsb = 4; 308 | memcpy(variable_header->magic, "MQTT", 4); 309 | variable_header->version = 4; 310 | #else 311 | #error "Please define protocol name" 312 | #endif 313 | 314 | variable_header->flags = 0; 315 | variable_header->keepaliveMsb = info->keepalive >> 8; 316 | variable_header->keepaliveLsb = info->keepalive & 0xff; 317 | 318 | if(info->clean_session) 319 | variable_header->flags |= MQTT_CONNECT_FLAG_CLEAN_SESSION; 320 | 321 | if(info->client_id != NULL && info->client_id[0] != '\0') 322 | { 323 | if(append_string(connection, info->client_id, strlen(info->client_id)) < 0) 324 | return fail_message(connection); 325 | } 326 | else 327 | return fail_message(connection); 328 | 329 | if(info->will_topic != NULL && info->will_topic[0] != '\0') 330 | { 331 | if(append_string(connection, info->will_topic, strlen(info->will_topic)) < 0) 332 | return fail_message(connection); 333 | 334 | if(append_string(connection, info->will_message, strlen(info->will_message)) < 0) 335 | return fail_message(connection); 336 | 337 | variable_header->flags |= MQTT_CONNECT_FLAG_WILL; 338 | if(info->will_retain) 339 | variable_header->flags |= MQTT_CONNECT_FLAG_WILL_RETAIN; 340 | variable_header->flags |= (info->will_qos & 3) << 3; 341 | } 342 | 343 | if(info->username != NULL && info->username[0] != '\0') 344 | { 345 | if(append_string(connection, info->username, strlen(info->username)) < 0) 346 | return fail_message(connection); 347 | 348 | variable_header->flags |= MQTT_CONNECT_FLAG_USERNAME; 349 | } 350 | 351 | if(info->password != NULL && info->password[0] != '\0') 352 | { 353 | if(append_string(connection, info->password, strlen(info->password)) < 0) 354 | return fail_message(connection); 355 | 356 | variable_header->flags |= MQTT_CONNECT_FLAG_PASSWORD; 357 | } 358 | 359 | return fini_message(connection, MQTT_MSG_TYPE_CONNECT, 0, 0, 0); 360 | } 361 | 362 | 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) 363 | { 364 | init_message(connection); 365 | 366 | if(topic == NULL || topic[0] == '\0') 367 | return fail_message(connection); 368 | 369 | if(append_string(connection, topic, strlen(topic)) < 0) 370 | return fail_message(connection); 371 | 372 | if(qos > 0) 373 | { 374 | if((*message_id = append_message_id(connection, 0)) == 0) 375 | return fail_message(connection); 376 | } 377 | else 378 | *message_id = 0; 379 | 380 | if(connection->message.length + data_length > connection->buffer_length) 381 | return fail_message(connection); 382 | memcpy(connection->buffer + connection->message.length, data, data_length); 383 | connection->message.length += data_length; 384 | 385 | return fini_message(connection, MQTT_MSG_TYPE_PUBLISH, 0, qos, retain); 386 | } 387 | 388 | mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_puback(mqtt_connection_t* connection, uint16_t message_id) 389 | { 390 | init_message(connection); 391 | if(append_message_id(connection, message_id) == 0) 392 | return fail_message(connection); 393 | return fini_message(connection, MQTT_MSG_TYPE_PUBACK, 0, 0, 0); 394 | } 395 | 396 | mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_pubrec(mqtt_connection_t* connection, uint16_t message_id) 397 | { 398 | init_message(connection); 399 | if(append_message_id(connection, message_id) == 0) 400 | return fail_message(connection); 401 | return fini_message(connection, MQTT_MSG_TYPE_PUBREC, 0, 0, 0); 402 | } 403 | 404 | mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_pubrel(mqtt_connection_t* connection, uint16_t message_id) 405 | { 406 | init_message(connection); 407 | if(append_message_id(connection, message_id) == 0) 408 | return fail_message(connection); 409 | return fini_message(connection, MQTT_MSG_TYPE_PUBREL, 0, 1, 0); 410 | } 411 | 412 | mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_pubcomp(mqtt_connection_t* connection, uint16_t message_id) 413 | { 414 | init_message(connection); 415 | if(append_message_id(connection, message_id) == 0) 416 | return fail_message(connection); 417 | return fini_message(connection, MQTT_MSG_TYPE_PUBCOMP, 0, 0, 0); 418 | } 419 | 420 | mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_subscribe(mqtt_connection_t* connection, const char* topic, int qos, uint16_t* message_id) 421 | { 422 | init_message(connection); 423 | 424 | if(topic == NULL || topic[0] == '\0') 425 | return fail_message(connection); 426 | 427 | if((*message_id = append_message_id(connection, 0)) == 0) 428 | return fail_message(connection); 429 | 430 | if(append_string(connection, topic, strlen(topic)) < 0) 431 | return fail_message(connection); 432 | 433 | if(connection->message.length + 1 > connection->buffer_length) 434 | return fail_message(connection); 435 | connection->buffer[connection->message.length++] = qos; 436 | 437 | return fini_message(connection, MQTT_MSG_TYPE_SUBSCRIBE, 0, 1, 0); 438 | } 439 | 440 | mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_unsubscribe(mqtt_connection_t* connection, const char* topic, uint16_t* message_id) 441 | { 442 | init_message(connection); 443 | 444 | if(topic == NULL || topic[0] == '\0') 445 | return fail_message(connection); 446 | 447 | if((*message_id = append_message_id(connection, 0)) == 0) 448 | return fail_message(connection); 449 | 450 | if(append_string(connection, topic, strlen(topic)) < 0) 451 | return fail_message(connection); 452 | 453 | return fini_message(connection, MQTT_MSG_TYPE_SUBSCRIBE, 0, 1, 0); 454 | } 455 | 456 | mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_pingreq(mqtt_connection_t* connection) 457 | { 458 | init_message(connection); 459 | return fini_message(connection, MQTT_MSG_TYPE_PINGREQ, 0, 0, 0); 460 | } 461 | 462 | mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_pingresp(mqtt_connection_t* connection) 463 | { 464 | init_message(connection); 465 | return fini_message(connection, MQTT_MSG_TYPE_PINGRESP, 0, 0, 0); 466 | } 467 | 468 | mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_disconnect(mqtt_connection_t* connection) 469 | { 470 | init_message(connection); 471 | return fini_message(connection, MQTT_MSG_TYPE_DISCONNECT, 0, 0, 0); 472 | } 473 | --------------------------------------------------------------------------------