├── .gitignore ├── LICENSE ├── README.md ├── aliyun_mqtt_app ├── Makefile ├── gen_misc.bat ├── gen_misc.sh ├── include │ ├── aliyun_mqtt.h │ ├── driver │ │ ├── uart.h │ │ └── uart_register.h │ ├── md5.h │ ├── mqtt │ │ ├── debug.h │ │ ├── mqtt.h │ │ ├── mqtt_msg.h │ │ ├── proto.h │ │ ├── queue.h │ │ ├── ringbuf.h │ │ ├── typedef.h │ │ └── utils.h │ ├── mqtt_config.h │ ├── user_config.h │ └── user_wifi.h ├── mqtt │ ├── Makefile │ ├── include │ │ ├── debug.h │ │ ├── mqtt.h │ │ ├── mqtt_msg.h │ │ ├── proto.h │ │ ├── queue.h │ │ ├── ringbuf.h │ │ ├── typedef.h │ │ └── utils.h │ ├── mqtt.c │ ├── mqtt_msg.c │ ├── proto.c │ ├── queue.c │ ├── ringbuf.c │ └── utils.c └── user │ ├── Makefile │ ├── aliyun_mqtt.c │ ├── md5.c │ ├── user_main.c │ └── user_wifi.c └── screenshot ├── build_success.png ├── mqtt_connect_success.png ├── project_list.png └── topic_get_helloworld.png /.gitignore: -------------------------------------------------------------------------------- 1 | !.gitignore 2 | 3 | .vscode 4 | 5 | .output 6 | .bin 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 AngelLiang 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # esp8266_aliyun_mqtt_app 2 | 3 | 基于ESP8266官方SDK接入[阿里云物联网平台](https://www.aliyun.com/product/iot),只需填入阿里云设备认证三元组即可快速接入。 4 | 5 | 相关博客:[使用ESP8266(基于官方SDK)接入阿里云物联网平台](https://blog.csdn.net/yannanxiu/article/details/81334230) 6 | 7 | 8 | ## 本人所用的环境 9 | 10 | - Windows 10 11 | - [安信可 ESP 系列一体化开发环境](http://wiki.ai-thinker.com/ai_ide_install)(基于 Windows + Cygwin + Eclipse + GCC 的综合 IDE 环境) 12 | - ESP8266_NONOS_SDK-3.0.0 13 | - NodeMCU(ESP8266 4MB flash) 14 | 15 | 16 | ## 使用步骤 17 | 18 | 1. 首先到乐鑫[官网](https://www.espressif.com/zh-hans/products/hardware/esp8266ex/resources)或[github](https://github.com/espressif/ESP8266_NONOS_SDK)下载ESP8266_NONOS_SDK; 19 | 2. 下载本仓库,然后拷贝`aliyun_mqtt_app`文件夹到SDK主目录,用法类似于`ESP8266_NONOS_SDK/examples`里面的工程; 20 | 3. 在ESP8266 IDE里导入整个SDK,如果不熟悉该环境,参考[这里](http://wiki.ai-thinker.com/ai_ide_use); 21 | 4. 使用SDKv3.0.0还需要修改该SDK的顶层Makefile。编辑器打开该SDK的顶层Makefile,找到下面配置变量,修改`SPI_SIZE_MAP`为4(如果是使用32Mbit Flash)。 22 | 23 | ```Makefile 24 | # ... 25 | # 25行 26 | BOOT?=none 27 | APP?=0 28 | SPI_SPEED?=40 29 | SPI_MODE?=QIO 30 | SPI_SIZE_MAP?=4 31 | ``` 32 | 33 | 如果不修改,后面编译会报下面错误: 34 | 35 | ``` 36 | #error "The flash map is not supported" 37 | ``` 38 | 39 | 5. 最后编译下载即可(建议先clean)。 40 | 41 | ![project_list](screenshot/project_list.png) 42 | 43 | 44 | > 如果想试试用smartconfig配置Wi-Fi信息,可下载smartconfig分支。 45 | 46 | ## 配置信息 47 | 48 | 当在阿里云物联网平台获取到设备认证三元组后,编辑`app/include/user_config.h`文件,修改下面信息,然后编译下载并重启ESP8266,最后应该就能在控制台看到设备上线了。 49 | 50 | > 注意,阿里云三元组的宏定义,从上到下分别是:产品key,设备name,设备secret。不要拷贝错了。 51 | 52 | ```C 53 | #define PRODUCT_KEY "PRODUCT_KEY" 54 | 55 | #define DEVICE_NAME "DEVICE_NAME" 56 | #define DEVICE_SECRET "DEVICE_SECRET" 57 | 58 | #define WIFI_SSID "WIFI_SSID" 59 | #define WIFI_PASS "WIFI_PASS" 60 | 61 | ``` 62 | 63 | 当ESP8266IDE的Console打印出以下信息,则表示编译成功: 64 | 65 | ``` 66 | ... 67 | !!! 68 | No boot needed. 69 | Generate eagle.flash.bin and eagle.irom0text.bin successully in folder bin. 70 | eagle.flash.bin-------->0x00000 71 | eagle.irom0text.bin---->0x10000 72 | !!! 73 | ``` 74 | 75 | ![编译成功](screenshot/build_success.png) 76 | 77 | ## 烧写bin 78 | 79 | 这一步对新手来说可能坑比较多。可参考安信可的[烧写步骤](http://wiki.ai-thinker.com/esp_download#%E7%83%A7%E5%BD%95%E4%B8%8B%E8%BD%BD),也可参考我[ESP8266-Demos](https://github.com/AngelLiang/ESP8266-Demos)仓库里[wiki](https://github.com/AngelLiang/ESP8266-Demos/wiki)的烧写说明(目前待完善)。 80 | 81 | 对老手来说,平时怎么烧写就怎么烧写。 82 | 83 | ## 主要模块说明 84 | 85 | - `mqtt/`:mqtt主模块,从官方SDK中的`example/esp_mqtt_proj`项目移植过来的; 86 | - `user/md5.c`:md5加密模块,生成阿里云mqtt password需要用到**hmacmd5**; 87 | - `user/aliyun_mqtt.c`:生成阿里云mqtt信息的核心模块,主要包括`mqtt host`、`mqtt port`、`mqtt client id`、`mqtt username`以及动态生成的`mqtt password`; 88 | - `user/user_smartconfig.c`:smartconfig模块(smartconfig分支才有),当定义了`SMARTCONFIG_ENABLE`可以以手机配网的方式给ESP8266连接Wi-Fi。 89 | 90 | 91 | ## 注意事项 92 | 93 | - 关于串口波特率 94 | 95 | ESP8266串口打印默认为74880bps,如果串口工具没有74880bps也可以选择76800bps。 96 | 97 | 或者修改下`user/user_main.c/user_init()`的代码: 98 | 99 | ```C 100 | // ... 101 | void user_init(void) { 102 | //uart_init(BIT_RATE_74880, BIT_RATE_74880); 103 | uart_init(BIT_RATE_115200, BIT_RATE_115200); 104 | //... 105 | } 106 | ``` 107 | 108 | - 关于源码文件中的中文乱码 109 | 110 | 因为源码文件编码默认为UTF-8,而Windows Eclipse IDE默认为GBK,所以可能需要设置一下: 111 | 112 | 菜单栏Window -> Preferences -> General -> Workspace -> 面板Text file encoding -> 选择UTF-8 -> OK 113 | 114 | 115 | ## 串口打印效果图 116 | 117 | MQTT连接阿里云成功: 118 | 119 | ![MQTT连接成功](screenshot/mqtt_connect_success.png) 120 | 121 | 接收云端下发的命令`hello world`: 122 | 123 | ![接收云端下发的命令](screenshot/topic_get_helloworld.png) 124 | 125 | ## 排错 126 | 127 | 首先要调试好ESP8266串口能正常打印出信息。一般来说,使用74880bps不会有乱码,使用115200bps,开头一小段会有乱码。 128 | 129 | ### wifi连接失败 130 | 131 | 如果wifi连接失败,会重复打印下面信息: 132 | 133 | 下面是表示找不到`WIFI_SSID`的wifi热点。 134 | 135 | ``` 136 | no WIFI_SSID found, reconnect after 1s 137 | reconnect 138 | wifi connect fail! 139 | wifi connect fail! 140 | wifi connect fail! 141 | wifi connect fail! 142 | wifi connect fail! 143 | wifi connect fail! 144 | scandone 145 | no WIFI_SSID found, reconnect after 1s 146 | reconnect 147 | wifi connect fail! 148 | wifi connect fail! 149 | wifi connect fail! 150 | wifi connect fail! 151 | wifi connect fail! 152 | scandone 153 | no WIFI_SSID found, reconnect after 1s 154 | wifi connect fail! 155 | reconnect 156 | wifi connect fail! 157 | wifi connect fail! 158 | wifi connect fail! 159 | ``` 160 | 161 | wifi密码错误及其他原因则不断打印「`wifi connect fail!`」信息,因为本人没有在代码层面上做更多的判断。 162 | 163 | ### MQTT连接阿里云失败 164 | 165 | 打印信息: 166 | 167 | ``` 168 | connected with TP-LINK, channel 13 169 | dhcp client start... 170 | wifi connect fail! 171 | ip:192.168.0.113,mask:255.255.255.0,gw:192.168.0.1 172 | TCP: Connect to domain PRODUCT_KEY.iot-as-mqtt.cn-shanghai.aliyuncs.com:1883 173 | DNS: found ip ****** 174 | TCP: connecting... 175 | MQTT: Connected to broker PRODUCT_KEY.iot-as-mqtt.cn-shanghai.aliyuncs.com:1883 176 | MQTT: Sending, type: 1, id: 0000 177 | TCP: Sent 178 | TCP: data received 4 bytes 179 | MQTT: Connected to PRODUCT_KEY.iot-as-mqtt.cn-shanghai.aliyuncs.com:1883 180 | MQTT: Connected 181 | MQTT: queue subscribe, topic"/PRODUCT_KEY/DEVICE_NAME/get", id: 1 182 | MQTT: queuing publish, length: 41, queue size(37/2048) 183 | TCP: Disconnected callback 184 | MQTT: Disconnected 185 | ``` 186 | 187 | 可以看到末尾有TCP/MQTT断开了连接的信息: 188 | 189 | ``` 190 | ... 191 | TCP: Disconnected callback 192 | MQTT: Disconnected 193 | ``` 194 | 195 | ## 其他补充 196 | 197 | - 如果想要学习使用ESP8266官方的mqtt sample app(esp_mqtt_proj),可以参考我这篇[博客](https://blog.csdn.net/yannanxiu/article/details/53088534) 198 | - 安信可IDE开发环境资料: 199 | - 如何安装安信可一体化开发环境:http://wiki.ai-thinker.com/ai_ide_install 200 | - 如何使用安信可 ESP 系列一体化开发环境:http://wiki.ai-thinker.com/ai_ide_use 201 | - 如何为 ESP 系列模组烧录固件:http://wiki.ai-thinker.com/esp_download 202 | -------------------------------------------------------------------------------- /aliyun_mqtt_app/Makefile: -------------------------------------------------------------------------------- 1 | ############################################################# 2 | # Required variables for each makefile 3 | # Discard this section from all parent makefiles 4 | # Expected variables (with automatic defaults): 5 | # CSRCS (all "C" files in the dir) 6 | # SUBDIRS (all subdirs with a Makefile) 7 | # GEN_LIBS - list of libs to be generated () 8 | # GEN_IMAGES - list of object file images to be generated () 9 | # GEN_BINS - list of binaries 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 | TARGET = eagle 15 | #FLAVOR = release 16 | FLAVOR = debug 17 | 18 | #EXTRA_CCFLAGS += -u 19 | 20 | ifndef PDIR # { 21 | GEN_IMAGES= eagle.app.v6.out 22 | GEN_BINS= eagle.app.v6.bin 23 | SPECIAL_MKTARGETS=$(APP_MKTARGETS) 24 | SUBDIRS= \ 25 | user \ 26 | mqtt 27 | 28 | endif # } PDIR 29 | 30 | APPDIR = . 31 | LDDIR = ../ld 32 | 33 | CCFLAGS += -Os 34 | 35 | TARGET_LDFLAGS = \ 36 | -nostdlib \ 37 | -Wl,-EL \ 38 | --longcalls \ 39 | --text-section-literals 40 | 41 | ifeq ($(FLAVOR),debug) 42 | TARGET_LDFLAGS += -g -O2 43 | endif 44 | 45 | ifeq ($(FLAVOR),release) 46 | TARGET_LDFLAGS += -g -O0 47 | endif 48 | 49 | COMPONENTS_eagle.app.v6 = \ 50 | user/libuser.a \ 51 | mqtt/libmqtt.a 52 | 53 | LINKFLAGS_eagle.app.v6 = \ 54 | -L../lib \ 55 | -nostdlib \ 56 | -T$(LD_FILE) \ 57 | -Wl,--no-check-sections \ 58 | -Wl,--gc-sections \ 59 | -u call_user_start \ 60 | -Wl,-static \ 61 | -Wl,--start-group \ 62 | -lc \ 63 | -lgcc \ 64 | -lhal \ 65 | -lphy \ 66 | -lpp \ 67 | -lnet80211 \ 68 | -llwip \ 69 | -lwpa \ 70 | -lcrypto \ 71 | -lmain \ 72 | -ljson \ 73 | -lupgrade\ 74 | -lssl \ 75 | -lpwm \ 76 | -ldriver \ 77 | -lsmartconfig \ 78 | -lairkiss\ 79 | $(DEP_LIBS_eagle.app.v6) \ 80 | -Wl,--end-group 81 | 82 | DEPENDS_eagle.app.v6 = \ 83 | $(LD_FILE) \ 84 | $(LDDIR)/eagle.rom.addr.v6.ld 85 | 86 | ############################################################# 87 | # Configuration i.e. compile options etc. 88 | # Target specific stuff (defines etc.) goes in here! 89 | # Generally values applying to a tree are captured in the 90 | # makefile at its root level - these are then overridden 91 | # for a subtree within the makefile rooted therein 92 | # 93 | 94 | #UNIVERSAL_TARGET_DEFINES = \ 95 | 96 | # Other potential configuration flags include: 97 | # -DTXRX_TXBUF_DEBUG 98 | # -DTXRX_RXBUF_DEBUG 99 | # -DWLAN_CONFIG_CCX 100 | CONFIGURATION_DEFINES = -DICACHE_FLASH 101 | 102 | DEFINES += \ 103 | $(UNIVERSAL_TARGET_DEFINES) \ 104 | $(CONFIGURATION_DEFINES) 105 | 106 | DDEFINES += \ 107 | $(UNIVERSAL_TARGET_DEFINES) \ 108 | $(CONFIGURATION_DEFINES) 109 | 110 | 111 | ############################################################# 112 | # Recursion Magic - Don't touch this!! 113 | # 114 | # Each subtree potentially has an include directory 115 | # corresponding to the common APIs applicable to modules 116 | # rooted at that subtree. Accordingly, the INCLUDE PATH 117 | # of a module can only contain the include directories up 118 | # its parent path, and not its siblings 119 | # 120 | # Required for each makefile to inherit from the parent 121 | # 122 | 123 | INCLUDES := $(INCLUDES) -I $(PDIR)include -I $(PDIR)include/mqtt 124 | PDIR := ../$(PDIR) 125 | sinclude $(PDIR)Makefile 126 | 127 | .PHONY: FORCE 128 | FORCE: 129 | 130 | -------------------------------------------------------------------------------- /aliyun_mqtt_app/gen_misc.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | echo gen_misc.bat version 20150511 4 | echo . 5 | 6 | echo Please follow below steps(1-5) to generate specific bin(s): 7 | echo STEP 1: choose boot version(0=boot_v1.1, 1=boot_v1.2+, 2=none) 8 | set input=default 9 | set /p input=enter(0/1/2, default 2): 10 | 11 | if %input% equ 0 ( 12 | set boot=old 13 | ) else ( 14 | if %input% equ 1 ( 15 | set boot=new 16 | ) else ( 17 | set boot=none 18 | ) 19 | ) 20 | 21 | echo boot mode: %boot% 22 | echo. 23 | 24 | echo STEP 2: choose bin generate(0=eagle.flash.bin+eagle.irom0text.bin, 1=user1.bin, 2=user2.bin) 25 | set input=default 26 | set /p input=enter (0/1/2, default 0): 27 | 28 | if %input% equ 1 ( 29 | if %boot% equ none ( 30 | set app=0 31 | echo choose no boot before 32 | echo generate bin: eagle.flash.bin+eagle.irom0text.bin 33 | ) else ( 34 | set app=1 35 | echo generate bin: user1.bin 36 | ) 37 | ) else ( 38 | if %input% equ 2 ( 39 | if %boot% equ none ( 40 | set app=0 41 | echo choose no boot before 42 | echo generate bin: eagle.flash.bin+eagle.irom0text.bin 43 | ) else ( 44 | set app=2 45 | echo generate bin: user2.bin 46 | ) 47 | ) else ( 48 | if %boot% neq none ( 49 | set boot=none 50 | echo ignore boot 51 | ) 52 | set app=0 53 | echo generate bin: eagle.flash.bin+eagle.irom0text.bin 54 | )) 55 | 56 | echo. 57 | 58 | echo STEP 3: choose spi speed(0=20MHz, 1=26.7MHz, 2=40MHz, 3=80MHz) 59 | set input=default 60 | set /p input=enter (0/1/2/3, default 2): 61 | 62 | if %input% equ 0 ( 63 | set spi_speed=20 64 | ) else ( 65 | if %input% equ 1 ( 66 | set spi_speed=26.7 67 | ) else ( 68 | if %input% equ 3 ( 69 | set spi_speed=80 70 | ) else ( 71 | set spi_speed=40 72 | ))) 73 | 74 | echo spi speed: %spi_speed% MHz 75 | echo. 76 | 77 | echo STEP 4: choose spi mode(0=QIO, 1=QOUT, 2=DIO, 3=DOUT) 78 | set input=default 79 | set /p input=enter (0/1/2/3, default 0): 80 | 81 | if %input% equ 1 ( 82 | set spi_mode=QOUT 83 | ) else ( 84 | if %input% equ 2 ( 85 | set spi_mode=DIO 86 | ) else ( 87 | if %input% equ 3 ( 88 | set spi_mode=DOUT 89 | ) else ( 90 | set spi_mode=QIO 91 | ))) 92 | 93 | echo spi mode: %spi_mode% 94 | echo. 95 | 96 | echo STEP 5: choose flash size and map 97 | echo 0= 512KB( 256KB+ 256KB) 98 | echo 2=1024KB( 512KB+ 512KB) 99 | echo 3=2048KB( 512KB+ 512KB) 100 | echo 4=4096KB( 512KB+ 512KB) 101 | echo 5=2048KB(1024KB+1024KB) 102 | echo 6=4096KB(1024KB+1024KB) 103 | set input=default 104 | set /p input=enter (0/1/2/3/4/5/6, default 0): 105 | 106 | if %input% equ 2 ( 107 | set spi_size_map=2 108 | echo spi size: 1024KB 109 | echo spi ota map: 512KB + 512KB 110 | ) else ( 111 | if %input% equ 3 ( 112 | set spi_size_map=3 113 | echo spi size: 2048KB 114 | echo spi ota map: 512KB + 512KB 115 | ) else ( 116 | if %input% equ 4 ( 117 | set spi_size_map=4 118 | echo spi size: 4096KB 119 | echo spi ota map: 512KB + 512KB 120 | ) else ( 121 | if %input% equ 5 ( 122 | set spi_size_map=5 123 | echo spi size: 2048KB 124 | echo spi ota map: 1024KB + 1024KB 125 | ) else ( 126 | if %input% equ 6 ( 127 | set spi_size_map=6 128 | echo spi size: 4096KB 129 | echo spi ota map: 1024KB + 1024KB 130 | ) else ( 131 | set spi_size_map=0 132 | echo spi size: 512KB 133 | echo spi ota map: 256KB + 256KB 134 | ) 135 | ) 136 | ) 137 | ) 138 | ) 139 | 140 | touch user/user_main.c 141 | 142 | echo. 143 | echo start... 144 | echo. 145 | 146 | make BOOT=%boot% APP=%app% SPI_SPEED=%spi_speed% SPI_MODE=%spi_mode% SPI_SIZE=%spi_size_map% 147 | 148 | -------------------------------------------------------------------------------- /aliyun_mqtt_app/gen_misc.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo "gen_misc.sh version 20150511" 4 | echo "" 5 | 6 | echo "Please follow below steps(1-5) to generate specific bin(s):" 7 | echo "STEP 1: choose boot version(0=boot_v1.1, 1=boot_v1.2+, 2=none)" 8 | echo "enter(0/1/2, default 2):" 9 | read input 10 | 11 | if [ -z "$input" ]; then 12 | boot=none 13 | elif [ $input == 0 ]; then 14 | boot=old 15 | elif [ $input == 1 ]; then 16 | boot=new 17 | else 18 | boot=none 19 | fi 20 | 21 | echo "boot mode: $boot" 22 | echo "" 23 | 24 | echo "STEP 2: choose bin generate(0=eagle.flash.bin+eagle.irom0text.bin, 1=user1.bin, 2=user2.bin)" 25 | echo "enter (0/1/2, default 0):" 26 | read input 27 | 28 | if [ -z "$input" ]; then 29 | if [ $boot != none ]; then 30 | boot=none 31 | echo "ignore boot" 32 | fi 33 | app=0 34 | echo "generate bin: eagle.flash.bin+eagle.irom0text.bin" 35 | elif [ $input == 1 ]; then 36 | if [ $boot == none ]; then 37 | app=0 38 | echo "choose no boot before" 39 | echo "generate bin: eagle.flash.bin+eagle.irom0text.bin" 40 | else 41 | app=1 42 | echo "generate bin: user1.bin" 43 | fi 44 | elif [ $input == 2 ]; then 45 | if [ $boot == none ]; then 46 | app=0 47 | echo "choose no boot before" 48 | echo "generate bin: eagle.flash.bin+eagle.irom0text.bin" 49 | else 50 | app=2 51 | echo "generate bin: user2.bin" 52 | fi 53 | else 54 | if [ $boot != none ]; then 55 | boot=none 56 | echo "ignore boot" 57 | fi 58 | app=0 59 | echo "generate bin: eagle.flash.bin+eagle.irom0text.bin" 60 | fi 61 | 62 | echo "" 63 | 64 | echo "STEP 3: choose spi speed(0=20MHz, 1=26.7MHz, 2=40MHz, 3=80MHz)" 65 | echo "enter (0/1/2/3, default 2):" 66 | read input 67 | 68 | if [ -z "$input" ]; then 69 | spi_speed=40 70 | elif [ $input == 0 ]; then 71 | spi_speed=20 72 | elif [ $input == 1 ]; then 73 | spi_speed=26.7 74 | elif [ $input == 3 ]; then 75 | spi_speed=80 76 | else 77 | spi_speed=40 78 | fi 79 | 80 | echo "spi speed: $spi_speed MHz" 81 | echo "" 82 | 83 | echo "STEP 4: choose spi mode(0=QIO, 1=QOUT, 2=DIO, 3=DOUT)" 84 | echo "enter (0/1/2/3, default 0):" 85 | read input 86 | 87 | if [ -z "$input" ]; then 88 | spi_mode=QIO 89 | elif [ $input == 1 ]; then 90 | spi_mode=QOUT 91 | elif [ $input == 2 ]; then 92 | spi_mode=DIO 93 | elif [ $input == 3 ]; then 94 | spi_mode=DOUT 95 | else 96 | spi_mode=QIO 97 | fi 98 | 99 | echo "spi mode: $spi_mode" 100 | echo "" 101 | 102 | echo "STEP 5: choose spi size and map" 103 | echo " 0= 512KB( 256KB+ 256KB)" 104 | echo " 2=1024KB( 512KB+ 512KB)" 105 | echo " 3=2048KB( 512KB+ 512KB)" 106 | echo " 4=4096KB( 512KB+ 512KB)" 107 | echo " 5=2048KB(1024KB+1024KB)" 108 | echo " 6=4096KB(1024KB+1024KB)" 109 | echo "enter (0/2/3/4/5/6, default 0):" 110 | read input 111 | 112 | if [ -z "$input" ]; then 113 | spi_size_map=0 114 | echo "spi size: 512KB" 115 | echo "spi ota map: 256KB + 256KB" 116 | elif [ $input == 2 ]; then 117 | spi_size_map=2 118 | echo "spi size: 1024KB" 119 | echo "spi ota map: 512KB + 512KB" 120 | elif [ $input == 3 ]; then 121 | spi_size_map=3 122 | echo "spi size: 2048KB" 123 | echo "spi ota map: 512KB + 512KB" 124 | elif [ $input == 4 ]; then 125 | spi_size_map=4 126 | echo "spi size: 4096KB" 127 | echo "spi ota map: 512KB + 512KB" 128 | elif [ $input == 5 ]; then 129 | spi_size_map=5 130 | echo "spi size: 2048KB" 131 | echo "spi ota map: 1024KB + 1024KB" 132 | elif [ $input == 6 ]; then 133 | spi_size_map=6 134 | echo "spi size: 4096KB" 135 | echo "spi ota map: 1024KB + 1024KB" 136 | else 137 | spi_size_map=0 138 | echo "spi size: 512KB" 139 | echo "spi ota map: 256KB + 256KB" 140 | fi 141 | 142 | echo "" 143 | 144 | touch user/user_main.c 145 | 146 | echo "" 147 | echo "start..." 148 | echo "" 149 | make clean 150 | make COMPILE=gcc BOOT=$boot APP=$app SPI_SPEED=$spi_speed SPI_MODE=$spi_mode SPI_SIZE_MAP=$spi_size_map 151 | -------------------------------------------------------------------------------- /aliyun_mqtt_app/include/aliyun_mqtt.h: -------------------------------------------------------------------------------- 1 | /* 2 | * aliyun_mqtt.h 3 | */ 4 | 5 | #ifndef _ALIYUN_MQTT_H_ 6 | #define _ALIYUN_MQTT_H_ 7 | 8 | /******************************************************************************/ 9 | /* 从阿里云平台获取的三元组 */ 10 | 11 | #if 0 12 | #define PRODUCT_KEY "PRODUCT_KEY" 13 | #define DEVICE_NAME "DEVICE_NAME" 14 | #define DEVICE_SECRET "DEVICE_SECRET" 15 | #else // 从 user_config.h 导入 16 | #include "user_config.h" 17 | #endif 18 | 19 | // 用户自定义的device id 20 | #define DEVICE_ID PRODUCT_KEY"."DEVICE_NAME 21 | 22 | // 是否使用随机生成的timestamp 23 | //#define RAMDOM_TIMESTAMP 24 | 25 | /******************************************************************************/ 26 | // 以下不需要变动 27 | #define DOMAIN "iot-as-mqtt.cn-shanghai.aliyuncs.com" 28 | 29 | #define MQTT_HOST PRODUCT_KEY"."DOMAIN 30 | #define MQTT_PORT 1883 31 | #define MQTT_CLIENT_ID DEVICE_ID"|securemode=3,signmethod=hmacmd5,timestamp=%s|" 32 | #define MQTT_USERNAME DEVICE_NAME"&"PRODUCT_KEY 33 | 34 | #define BUF_SIZE 128 35 | 36 | // mqtt struct 37 | typedef struct { 38 | u8 host[BUF_SIZE]; 39 | u16 port; 40 | u8 client_id[BUF_SIZE]; 41 | u8 username[BUF_SIZE]; 42 | u8 password[BUF_SIZE]; 43 | u16 keepalive; 44 | } s_mqtt; 45 | 46 | #define TIMESTAMP_STR "789" 47 | 48 | /******************************************************************************/ 49 | /* interface */ 50 | extern void aliyun_mqtt_init(void); 51 | extern void test_hmac_md5(void); 52 | 53 | extern s_mqtt g_aliyun_mqtt; 54 | 55 | #endif /* _ALIYUN_MQTT_H_ */ 56 | -------------------------------------------------------------------------------- /aliyun_mqtt_app/include/driver/uart.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ESPRSSIF MIT License 3 | * 4 | * Copyright (c) 2016 5 | * 6 | * Permission is hereby granted for use on ESPRESSIF SYSTEMS ESP8266 only, in which case, 7 | * it is free of charge, to any person obtaining a copy of this software and associated 8 | * documentation files (the "Software"), to deal in the Software without restriction, including 9 | * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 | * and/or sell copies of the Software, and to permit persons to whom the Software is furnished 11 | * to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all copies or 14 | * substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 18 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 19 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | * 23 | */ 24 | 25 | #ifndef UART_APP_H 26 | #define UART_APP_H 27 | 28 | #include "uart_register.h" 29 | #include "eagle_soc.h" 30 | #include "c_types.h" 31 | 32 | #define RX_BUFF_SIZE 256 33 | #define TX_BUFF_SIZE 100 34 | #define UART0 0 35 | #define UART1 1 36 | 37 | typedef enum { 38 | FIVE_BITS = 0x0, 39 | SIX_BITS = 0x1, 40 | SEVEN_BITS = 0x2, 41 | EIGHT_BITS = 0x3 42 | } UartBitsNum4Char; 43 | 44 | typedef enum { 45 | ONE_STOP_BIT = 0, 46 | ONE_HALF_STOP_BIT = BIT2, 47 | TWO_STOP_BIT = BIT2 48 | } UartStopBitsNum; 49 | 50 | typedef enum { 51 | NONE_BITS = 0, 52 | ODD_BITS = 0, 53 | EVEN_BITS = BIT4 54 | } UartParityMode; 55 | 56 | typedef enum { 57 | STICK_PARITY_DIS = 0, 58 | STICK_PARITY_EN = BIT3 | BIT5 59 | } UartExistParity; 60 | 61 | typedef enum { 62 | BIT_RATE_9600 = 9600, 63 | BIT_RATE_19200 = 19200, 64 | BIT_RATE_38400 = 38400, 65 | BIT_RATE_57600 = 57600, 66 | BIT_RATE_74880 = 74880, 67 | BIT_RATE_115200 = 115200, 68 | BIT_RATE_230400 = 230400, 69 | BIT_RATE_256000 = 256000, 70 | BIT_RATE_460800 = 460800, 71 | BIT_RATE_921600 = 921600 72 | } UartBautRate; 73 | 74 | typedef enum { 75 | NONE_CTRL, 76 | HARDWARE_CTRL, 77 | XON_XOFF_CTRL 78 | } UartFlowCtrl; 79 | 80 | typedef enum { 81 | EMPTY, 82 | UNDER_WRITE, 83 | WRITE_OVER 84 | } RcvMsgBuffState; 85 | 86 | typedef struct { 87 | uint32 RcvBuffSize; 88 | uint8 *pRcvMsgBuff; 89 | uint8 *pWritePos; 90 | uint8 *pReadPos; 91 | uint8 TrigLvl; //JLU: may need to pad 92 | RcvMsgBuffState BuffState; 93 | } RcvMsgBuff; 94 | 95 | typedef struct { 96 | uint32 TrxBuffSize; 97 | uint8 *pTrxBuff; 98 | } TrxMsgBuff; 99 | 100 | typedef enum { 101 | BAUD_RATE_DET, 102 | WAIT_SYNC_FRM, 103 | SRCH_MSG_HEAD, 104 | RCV_MSG_BODY, 105 | RCV_ESC_CHAR, 106 | } RcvMsgState; 107 | 108 | typedef struct { 109 | UartBautRate baut_rate; 110 | UartBitsNum4Char data_bits; 111 | UartExistParity exist_parity; 112 | UartParityMode parity; // chip size in byte 113 | UartStopBitsNum stop_bits; 114 | UartFlowCtrl flow_ctrl; 115 | RcvMsgBuff rcv_buff; 116 | TrxMsgBuff trx_buff; 117 | RcvMsgState rcv_state; 118 | int received; 119 | int buff_uart_no; //indicate which uart use tx/rx buffer 120 | } UartDevice; 121 | 122 | void uart_init(UartBautRate uart0_br, UartBautRate uart1_br); 123 | void uart0_sendStr(const char *str); 124 | #endif 125 | 126 | -------------------------------------------------------------------------------- /aliyun_mqtt_app/include/driver/uart_register.h: -------------------------------------------------------------------------------- 1 | //Generated at 2012-07-03 18:44:06 2 | /* 3 | * ESPRSSIF MIT License 4 | * 5 | * Copyright (c) 2016 6 | * 7 | * Permission is hereby granted for use on ESPRESSIF SYSTEMS ESP8266 only, in which case, 8 | * it is free of charge, to any person obtaining a copy of this software and associated 9 | * documentation files (the "Software"), to deal in the Software without restriction, including 10 | * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 | * and/or sell copies of the Software, and to permit persons to whom the Software is furnished 12 | * to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all copies or 15 | * substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | * 24 | */ 25 | 26 | #ifndef UART_REGISTER_H_INCLUDED 27 | #define UART_REGISTER_H_INCLUDED 28 | #define REG_UART_BASE( i ) (0x60000000+(i)*0xf00) 29 | //version value:32'h062000 30 | 31 | #define UART_FIFO( i ) (REG_UART_BASE( i ) + 0x0) 32 | #define UART_RXFIFO_RD_BYTE 0x000000FF 33 | #define UART_RXFIFO_RD_BYTE_S 0 34 | 35 | #define UART_INT_RAW( i ) (REG_UART_BASE( i ) + 0x4) 36 | #define UART_RXFIFO_TOUT_INT_RAW (BIT(8)) 37 | #define UART_BRK_DET_INT_RAW (BIT(7)) 38 | #define UART_CTS_CHG_INT_RAW (BIT(6)) 39 | #define UART_DSR_CHG_INT_RAW (BIT(5)) 40 | #define UART_RXFIFO_OVF_INT_RAW (BIT(4)) 41 | #define UART_FRM_ERR_INT_RAW (BIT(3)) 42 | #define UART_PARITY_ERR_INT_RAW (BIT(2)) 43 | #define UART_TXFIFO_EMPTY_INT_RAW (BIT(1)) 44 | #define UART_RXFIFO_FULL_INT_RAW (BIT(0)) 45 | 46 | #define UART_INT_ST( i ) (REG_UART_BASE( i ) + 0x8) 47 | #define UART_RXFIFO_TOUT_INT_ST (BIT(8)) 48 | #define UART_BRK_DET_INT_ST (BIT(7)) 49 | #define UART_CTS_CHG_INT_ST (BIT(6)) 50 | #define UART_DSR_CHG_INT_ST (BIT(5)) 51 | #define UART_RXFIFO_OVF_INT_ST (BIT(4)) 52 | #define UART_FRM_ERR_INT_ST (BIT(3)) 53 | #define UART_PARITY_ERR_INT_ST (BIT(2)) 54 | #define UART_TXFIFO_EMPTY_INT_ST (BIT(1)) 55 | #define UART_RXFIFO_FULL_INT_ST (BIT(0)) 56 | 57 | #define UART_INT_ENA( i ) (REG_UART_BASE( i ) + 0xC) 58 | #define UART_RXFIFO_TOUT_INT_ENA (BIT(8)) 59 | #define UART_BRK_DET_INT_ENA (BIT(7)) 60 | #define UART_CTS_CHG_INT_ENA (BIT(6)) 61 | #define UART_DSR_CHG_INT_ENA (BIT(5)) 62 | #define UART_RXFIFO_OVF_INT_ENA (BIT(4)) 63 | #define UART_FRM_ERR_INT_ENA (BIT(3)) 64 | #define UART_PARITY_ERR_INT_ENA (BIT(2)) 65 | #define UART_TXFIFO_EMPTY_INT_ENA (BIT(1)) 66 | #define UART_RXFIFO_FULL_INT_ENA (BIT(0)) 67 | 68 | #define UART_INT_CLR( i ) (REG_UART_BASE( i ) + 0x10) 69 | #define UART_RXFIFO_TOUT_INT_CLR (BIT(8)) 70 | #define UART_BRK_DET_INT_CLR (BIT(7)) 71 | #define UART_CTS_CHG_INT_CLR (BIT(6)) 72 | #define UART_DSR_CHG_INT_CLR (BIT(5)) 73 | #define UART_RXFIFO_OVF_INT_CLR (BIT(4)) 74 | #define UART_FRM_ERR_INT_CLR (BIT(3)) 75 | #define UART_PARITY_ERR_INT_CLR (BIT(2)) 76 | #define UART_TXFIFO_EMPTY_INT_CLR (BIT(1)) 77 | #define UART_RXFIFO_FULL_INT_CLR (BIT(0)) 78 | 79 | #define UART_CLKDIV( i ) (REG_UART_BASE( i ) + 0x14) 80 | #define UART_CLKDIV_CNT 0x000FFFFF 81 | #define UART_CLKDIV_S 0 82 | 83 | #define UART_AUTOBAUD( i ) (REG_UART_BASE( i ) + 0x18) 84 | #define UART_GLITCH_FILT 0x000000FF 85 | #define UART_GLITCH_FILT_S 8 86 | #define UART_AUTOBAUD_EN (BIT(0)) 87 | 88 | #define UART_STATUS( i ) (REG_UART_BASE( i ) + 0x1C) 89 | #define UART_TXD (BIT(31)) 90 | #define UART_RTSN (BIT(30)) 91 | #define UART_DTRN (BIT(29)) 92 | #define UART_TXFIFO_CNT 0x000000FF 93 | #define UART_TXFIFO_CNT_S 16 94 | #define UART_RXD (BIT(15)) 95 | #define UART_CTSN (BIT(14)) 96 | #define UART_DSRN (BIT(13)) 97 | #define UART_RXFIFO_CNT 0x000000FF 98 | #define UART_RXFIFO_CNT_S 0 99 | 100 | #define UART_CONF0( i ) (REG_UART_BASE( i ) + 0x20) 101 | #define UART_TXFIFO_RST (BIT(18)) 102 | #define UART_RXFIFO_RST (BIT(17)) 103 | #define UART_IRDA_EN (BIT(16)) 104 | #define UART_TX_FLOW_EN (BIT(15)) 105 | #define UART_LOOPBACK (BIT(14)) 106 | #define UART_IRDA_RX_INV (BIT(13)) 107 | #define UART_IRDA_TX_INV (BIT(12)) 108 | #define UART_IRDA_WCTL (BIT(11)) 109 | #define UART_IRDA_TX_EN (BIT(10)) 110 | #define UART_IRDA_DPLX (BIT(9)) 111 | #define UART_TXD_BRK (BIT(8)) 112 | #define UART_SW_DTR (BIT(7)) 113 | #define UART_SW_RTS (BIT(6)) 114 | #define UART_STOP_BIT_NUM 0x00000003 115 | #define UART_STOP_BIT_NUM_S 4 116 | #define UART_BIT_NUM 0x00000003 117 | #define UART_BIT_NUM_S 2 118 | #define UART_PARITY_EN (BIT(1)) 119 | #define UART_PARITY (BIT(0)) 120 | 121 | #define UART_CONF1( i ) (REG_UART_BASE( i ) + 0x24) 122 | #define UART_RX_TOUT_EN (BIT(31)) 123 | #define UART_RX_TOUT_THRHD 0x0000007F 124 | #define UART_RX_TOUT_THRHD_S 24 125 | #define UART_RX_FLOW_EN (BIT(23)) 126 | #define UART_RX_FLOW_THRHD 0x0000007F 127 | #define UART_RX_FLOW_THRHD_S 16 128 | #define UART_TXFIFO_EMPTY_THRHD 0x0000007F 129 | #define UART_TXFIFO_EMPTY_THRHD_S 8 130 | #define UART_RXFIFO_FULL_THRHD 0x0000007F 131 | #define UART_RXFIFO_FULL_THRHD_S 0 132 | 133 | #define UART_LOWPULSE( i ) (REG_UART_BASE( i ) + 0x28) 134 | #define UART_LOWPULSE_MIN_CNT 0x000FFFFF 135 | #define UART_LOWPULSE_MIN_CNT_S 0 136 | 137 | #define UART_HIGHPULSE( i ) (REG_UART_BASE( i ) + 0x2C) 138 | #define UART_HIGHPULSE_MIN_CNT 0x000FFFFF 139 | #define UART_HIGHPULSE_MIN_CNT_S 0 140 | 141 | #define UART_PULSE_NUM( i ) (REG_UART_BASE( i ) + 0x30) 142 | #define UART_PULSE_NUM_CNT 0x0003FF 143 | #define UART_PULSE_NUM_CNT_S 0 144 | 145 | #define UART_DATE( i ) (REG_UART_BASE( i ) + 0x78) 146 | #define UART_ID( i ) (REG_UART_BASE( i ) + 0x7C) 147 | #endif // UART_REGISTER_H_INCLUDED 148 | -------------------------------------------------------------------------------- /aliyun_mqtt_app/include/md5.h: -------------------------------------------------------------------------------- 1 | #ifndef _MD5_H_ 2 | #define _MD5_H_ 3 | 4 | #include "ets_sys.h" 5 | 6 | typedef struct { 7 | unsigned int count[2]; 8 | unsigned int state[4]; 9 | unsigned char buffer[64]; 10 | } MD5_CTX; 11 | 12 | #define F(x,y,z) ((x & y) | (~x & z)) 13 | #define G(x,y,z) ((x & z) | (y & ~z)) 14 | #define H(x,y,z) (x^y^z) 15 | #define I(x,y,z) (y ^ (x | ~z)) 16 | #define ROTATE_LEFT(x,n) ((x << n) | (x >> (32-n))) 17 | 18 | #define FF(a,b,c,d,x,s,ac) do{ \ 19 | a += F(b, c, d) + x + ac; \ 20 | a = ROTATE_LEFT(a, s); \ 21 | a += b; \ 22 | } while(0) 23 | 24 | #define GG(a,b,c,d,x,s,ac) do { \ 25 | a += G(b, c, d) + x + ac; \ 26 | a = ROTATE_LEFT(a, s); \ 27 | a += b; \ 28 | } while(0) 29 | 30 | #define HH(a,b,c,d,x,s,ac) do { \ 31 | a += H(b, c, d) + x + ac; \ 32 | a = ROTATE_LEFT(a, s); \ 33 | a += b; \ 34 | }while(0) 35 | 36 | #define II(a,b,c,d,x,s,ac) do{ \ 37 | a += I(b, c, d) + x + ac; \ 38 | a = ROTATE_LEFT(a, s); \ 39 | a += b; \ 40 | }while(0) 41 | 42 | void MD5Init(MD5_CTX *context); 43 | void MD5Update(MD5_CTX *context, unsigned char *input, unsigned int inputlen); 44 | void MD5Final(MD5_CTX *context, unsigned char digest[16]); 45 | void MD5Transform(unsigned int state[4], unsigned char block[64]); 46 | void MD5Encode(unsigned char *output, unsigned int *input, unsigned int len); 47 | void MD5Decode(unsigned int *output, unsigned char *input, unsigned int len); 48 | 49 | extern void MD5Digest(void const *strContent, u16 iLength, u8 output[16]); 50 | extern void HMAC_MD5(u8 *inBuffer, u16 len, u8 *ky, u8 output[16]); 51 | 52 | #endif /* _MD5_H_ */ 53 | -------------------------------------------------------------------------------- /aliyun_mqtt_app/include/mqtt/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 | // 如果不需要mqtt打印信息,则注释下面这条define 12 | #define MQTT_DEBUG_ON 13 | 14 | #if defined(MQTT_DEBUG_ON) 15 | #define INFO( format, ... ) os_printf( format, ## __VA_ARGS__ ) 16 | #else 17 | #define INFO( format, ... ) 18 | #endif 19 | 20 | // #ifndef INFO 21 | // #define INFO os_printf 22 | // #endif 23 | 24 | #endif /* USER_DEBUG_H_ */ 25 | -------------------------------------------------------------------------------- /aliyun_mqtt_app/include/mqtt/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_config.h" 33 | #include "mqtt_msg.h" 34 | #include "user_interface.h" 35 | 36 | #include "queue.h" 37 | typedef struct mqtt_event_data_t 38 | { 39 | uint8_t type; 40 | const char* topic; 41 | const char* data; 42 | uint16_t topic_length; 43 | uint16_t data_length; 44 | uint16_t data_offset; 45 | } mqtt_event_data_t; 46 | 47 | typedef struct mqtt_state_t 48 | { 49 | uint16_t port; 50 | int auto_reconnect; 51 | mqtt_connect_info_t* connect_info; 52 | uint8_t* in_buffer; 53 | uint8_t* out_buffer; 54 | int in_buffer_length; 55 | int out_buffer_length; 56 | uint16_t message_length; 57 | uint16_t message_length_read; 58 | mqtt_message_t* outbound_message; 59 | mqtt_connection_t mqtt_connection; 60 | uint16_t pending_msg_id; 61 | int pending_msg_type; 62 | int pending_publish_qos; 63 | } mqtt_state_t; 64 | 65 | typedef enum { 66 | WIFI_INIT, 67 | WIFI_CONNECTING, 68 | WIFI_CONNECTING_ERROR, 69 | WIFI_CONNECTED, 70 | DNS_RESOLVE, 71 | TCP_DISCONNECTING, 72 | TCP_DISCONNECTED, 73 | TCP_RECONNECT_DISCONNECTING, 74 | TCP_RECONNECT_REQ, 75 | TCP_RECONNECT, 76 | TCP_CONNECTING, 77 | TCP_CONNECTING_ERROR, 78 | TCP_CONNECTED, 79 | MQTT_CONNECT_SEND, 80 | MQTT_CONNECT_SENDING, 81 | MQTT_SUBSCIBE_SEND, 82 | MQTT_SUBSCIBE_SENDING, 83 | MQTT_DATA, 84 | MQTT_KEEPALIVE_SEND, 85 | MQTT_PUBLISH_RECV, 86 | MQTT_PUBLISHING, 87 | MQTT_DELETING, 88 | MQTT_DELETED, 89 | } tConnState; 90 | 91 | typedef void (*MqttCallback)(uint32_t *args); 92 | typedef void (*MqttDataCallback)(uint32_t *args, const char* topic, uint32_t topic_len, const char *data, uint32_t lengh); 93 | 94 | typedef struct { 95 | struct espconn *pCon; 96 | uint8_t security; 97 | uint8_t* host; 98 | uint32_t port; 99 | ip_addr_t ip; 100 | mqtt_state_t mqtt_state; 101 | mqtt_connect_info_t connect_info; 102 | MqttCallback connectedCb; 103 | MqttCallback disconnectedCb; 104 | MqttCallback publishedCb; 105 | MqttCallback timeoutCb; 106 | MqttDataCallback dataCb; 107 | ETSTimer mqttTimer; 108 | uint32_t keepAliveTick; 109 | uint32_t reconnectTick; 110 | uint32_t sendTimeout; 111 | tConnState connState; 112 | QUEUE msgQueue; 113 | void* user_data; 114 | } MQTT_Client; 115 | 116 | #define SEC_NONSSL 0 117 | #define SEC_SSL 1 118 | 119 | #define MQTT_FLAG_CONNECTED 1 120 | #define MQTT_FLAG_READY 2 121 | #define MQTT_FLAG_EXIT 4 122 | 123 | #define MQTT_EVENT_TYPE_NONE 0 124 | #define MQTT_EVENT_TYPE_CONNECTED 1 125 | #define MQTT_EVENT_TYPE_DISCONNECTED 2 126 | #define MQTT_EVENT_TYPE_SUBSCRIBED 3 127 | #define MQTT_EVENT_TYPE_UNSUBSCRIBED 4 128 | #define MQTT_EVENT_TYPE_PUBLISH 5 129 | #define MQTT_EVENT_TYPE_PUBLISHED 6 130 | #define MQTT_EVENT_TYPE_EXITED 7 131 | #define MQTT_EVENT_TYPE_PUBLISH_CONTINUATION 8 132 | 133 | void ICACHE_FLASH_ATTR MQTT_InitConnection(MQTT_Client *mqttClient, uint8_t* host, uint32_t port, uint8_t security); 134 | 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); 135 | void ICACHE_FLASH_ATTR MQTT_DeleteClient(MQTT_Client *mqttClient); 136 | 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); 137 | void ICACHE_FLASH_ATTR MQTT_OnConnected(MQTT_Client *mqttClient, MqttCallback connectedCb); 138 | void ICACHE_FLASH_ATTR MQTT_OnDisconnected(MQTT_Client *mqttClient, MqttCallback disconnectedCb); 139 | void ICACHE_FLASH_ATTR MQTT_OnPublished(MQTT_Client *mqttClient, MqttCallback publishedCb); 140 | void ICACHE_FLASH_ATTR MQTT_OnTimeout(MQTT_Client *mqttClient, MqttCallback timeoutCb); 141 | void ICACHE_FLASH_ATTR MQTT_OnData(MQTT_Client *mqttClient, MqttDataCallback dataCb); 142 | BOOL ICACHE_FLASH_ATTR MQTT_Subscribe(MQTT_Client *client, char* topic, uint8_t qos); 143 | BOOL ICACHE_FLASH_ATTR MQTT_UnSubscribe(MQTT_Client *client, char* topic); 144 | void ICACHE_FLASH_ATTR MQTT_Connect(MQTT_Client *mqttClient); 145 | void ICACHE_FLASH_ATTR MQTT_Disconnect(MQTT_Client *mqttClient); 146 | BOOL ICACHE_FLASH_ATTR MQTT_Publish(MQTT_Client *client, const char* topic, const char* data, int data_length, int qos, int retain); 147 | 148 | #endif /* USER_AT_MQTT_H_ */ 149 | -------------------------------------------------------------------------------- /aliyun_mqtt_app/include/mqtt/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 "mqtt_config.h" 11 | #include "c_types.h" 12 | #ifdef __cplusplus 13 | extern "C" { 14 | #endif 15 | 16 | /* 17 | * Copyright (c) 2014, Stephen Robinson 18 | * All rights reserved. 19 | * 20 | * Redistribution and use in source and binary forms, with or without 21 | * modification, are permitted provided that the following conditions 22 | * are met: 23 | * 24 | * 1. Redistributions of source code must retain the above copyright 25 | * notice, this list of conditions and the following disclaimer. 26 | * 2. Redistributions in binary form must reproduce the above copyright 27 | * notice, this list of conditions and the following disclaimer in the 28 | * documentation and/or other materials provided with the distribution. 29 | * 3. Neither the name of the copyright holder nor the names of its 30 | * contributors may be used to endorse or promote products derived 31 | * from this software without specific prior written permission. 32 | * 33 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 34 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 35 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 36 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 37 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 38 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 39 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 40 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 41 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 42 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 43 | * POSSIBILITY OF SUCH DAMAGE. 44 | * 45 | */ 46 | /* 7 6 5 4 3 2 1 0*/ 47 | /*| --- Message Type---- | DUP Flag | QoS Level | Retain | 48 | /* Remaining Length */ 49 | 50 | 51 | enum mqtt_message_type 52 | { 53 | MQTT_MSG_TYPE_CONNECT = 1, 54 | MQTT_MSG_TYPE_CONNACK = 2, 55 | MQTT_MSG_TYPE_PUBLISH = 3, 56 | MQTT_MSG_TYPE_PUBACK = 4, 57 | MQTT_MSG_TYPE_PUBREC = 5, 58 | MQTT_MSG_TYPE_PUBREL = 6, 59 | MQTT_MSG_TYPE_PUBCOMP = 7, 60 | MQTT_MSG_TYPE_SUBSCRIBE = 8, 61 | MQTT_MSG_TYPE_SUBACK = 9, 62 | MQTT_MSG_TYPE_UNSUBSCRIBE = 10, 63 | MQTT_MSG_TYPE_UNSUBACK = 11, 64 | MQTT_MSG_TYPE_PINGREQ = 12, 65 | MQTT_MSG_TYPE_PINGRESP = 13, 66 | MQTT_MSG_TYPE_DISCONNECT = 14 67 | }; 68 | 69 | typedef struct mqtt_message 70 | { 71 | uint8_t* data; 72 | uint16_t length; 73 | 74 | } mqtt_message_t; 75 | 76 | typedef struct mqtt_connection 77 | { 78 | mqtt_message_t message; 79 | 80 | uint16_t message_id; 81 | uint8_t* buffer; 82 | uint16_t buffer_length; 83 | 84 | } mqtt_connection_t; 85 | 86 | typedef struct mqtt_connect_info 87 | { 88 | char* client_id; 89 | char* username; 90 | char* password; 91 | char* will_topic; 92 | char* will_message; 93 | int keepalive; 94 | int will_qos; 95 | int will_retain; 96 | int clean_session; 97 | 98 | } mqtt_connect_info_t; 99 | 100 | 101 | static inline int ICACHE_FLASH_ATTR mqtt_get_type(uint8_t* buffer) { return (buffer[0] & 0xf0) >> 4; } 102 | static inline int ICACHE_FLASH_ATTR mqtt_get_dup(uint8_t* buffer) { return (buffer[0] & 0x08) >> 3; } 103 | static inline int ICACHE_FLASH_ATTR mqtt_get_qos(uint8_t* buffer) { return (buffer[0] & 0x06) >> 1; } 104 | static inline int ICACHE_FLASH_ATTR mqtt_get_retain(uint8_t* buffer) { return (buffer[0] & 0x01); } 105 | 106 | void ICACHE_FLASH_ATTR mqtt_msg_init(mqtt_connection_t* connection, uint8_t* buffer, uint16_t buffer_length); 107 | int ICACHE_FLASH_ATTR mqtt_get_total_length(uint8_t* buffer, uint16_t length); 108 | const char* ICACHE_FLASH_ATTR mqtt_get_publish_topic(uint8_t* buffer, uint16_t* length); 109 | const char* ICACHE_FLASH_ATTR mqtt_get_publish_data(uint8_t* buffer, uint16_t* length); 110 | uint16_t ICACHE_FLASH_ATTR mqtt_get_id(uint8_t* buffer, uint16_t length); 111 | 112 | mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_connect(mqtt_connection_t* connection, mqtt_connect_info_t* info); 113 | mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_publish(mqtt_connection_t* connection, const char* topic, const char* data, int data_length, int qos, int retain, uint16_t* message_id); 114 | mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_puback(mqtt_connection_t* connection, uint16_t message_id); 115 | mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_pubrec(mqtt_connection_t* connection, uint16_t message_id); 116 | mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_pubrel(mqtt_connection_t* connection, uint16_t message_id); 117 | mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_pubcomp(mqtt_connection_t* connection, uint16_t message_id); 118 | mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_subscribe(mqtt_connection_t* connection, const char* topic, int qos, uint16_t* message_id); 119 | mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_unsubscribe(mqtt_connection_t* connection, const char* topic, uint16_t* message_id); 120 | mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_pingreq(mqtt_connection_t* connection); 121 | mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_pingresp(mqtt_connection_t* connection); 122 | mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_disconnect(mqtt_connection_t* connection); 123 | 124 | 125 | #ifdef __cplusplus 126 | } 127 | #endif 128 | 129 | #endif /* MQTT_MSG_H */ 130 | 131 | -------------------------------------------------------------------------------- /aliyun_mqtt_app/include/mqtt/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 | -------------------------------------------------------------------------------- /aliyun_mqtt_app/include/mqtt/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 | -------------------------------------------------------------------------------- /aliyun_mqtt_app/include/mqtt/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 | -------------------------------------------------------------------------------- /aliyun_mqtt_app/include/mqtt/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 | -------------------------------------------------------------------------------- /aliyun_mqtt_app/include/mqtt/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 | -------------------------------------------------------------------------------- /aliyun_mqtt_app/include/mqtt_config.h: -------------------------------------------------------------------------------- 1 | #ifndef __MQTT_CONFIG_H__ 2 | #define __MQTT_CONFIG_H__ 3 | 4 | #define CFG_HOLDER 0x00FF55A3 /* Change this value to load default configurations */ 5 | #define CFG_LOCATION 0x79 /* Please don't change or if you know what you doing */ 6 | #define MQTT_SSL_ENABLE 7 | 8 | /*DEFAULT CONFIGURATIONS*/ 9 | 10 | 11 | /* 以下配置转移到 aliyun_mqtt.h */ 12 | #if 0 13 | 14 | #define MQTT_HOST "192.168.10.168" //or "mqtt.yourdomain.com" 15 | #define MQTT_PORT 61613 16 | 17 | #define MQTT_CLIENT_ID "DVES_%08X" 18 | #define MQTT_USER "admin" 19 | #define MQTT_PASS "password" 20 | 21 | #endif 22 | 23 | #define MQTT_BUF_SIZE 1024 24 | #define MQTT_KEEPALIVE 120 /*second*/ 25 | 26 | /* 以下配置转移到 user_config.h */ 27 | #if 0 28 | #define STA_SSID "DVES_HOME" 29 | #define STA_PASS "yourpassword" 30 | #define STA_TYPE AUTH_WPA2_PSK 31 | #endif 32 | 33 | #define MQTT_RECONNECT_TIMEOUT 5 /*second*/ 34 | 35 | #define DEFAULT_SECURITY 0 36 | #define QUEUE_BUFFER_SIZE 2048 37 | 38 | //#define PROTOCOL_NAMEv31 /*MQTT version 3.1 compatible with Mosquitto v0.15*/ 39 | #define PROTOCOL_NAMEv311 /*MQTT version 3.11 compatible with https://eclipse.org/paho/clients/testing/*/ 40 | 41 | #endif // __MQTT_CONFIG_H__ 42 | -------------------------------------------------------------------------------- /aliyun_mqtt_app/include/user_config.h: -------------------------------------------------------------------------------- 1 | #ifndef __USER_CONFIG_H__ 2 | #define __USER_CONFIG_H__ 3 | 4 | #define PRODUCT_KEY "PRODUCT_KEY" 5 | 6 | #define DEVICE_NAME "DEVICE_NAME" 7 | #define DEVICE_SECRET "DEVICE_SECRET" 8 | 9 | #define WIFI_SSID "WIFI_SSID" 10 | #define WIFI_PASS "WIFI_PASS" 11 | 12 | #endif 13 | 14 | -------------------------------------------------------------------------------- /aliyun_mqtt_app/include/user_wifi.h: -------------------------------------------------------------------------------- 1 | /* 2 | * user_wifi.h 3 | */ 4 | 5 | #ifndef _USER_WIFI_H_ 6 | #define _USER_WIFI_H_ 7 | 8 | #include "os_type.h" 9 | #include "user_config.h" 10 | 11 | typedef void (*WifiCallback)(uint8_t); 12 | 13 | extern void wifi_check_init(u16); 14 | extern void wifi_connect(WifiCallback cb); 15 | 16 | #endif /* _USER_WIFI_H_ */ 17 | -------------------------------------------------------------------------------- /aliyun_mqtt_app/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 | -------------------------------------------------------------------------------- /aliyun_mqtt_app/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 | // 如果不希望mqtt打印信息,可以注释下面这条语句 12 | #define MQTT_DEBUG_ON 13 | 14 | #if defined(MQTT_DEBUG_ON) 15 | #define INFO( format, ... ) os_printf( format, ## __VA_ARGS__ ) 16 | #else 17 | #define INFO( format, ... ) 18 | #endif 19 | 20 | // #ifndef INFO 21 | // #define INFO os_printf 22 | // #endif 23 | 24 | #endif /* USER_DEBUG_H_ */ 25 | -------------------------------------------------------------------------------- /aliyun_mqtt_app/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_config.h" 33 | #include "mqtt_msg.h" 34 | #include "user_interface.h" 35 | 36 | #include "queue.h" 37 | typedef struct mqtt_event_data_t 38 | { 39 | uint8_t type; 40 | const char* topic; 41 | const char* data; 42 | uint16_t topic_length; 43 | uint16_t data_length; 44 | uint16_t data_offset; 45 | } mqtt_event_data_t; 46 | 47 | typedef struct mqtt_state_t 48 | { 49 | uint16_t port; 50 | int auto_reconnect; 51 | mqtt_connect_info_t* connect_info; 52 | uint8_t* in_buffer; 53 | uint8_t* out_buffer; 54 | int in_buffer_length; 55 | int out_buffer_length; 56 | uint16_t message_length; 57 | uint16_t message_length_read; 58 | mqtt_message_t* outbound_message; 59 | mqtt_connection_t mqtt_connection; 60 | uint16_t pending_msg_id; 61 | int pending_msg_type; 62 | int pending_publish_qos; 63 | } mqtt_state_t; 64 | 65 | typedef enum { 66 | WIFI_INIT, 67 | WIFI_CONNECTING, 68 | WIFI_CONNECTING_ERROR, 69 | WIFI_CONNECTED, 70 | DNS_RESOLVE, 71 | TCP_DISCONNECTING, 72 | TCP_DISCONNECTED, 73 | TCP_RECONNECT_DISCONNECTING, 74 | TCP_RECONNECT_REQ, 75 | TCP_RECONNECT, 76 | TCP_CONNECTING, 77 | TCP_CONNECTING_ERROR, 78 | TCP_CONNECTED, 79 | MQTT_CONNECT_SEND, 80 | MQTT_CONNECT_SENDING, 81 | MQTT_SUBSCIBE_SEND, 82 | MQTT_SUBSCIBE_SENDING, 83 | MQTT_DATA, 84 | MQTT_KEEPALIVE_SEND, 85 | MQTT_PUBLISH_RECV, 86 | MQTT_PUBLISHING, 87 | MQTT_DELETING, 88 | MQTT_DELETED, 89 | } tConnState; 90 | 91 | typedef void (*MqttCallback)(uint32_t *args); 92 | typedef void (*MqttDataCallback)(uint32_t *args, const char* topic, uint32_t topic_len, const char *data, uint32_t lengh); 93 | 94 | typedef struct { 95 | struct espconn *pCon; 96 | uint8_t security; 97 | uint8_t* host; 98 | uint32_t port; 99 | ip_addr_t ip; 100 | mqtt_state_t mqtt_state; 101 | mqtt_connect_info_t connect_info; 102 | MqttCallback connectedCb; 103 | MqttCallback disconnectedCb; 104 | MqttCallback publishedCb; 105 | MqttCallback timeoutCb; 106 | MqttDataCallback dataCb; 107 | ETSTimer mqttTimer; 108 | uint32_t keepAliveTick; 109 | uint32_t reconnectTick; 110 | uint32_t sendTimeout; 111 | tConnState connState; 112 | QUEUE msgQueue; 113 | void* user_data; 114 | } MQTT_Client; 115 | 116 | #define SEC_NONSSL 0 117 | #define SEC_SSL 1 118 | 119 | #define MQTT_FLAG_CONNECTED 1 120 | #define MQTT_FLAG_READY 2 121 | #define MQTT_FLAG_EXIT 4 122 | 123 | #define MQTT_EVENT_TYPE_NONE 0 124 | #define MQTT_EVENT_TYPE_CONNECTED 1 125 | #define MQTT_EVENT_TYPE_DISCONNECTED 2 126 | #define MQTT_EVENT_TYPE_SUBSCRIBED 3 127 | #define MQTT_EVENT_TYPE_UNSUBSCRIBED 4 128 | #define MQTT_EVENT_TYPE_PUBLISH 5 129 | #define MQTT_EVENT_TYPE_PUBLISHED 6 130 | #define MQTT_EVENT_TYPE_EXITED 7 131 | #define MQTT_EVENT_TYPE_PUBLISH_CONTINUATION 8 132 | 133 | void ICACHE_FLASH_ATTR MQTT_InitConnection(MQTT_Client *mqttClient, uint8_t* host, uint32_t port, uint8_t security); 134 | 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); 135 | void ICACHE_FLASH_ATTR MQTT_DeleteClient(MQTT_Client *mqttClient); 136 | 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); 137 | void ICACHE_FLASH_ATTR MQTT_OnConnected(MQTT_Client *mqttClient, MqttCallback connectedCb); 138 | void ICACHE_FLASH_ATTR MQTT_OnDisconnected(MQTT_Client *mqttClient, MqttCallback disconnectedCb); 139 | void ICACHE_FLASH_ATTR MQTT_OnPublished(MQTT_Client *mqttClient, MqttCallback publishedCb); 140 | void ICACHE_FLASH_ATTR MQTT_OnTimeout(MQTT_Client *mqttClient, MqttCallback timeoutCb); 141 | void ICACHE_FLASH_ATTR MQTT_OnData(MQTT_Client *mqttClient, MqttDataCallback dataCb); 142 | BOOL ICACHE_FLASH_ATTR MQTT_Subscribe(MQTT_Client *client, char* topic, uint8_t qos); 143 | BOOL ICACHE_FLASH_ATTR MQTT_UnSubscribe(MQTT_Client *client, char* topic); 144 | void ICACHE_FLASH_ATTR MQTT_Connect(MQTT_Client *mqttClient); 145 | void ICACHE_FLASH_ATTR MQTT_Disconnect(MQTT_Client *mqttClient); 146 | BOOL ICACHE_FLASH_ATTR MQTT_Publish(MQTT_Client *client, const char* topic, const char* data, int data_length, int qos, int retain); 147 | 148 | #endif /* USER_AT_MQTT_H_ */ 149 | -------------------------------------------------------------------------------- /aliyun_mqtt_app/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 "mqtt_config.h" 11 | #include "c_types.h" 12 | #ifdef __cplusplus 13 | extern "C" { 14 | #endif 15 | 16 | /* 17 | * Copyright (c) 2014, Stephen Robinson 18 | * All rights reserved. 19 | * 20 | * Redistribution and use in source and binary forms, with or without 21 | * modification, are permitted provided that the following conditions 22 | * are met: 23 | * 24 | * 1. Redistributions of source code must retain the above copyright 25 | * notice, this list of conditions and the following disclaimer. 26 | * 2. Redistributions in binary form must reproduce the above copyright 27 | * notice, this list of conditions and the following disclaimer in the 28 | * documentation and/or other materials provided with the distribution. 29 | * 3. Neither the name of the copyright holder nor the names of its 30 | * contributors may be used to endorse or promote products derived 31 | * from this software without specific prior written permission. 32 | * 33 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 34 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 35 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 36 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 37 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 38 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 39 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 40 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 41 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 42 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 43 | * POSSIBILITY OF SUCH DAMAGE. 44 | * 45 | */ 46 | /* 7 6 5 4 3 2 1 0*/ 47 | /*| --- Message Type---- | DUP Flag | QoS Level | Retain | 48 | /* Remaining Length */ 49 | 50 | 51 | enum mqtt_message_type 52 | { 53 | MQTT_MSG_TYPE_CONNECT = 1, 54 | MQTT_MSG_TYPE_CONNACK = 2, 55 | MQTT_MSG_TYPE_PUBLISH = 3, 56 | MQTT_MSG_TYPE_PUBACK = 4, 57 | MQTT_MSG_TYPE_PUBREC = 5, 58 | MQTT_MSG_TYPE_PUBREL = 6, 59 | MQTT_MSG_TYPE_PUBCOMP = 7, 60 | MQTT_MSG_TYPE_SUBSCRIBE = 8, 61 | MQTT_MSG_TYPE_SUBACK = 9, 62 | MQTT_MSG_TYPE_UNSUBSCRIBE = 10, 63 | MQTT_MSG_TYPE_UNSUBACK = 11, 64 | MQTT_MSG_TYPE_PINGREQ = 12, 65 | MQTT_MSG_TYPE_PINGRESP = 13, 66 | MQTT_MSG_TYPE_DISCONNECT = 14 67 | }; 68 | 69 | typedef struct mqtt_message 70 | { 71 | uint8_t* data; 72 | uint16_t length; 73 | 74 | } mqtt_message_t; 75 | 76 | typedef struct mqtt_connection 77 | { 78 | mqtt_message_t message; 79 | 80 | uint16_t message_id; 81 | uint8_t* buffer; 82 | uint16_t buffer_length; 83 | 84 | } mqtt_connection_t; 85 | 86 | typedef struct mqtt_connect_info 87 | { 88 | char* client_id; 89 | char* username; 90 | char* password; 91 | char* will_topic; 92 | char* will_message; 93 | int keepalive; 94 | int will_qos; 95 | int will_retain; 96 | int clean_session; 97 | 98 | } mqtt_connect_info_t; 99 | 100 | 101 | static inline int ICACHE_FLASH_ATTR mqtt_get_type(uint8_t* buffer) { return (buffer[0] & 0xf0) >> 4; } 102 | static inline int ICACHE_FLASH_ATTR mqtt_get_dup(uint8_t* buffer) { return (buffer[0] & 0x08) >> 3; } 103 | static inline int ICACHE_FLASH_ATTR mqtt_get_qos(uint8_t* buffer) { return (buffer[0] & 0x06) >> 1; } 104 | static inline int ICACHE_FLASH_ATTR mqtt_get_retain(uint8_t* buffer) { return (buffer[0] & 0x01); } 105 | 106 | void ICACHE_FLASH_ATTR mqtt_msg_init(mqtt_connection_t* connection, uint8_t* buffer, uint16_t buffer_length); 107 | int ICACHE_FLASH_ATTR mqtt_get_total_length(uint8_t* buffer, uint16_t length); 108 | const char* ICACHE_FLASH_ATTR mqtt_get_publish_topic(uint8_t* buffer, uint16_t* length); 109 | const char* ICACHE_FLASH_ATTR mqtt_get_publish_data(uint8_t* buffer, uint16_t* length); 110 | uint16_t ICACHE_FLASH_ATTR mqtt_get_id(uint8_t* buffer, uint16_t length); 111 | 112 | mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_connect(mqtt_connection_t* connection, mqtt_connect_info_t* info); 113 | mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_publish(mqtt_connection_t* connection, const char* topic, const char* data, int data_length, int qos, int retain, uint16_t* message_id); 114 | mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_puback(mqtt_connection_t* connection, uint16_t message_id); 115 | mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_pubrec(mqtt_connection_t* connection, uint16_t message_id); 116 | mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_pubrel(mqtt_connection_t* connection, uint16_t message_id); 117 | mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_pubcomp(mqtt_connection_t* connection, uint16_t message_id); 118 | mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_subscribe(mqtt_connection_t* connection, const char* topic, int qos, uint16_t* message_id); 119 | mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_unsubscribe(mqtt_connection_t* connection, const char* topic, uint16_t* message_id); 120 | mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_pingreq(mqtt_connection_t* connection); 121 | mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_pingresp(mqtt_connection_t* connection); 122 | mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_disconnect(mqtt_connection_t* connection); 123 | 124 | 125 | #ifdef __cplusplus 126 | } 127 | #endif 128 | 129 | #endif /* MQTT_MSG_H */ 130 | 131 | -------------------------------------------------------------------------------- /aliyun_mqtt_app/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 | -------------------------------------------------------------------------------- /aliyun_mqtt_app/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 | -------------------------------------------------------------------------------- /aliyun_mqtt_app/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 | -------------------------------------------------------------------------------- /aliyun_mqtt_app/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 | -------------------------------------------------------------------------------- /aliyun_mqtt_app/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 | -------------------------------------------------------------------------------- /aliyun_mqtt_app/mqtt/mqtt.c: -------------------------------------------------------------------------------- 1 | /* mqtt.c 2 | * Protocol: http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html 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 | 32 | #include "user_interface.h" 33 | #include "osapi.h" 34 | #include "espconn.h" 35 | #include "os_type.h" 36 | #include "mem.h" 37 | #include "mqtt_msg.h" 38 | #include "debug.h" 39 | #include "user_config.h" 40 | #include "mqtt.h" 41 | #include "queue.h" 42 | 43 | #define MQTT_TASK_PRIO 2 44 | #define MQTT_TASK_QUEUE_SIZE 1 45 | #define MQTT_SEND_TIMOUT 5 46 | 47 | #ifndef QUEUE_BUFFER_SIZE 48 | #define QUEUE_BUFFER_SIZE 2048 49 | #endif 50 | 51 | unsigned char *default_certificate; 52 | unsigned int default_certificate_len = 0; 53 | unsigned char *default_private_key; 54 | unsigned int default_private_key_len = 0; 55 | 56 | os_event_t mqtt_procTaskQueue[MQTT_TASK_QUEUE_SIZE]; 57 | 58 | LOCAL void ICACHE_FLASH_ATTR 59 | mqtt_dns_found(const char *name, ip_addr_t *ipaddr, void *arg) 60 | { 61 | struct espconn *pConn = (struct espconn *)arg; 62 | MQTT_Client* client = (MQTT_Client *)pConn->reverse; 63 | 64 | 65 | if (ipaddr == NULL) 66 | { 67 | INFO("DNS: Found, but got no ip, try to reconnect\r\n"); 68 | client->connState = TCP_RECONNECT_REQ; 69 | return; 70 | } 71 | 72 | INFO("DNS: found ip %d.%d.%d.%d\n", 73 | *((uint8 *) &ipaddr->addr), 74 | *((uint8 *) &ipaddr->addr + 1), 75 | *((uint8 *) &ipaddr->addr + 2), 76 | *((uint8 *) &ipaddr->addr + 3)); 77 | 78 | if (client->ip.addr == 0 && ipaddr->addr != 0) 79 | { 80 | os_memcpy(client->pCon->proto.tcp->remote_ip, &ipaddr->addr, 4); 81 | if (client->security) { 82 | #ifdef MQTT_SSL_ENABLE 83 | espconn_secure_connect(client->pCon); 84 | #else 85 | INFO("TCP: Do not support SSL\r\n"); 86 | #endif 87 | } 88 | else { 89 | espconn_connect(client->pCon); 90 | } 91 | 92 | client->connState = TCP_CONNECTING; 93 | INFO("TCP: connecting...\r\n"); 94 | } 95 | 96 | system_os_post(MQTT_TASK_PRIO, 0, (os_param_t)client); 97 | } 98 | 99 | 100 | 101 | LOCAL void ICACHE_FLASH_ATTR 102 | deliver_publish(MQTT_Client* client, uint8_t* message, int length) 103 | { 104 | mqtt_event_data_t event_data; 105 | 106 | event_data.topic_length = length; 107 | event_data.topic = mqtt_get_publish_topic(message, &event_data.topic_length); 108 | event_data.data_length = length; 109 | event_data.data = mqtt_get_publish_data(message, &event_data.data_length); 110 | 111 | if (client->dataCb) 112 | client->dataCb((uint32_t*)client, event_data.topic, event_data.topic_length, event_data.data, event_data.data_length); 113 | 114 | } 115 | 116 | void ICACHE_FLASH_ATTR 117 | mqtt_send_keepalive(MQTT_Client *client) 118 | { 119 | INFO("\r\nMQTT: Send keepalive packet to %s:%d!\r\n", client->host, client->port); 120 | client->mqtt_state.outbound_message = mqtt_msg_pingreq(&client->mqtt_state.mqtt_connection); 121 | client->mqtt_state.pending_msg_type = MQTT_MSG_TYPE_PINGREQ; 122 | client->mqtt_state.pending_msg_type = mqtt_get_type(client->mqtt_state.outbound_message->data); 123 | client->mqtt_state.pending_msg_id = mqtt_get_id(client->mqtt_state.outbound_message->data, client->mqtt_state.outbound_message->length); 124 | 125 | 126 | client->sendTimeout = MQTT_SEND_TIMOUT; 127 | INFO("MQTT: Sending, type: %d, id: %04X\r\n", client->mqtt_state.pending_msg_type, client->mqtt_state.pending_msg_id); 128 | err_t result = ESPCONN_OK; 129 | if (client->security) { 130 | #ifdef MQTT_SSL_ENABLE 131 | result = espconn_secure_send(client->pCon, client->mqtt_state.outbound_message->data, client->mqtt_state.outbound_message->length); 132 | #else 133 | INFO("TCP: Do not support SSL\r\n"); 134 | #endif 135 | } 136 | else { 137 | result = espconn_send(client->pCon, client->mqtt_state.outbound_message->data, client->mqtt_state.outbound_message->length); 138 | } 139 | 140 | client->mqtt_state.outbound_message = NULL; 141 | if(ESPCONN_OK == result) { 142 | client->keepAliveTick = 0; 143 | client->connState = MQTT_DATA; 144 | system_os_post(MQTT_TASK_PRIO, 0, (os_param_t)client); 145 | } 146 | else { 147 | client->connState = TCP_RECONNECT_DISCONNECTING; 148 | system_os_post(MQTT_TASK_PRIO, 0, (os_param_t)client); 149 | } 150 | } 151 | 152 | /** 153 | * @brief Delete tcp client and free all memory 154 | * @param mqttClient: The mqtt client which contain TCP client 155 | * @retval None 156 | */ 157 | void ICACHE_FLASH_ATTR 158 | mqtt_tcpclient_delete(MQTT_Client *mqttClient) 159 | { 160 | if (mqttClient->pCon != NULL) { 161 | INFO("Free memory\r\n"); 162 | espconn_delete(mqttClient->pCon); 163 | if (mqttClient->pCon->proto.tcp) 164 | os_free(mqttClient->pCon->proto.tcp); 165 | os_free(mqttClient->pCon); 166 | mqttClient->pCon = NULL; 167 | } 168 | } 169 | 170 | /** 171 | * @brief Delete MQTT client and free all memory 172 | * @param mqttClient: The mqtt client 173 | * @retval None 174 | */ 175 | void ICACHE_FLASH_ATTR 176 | mqtt_client_delete(MQTT_Client *mqttClient) 177 | { 178 | mqtt_tcpclient_delete(mqttClient); 179 | if (mqttClient->host != NULL) { 180 | os_free(mqttClient->host); 181 | mqttClient->host = NULL; 182 | } 183 | 184 | if (mqttClient->user_data != NULL) { 185 | os_free(mqttClient->user_data); 186 | mqttClient->user_data = NULL; 187 | } 188 | 189 | if(mqttClient->connect_info.client_id != NULL) { 190 | os_free(mqttClient->connect_info.client_id); 191 | mqttClient->connect_info.client_id = NULL; 192 | } 193 | 194 | if(mqttClient->connect_info.username != NULL) { 195 | os_free(mqttClient->connect_info.username); 196 | mqttClient->connect_info.username = NULL; 197 | } 198 | 199 | if(mqttClient->connect_info.password != NULL) { 200 | os_free(mqttClient->connect_info.password); 201 | mqttClient->connect_info.password = NULL; 202 | } 203 | 204 | if(mqttClient->connect_info.will_topic != NULL) { 205 | os_free(mqttClient->connect_info.will_topic); 206 | mqttClient->connect_info.will_topic = NULL; 207 | } 208 | 209 | if(mqttClient->connect_info.will_message != NULL) { 210 | os_free(mqttClient->connect_info.will_message); 211 | mqttClient->connect_info.will_message = NULL; 212 | } 213 | 214 | if(mqttClient->mqtt_state.in_buffer != NULL) { 215 | os_free(mqttClient->mqtt_state.in_buffer); 216 | mqttClient->mqtt_state.in_buffer = NULL; 217 | } 218 | 219 | if(mqttClient->mqtt_state.out_buffer != NULL) { 220 | os_free(mqttClient->mqtt_state.out_buffer); 221 | mqttClient->mqtt_state.out_buffer = NULL; 222 | } 223 | } 224 | 225 | 226 | /** 227 | * @brief Client received callback function. 228 | * @param arg: contain the ip link information 229 | * @param pdata: received data 230 | * @param len: the lenght of received data 231 | * @retval None 232 | */ 233 | void ICACHE_FLASH_ATTR 234 | mqtt_tcpclient_recv(void *arg, char *pdata, unsigned short len) 235 | { 236 | uint8_t msg_type; 237 | uint8_t msg_qos; 238 | uint16_t msg_id; 239 | 240 | struct espconn *pCon = (struct espconn*)arg; 241 | MQTT_Client *client = (MQTT_Client *)pCon->reverse; 242 | 243 | client->keepAliveTick = 0; 244 | READPACKET: 245 | INFO("TCP: data received %d bytes\r\n", len); 246 | if (len < MQTT_BUF_SIZE && len > 0) { 247 | os_memcpy(client->mqtt_state.in_buffer, pdata, len); 248 | 249 | msg_type = mqtt_get_type(client->mqtt_state.in_buffer); 250 | msg_qos = mqtt_get_qos(client->mqtt_state.in_buffer); 251 | msg_id = mqtt_get_id(client->mqtt_state.in_buffer, client->mqtt_state.in_buffer_length); 252 | switch (client->connState) { 253 | case MQTT_CONNECT_SENDING: 254 | if (msg_type == MQTT_MSG_TYPE_CONNACK) { 255 | if (client->mqtt_state.pending_msg_type != MQTT_MSG_TYPE_CONNECT) { 256 | INFO("MQTT: Invalid packet\r\n"); 257 | if (client->security) { 258 | #ifdef MQTT_SSL_ENABLE 259 | espconn_secure_disconnect(client->pCon); 260 | #else 261 | INFO("TCP: Do not support SSL\r\n"); 262 | #endif 263 | } 264 | else { 265 | espconn_disconnect(client->pCon); 266 | } 267 | } else { 268 | INFO("MQTT: Connected to %s:%d\r\n", client->host, client->port); 269 | client->connState = MQTT_DATA; 270 | if (client->connectedCb) 271 | client->connectedCb((uint32_t*)client); 272 | } 273 | 274 | } 275 | break; 276 | case MQTT_DATA: 277 | case MQTT_KEEPALIVE_SEND: 278 | client->mqtt_state.message_length_read = len; 279 | client->mqtt_state.message_length = mqtt_get_total_length(client->mqtt_state.in_buffer, client->mqtt_state.message_length_read); 280 | 281 | 282 | switch (msg_type) 283 | { 284 | 285 | case MQTT_MSG_TYPE_SUBACK: 286 | if (client->mqtt_state.pending_msg_type == MQTT_MSG_TYPE_SUBSCRIBE && client->mqtt_state.pending_msg_id == msg_id) 287 | INFO("MQTT: Subscribe successful\r\n"); 288 | break; 289 | case MQTT_MSG_TYPE_UNSUBACK: 290 | if (client->mqtt_state.pending_msg_type == MQTT_MSG_TYPE_UNSUBSCRIBE && client->mqtt_state.pending_msg_id == msg_id) 291 | INFO("MQTT: UnSubscribe successful\r\n"); 292 | break; 293 | case MQTT_MSG_TYPE_PUBLISH: 294 | if (msg_qos == 1) 295 | client->mqtt_state.outbound_message = mqtt_msg_puback(&client->mqtt_state.mqtt_connection, msg_id); 296 | else if (msg_qos == 2) 297 | client->mqtt_state.outbound_message = mqtt_msg_pubrec(&client->mqtt_state.mqtt_connection, msg_id); 298 | if (msg_qos == 1 || msg_qos == 2) { 299 | INFO("MQTT: Queue response QoS: %d\r\n", msg_qos); 300 | if (QUEUE_Puts(&client->msgQueue, client->mqtt_state.outbound_message->data, client->mqtt_state.outbound_message->length) == -1) { 301 | INFO("MQTT: Queue full\r\n"); 302 | } 303 | } 304 | 305 | deliver_publish(client, client->mqtt_state.in_buffer, client->mqtt_state.message_length_read); 306 | break; 307 | case MQTT_MSG_TYPE_PUBACK: 308 | if (client->mqtt_state.pending_msg_type == MQTT_MSG_TYPE_PUBLISH && client->mqtt_state.pending_msg_id == msg_id) { 309 | INFO("MQTT: received MQTT_MSG_TYPE_PUBACK, finish QoS1 publish\r\n"); 310 | } 311 | 312 | break; 313 | case MQTT_MSG_TYPE_PUBREC: 314 | client->mqtt_state.outbound_message = mqtt_msg_pubrel(&client->mqtt_state.mqtt_connection, msg_id); 315 | if (QUEUE_Puts(&client->msgQueue, client->mqtt_state.outbound_message->data, client->mqtt_state.outbound_message->length) == -1) { 316 | INFO("MQTT: Queue full\r\n"); 317 | } 318 | break; 319 | case MQTT_MSG_TYPE_PUBREL: 320 | client->mqtt_state.outbound_message = mqtt_msg_pubcomp(&client->mqtt_state.mqtt_connection, msg_id); 321 | if (QUEUE_Puts(&client->msgQueue, client->mqtt_state.outbound_message->data, client->mqtt_state.outbound_message->length) == -1) { 322 | INFO("MQTT: Queue full\r\n"); 323 | } 324 | break; 325 | case MQTT_MSG_TYPE_PUBCOMP: 326 | if (client->mqtt_state.pending_msg_type == MQTT_MSG_TYPE_PUBLISH && client->mqtt_state.pending_msg_id == msg_id) { 327 | INFO("MQTT: receive MQTT_MSG_TYPE_PUBCOMP, finish QoS2 publish\r\n"); 328 | } 329 | break; 330 | case MQTT_MSG_TYPE_PINGREQ: 331 | client->mqtt_state.outbound_message = mqtt_msg_pingresp(&client->mqtt_state.mqtt_connection); 332 | if (QUEUE_Puts(&client->msgQueue, client->mqtt_state.outbound_message->data, client->mqtt_state.outbound_message->length) == -1) { 333 | INFO("MQTT: Queue full\r\n"); 334 | } 335 | break; 336 | case MQTT_MSG_TYPE_PINGRESP: 337 | // Ignore 338 | break; 339 | } 340 | // NOTE: this is done down here and not in the switch case above 341 | // because the PSOCK_READBUF_LEN() won't work inside a switch 342 | // statement due to the way protothreads resume. 343 | if (msg_type == MQTT_MSG_TYPE_PUBLISH) 344 | { 345 | len = client->mqtt_state.message_length_read; 346 | 347 | if (client->mqtt_state.message_length < client->mqtt_state.message_length_read) 348 | { 349 | //client->connState = MQTT_PUBLISH_RECV; 350 | //Not Implement yet 351 | len -= client->mqtt_state.message_length; 352 | pdata += client->mqtt_state.message_length; 353 | 354 | INFO("Get another published message\r\n"); 355 | goto READPACKET; 356 | } 357 | 358 | } 359 | break; 360 | } 361 | } else { 362 | INFO("ERROR: Message too long\r\n"); 363 | } 364 | system_os_post(MQTT_TASK_PRIO, 0, (os_param_t)client); 365 | } 366 | 367 | /** 368 | * @brief Client send over callback function. 369 | * @param arg: contain the ip link information 370 | * @retval None 371 | */ 372 | void ICACHE_FLASH_ATTR 373 | mqtt_tcpclient_sent_cb(void *arg) 374 | { 375 | struct espconn *pCon = (struct espconn *)arg; 376 | MQTT_Client* client = (MQTT_Client *)pCon->reverse; 377 | INFO("TCP: Sent\r\n"); 378 | client->sendTimeout = 0; 379 | client->keepAliveTick =0; 380 | 381 | if ((client->connState == MQTT_DATA || client->connState == MQTT_KEEPALIVE_SEND) 382 | && client->mqtt_state.pending_msg_type == MQTT_MSG_TYPE_PUBLISH) { 383 | if (client->publishedCb) 384 | client->publishedCb((uint32_t*)client); 385 | } 386 | system_os_post(MQTT_TASK_PRIO, 0, (os_param_t)client); 387 | } 388 | 389 | void ICACHE_FLASH_ATTR mqtt_timer(void *arg) 390 | { 391 | MQTT_Client* client = (MQTT_Client*)arg; 392 | 393 | if (client->connState == MQTT_DATA) { 394 | client->keepAliveTick ++; 395 | if (client->keepAliveTick > client->mqtt_state.connect_info->keepalive) { 396 | client->connState = MQTT_KEEPALIVE_SEND; 397 | system_os_post(MQTT_TASK_PRIO, 0, (os_param_t)client); 398 | } 399 | 400 | } else if (client->connState == TCP_RECONNECT_REQ) { 401 | client->reconnectTick ++; 402 | if (client->reconnectTick > MQTT_RECONNECT_TIMEOUT) { 403 | client->reconnectTick = 0; 404 | client->connState = TCP_RECONNECT; 405 | system_os_post(MQTT_TASK_PRIO, 0, (os_param_t)client); 406 | if (client->timeoutCb) 407 | client->timeoutCb((uint32_t*)client); 408 | } 409 | } 410 | if (client->sendTimeout > 0) 411 | client->sendTimeout --; 412 | } 413 | 414 | void ICACHE_FLASH_ATTR 415 | mqtt_tcpclient_discon_cb(void *arg) 416 | { 417 | 418 | struct espconn *pespconn = (struct espconn *)arg; 419 | MQTT_Client* client = (MQTT_Client *)pespconn->reverse; 420 | INFO("TCP: Disconnected callback\r\n"); 421 | if(TCP_DISCONNECTING == client->connState) { 422 | client->connState = TCP_DISCONNECTED; 423 | } 424 | else if(MQTT_DELETING == client->connState) { 425 | client->connState = MQTT_DELETED; 426 | } 427 | else { 428 | client->connState = TCP_RECONNECT_REQ; 429 | } 430 | if (client->disconnectedCb) 431 | client->disconnectedCb((uint32_t*)client); 432 | 433 | system_os_post(MQTT_TASK_PRIO, 0, (os_param_t)client); 434 | } 435 | 436 | 437 | 438 | /** 439 | * @brief Tcp client connect success callback function. 440 | * @param arg: contain the ip link information 441 | * @retval None 442 | */ 443 | void ICACHE_FLASH_ATTR 444 | mqtt_tcpclient_connect_cb(void *arg) 445 | { 446 | struct espconn *pCon = (struct espconn *)arg; 447 | MQTT_Client* client = (MQTT_Client *)pCon->reverse; 448 | 449 | espconn_regist_disconcb(client->pCon, mqtt_tcpclient_discon_cb); 450 | espconn_regist_recvcb(client->pCon, mqtt_tcpclient_recv);//////// 451 | espconn_regist_sentcb(client->pCon, mqtt_tcpclient_sent_cb);/////// 452 | INFO("MQTT: Connected to broker %s:%d\r\n", client->host, client->port); 453 | 454 | mqtt_msg_init(&client->mqtt_state.mqtt_connection, client->mqtt_state.out_buffer, client->mqtt_state.out_buffer_length); 455 | client->mqtt_state.outbound_message = mqtt_msg_connect(&client->mqtt_state.mqtt_connection, client->mqtt_state.connect_info); 456 | client->mqtt_state.pending_msg_type = mqtt_get_type(client->mqtt_state.outbound_message->data); 457 | client->mqtt_state.pending_msg_id = mqtt_get_id(client->mqtt_state.outbound_message->data, client->mqtt_state.outbound_message->length); 458 | 459 | 460 | client->sendTimeout = MQTT_SEND_TIMOUT; 461 | INFO("MQTT: Sending, type: %d, id: %04X\r\n", client->mqtt_state.pending_msg_type, client->mqtt_state.pending_msg_id); 462 | if (client->security) { 463 | #ifdef MQTT_SSL_ENABLE 464 | espconn_secure_send(client->pCon, client->mqtt_state.outbound_message->data, client->mqtt_state.outbound_message->length); 465 | #else 466 | INFO("TCP: Do not support SSL\r\n"); 467 | #endif 468 | } 469 | else { 470 | espconn_send(client->pCon, client->mqtt_state.outbound_message->data, client->mqtt_state.outbound_message->length); 471 | } 472 | 473 | client->mqtt_state.outbound_message = NULL; 474 | client->connState = MQTT_CONNECT_SENDING; 475 | system_os_post(MQTT_TASK_PRIO, 0, (os_param_t)client); 476 | } 477 | 478 | /** 479 | * @brief Tcp client connect repeat callback function. 480 | * @param arg: contain the ip link information 481 | * @retval None 482 | */ 483 | void ICACHE_FLASH_ATTR 484 | mqtt_tcpclient_recon_cb(void *arg, sint8 errType) 485 | { 486 | struct espconn *pCon = (struct espconn *)arg; 487 | MQTT_Client* client = (MQTT_Client *)pCon->reverse; 488 | 489 | INFO("TCP: Reconnect to %s:%d\r\n", client->host, client->port); 490 | 491 | client->connState = TCP_RECONNECT_REQ; 492 | 493 | system_os_post(MQTT_TASK_PRIO, 0, (os_param_t)client); 494 | 495 | } 496 | 497 | /** 498 | * @brief MQTT publish function. 499 | * @param client: MQTT_Client reference 500 | * @param topic: string topic will publish to 501 | * @param data: buffer data send point to 502 | * @param data_length: length of data 503 | * @param qos: qos 504 | * @param retain: retain 505 | * @retval TRUE if success queue 506 | */ 507 | BOOL ICACHE_FLASH_ATTR 508 | MQTT_Publish(MQTT_Client *client, const char* topic, const char* data, int data_length, int qos, int retain) 509 | { 510 | uint8_t dataBuffer[MQTT_BUF_SIZE]; 511 | uint16_t dataLen; 512 | client->mqtt_state.outbound_message = mqtt_msg_publish(&client->mqtt_state.mqtt_connection, 513 | topic, data, data_length, 514 | qos, retain, 515 | &client->mqtt_state.pending_msg_id); 516 | if (client->mqtt_state.outbound_message->length == 0) { 517 | INFO("MQTT: Queuing publish failed\r\n"); 518 | return FALSE; 519 | } 520 | INFO("MQTT: queuing publish, length: %d, queue size(%d/%d)\r\n", client->mqtt_state.outbound_message->length, client->msgQueue.rb.fill_cnt, client->msgQueue.rb.size); 521 | while (QUEUE_Puts(&client->msgQueue, client->mqtt_state.outbound_message->data, client->mqtt_state.outbound_message->length) == -1) { 522 | INFO("MQTT: Queue full\r\n"); 523 | if (QUEUE_Gets(&client->msgQueue, dataBuffer, &dataLen, MQTT_BUF_SIZE) == -1) { 524 | INFO("MQTT: Serious buffer error\r\n"); 525 | return FALSE; 526 | } 527 | } 528 | system_os_post(MQTT_TASK_PRIO, 0, (os_param_t)client); 529 | return TRUE; 530 | } 531 | 532 | /** 533 | * @brief MQTT subscibe function. 534 | * @param client: MQTT_Client reference 535 | * @param topic: string topic will subscribe 536 | * @param qos: qos 537 | * @retval TRUE if success queue 538 | */ 539 | BOOL ICACHE_FLASH_ATTR 540 | MQTT_Subscribe(MQTT_Client *client, char* topic, uint8_t qos) 541 | { 542 | uint8_t dataBuffer[MQTT_BUF_SIZE]; 543 | uint16_t dataLen; 544 | 545 | client->mqtt_state.outbound_message = mqtt_msg_subscribe(&client->mqtt_state.mqtt_connection, 546 | topic, qos, 547 | &client->mqtt_state.pending_msg_id); 548 | INFO("MQTT: queue subscribe, topic\"%s\", id: %d\r\n", topic, client->mqtt_state.pending_msg_id); 549 | while (QUEUE_Puts(&client->msgQueue, client->mqtt_state.outbound_message->data, client->mqtt_state.outbound_message->length) == -1) { 550 | INFO("MQTT: Queue full\r\n"); 551 | if (QUEUE_Gets(&client->msgQueue, dataBuffer, &dataLen, MQTT_BUF_SIZE) == -1) { 552 | INFO("MQTT: Serious buffer error\r\n"); 553 | return FALSE; 554 | } 555 | } 556 | system_os_post(MQTT_TASK_PRIO, 0, (os_param_t)client); 557 | return TRUE; 558 | } 559 | 560 | /** 561 | * @brief MQTT un-subscibe function. 562 | * @param client: MQTT_Client reference 563 | * @param topic: String topic will un-subscribe 564 | * @retval TRUE if success queue 565 | */ 566 | BOOL ICACHE_FLASH_ATTR 567 | MQTT_UnSubscribe(MQTT_Client *client, char* topic) 568 | { 569 | uint8_t dataBuffer[MQTT_BUF_SIZE]; 570 | uint16_t dataLen; 571 | client->mqtt_state.outbound_message = mqtt_msg_unsubscribe(&client->mqtt_state.mqtt_connection, 572 | topic, 573 | &client->mqtt_state.pending_msg_id); 574 | INFO("MQTT: queue un-subscribe, topic\"%s\", id: %d\r\n", topic, client->mqtt_state.pending_msg_id); 575 | while (QUEUE_Puts(&client->msgQueue, client->mqtt_state.outbound_message->data, client->mqtt_state.outbound_message->length) == -1) { 576 | INFO("MQTT: Queue full\r\n"); 577 | if (QUEUE_Gets(&client->msgQueue, dataBuffer, &dataLen, MQTT_BUF_SIZE) == -1) { 578 | INFO("MQTT: Serious buffer error\r\n"); 579 | return FALSE; 580 | } 581 | } 582 | system_os_post(MQTT_TASK_PRIO, 0, (os_param_t)client); 583 | return TRUE; 584 | } 585 | 586 | /** 587 | * @brief MQTT ping function. 588 | * @param client: MQTT_Client reference 589 | * @retval TRUE if success queue 590 | */ 591 | BOOL ICACHE_FLASH_ATTR 592 | MQTT_Ping(MQTT_Client *client) 593 | { 594 | uint8_t dataBuffer[MQTT_BUF_SIZE]; 595 | uint16_t dataLen; 596 | client->mqtt_state.outbound_message = mqtt_msg_pingreq(&client->mqtt_state.mqtt_connection); 597 | if(client->mqtt_state.outbound_message->length == 0){ 598 | INFO("MQTT: Queuing publish failed\r\n"); 599 | return FALSE; 600 | } 601 | INFO("MQTT: queuing publish, length: %d, queue size(%d/%d)\r\n", client->mqtt_state.outbound_message->length, client->msgQueue.rb.fill_cnt, client->msgQueue.rb.size); 602 | while(QUEUE_Puts(&client->msgQueue, client->mqtt_state.outbound_message->data, client->mqtt_state.outbound_message->length) == -1){ 603 | INFO("MQTT: Queue full\r\n"); 604 | if(QUEUE_Gets(&client->msgQueue, dataBuffer, &dataLen, MQTT_BUF_SIZE) == -1) { 605 | INFO("MQTT: Serious buffer error\r\n"); 606 | return FALSE; 607 | } 608 | } 609 | system_os_post(MQTT_TASK_PRIO, 0, (os_param_t)client); 610 | return TRUE; 611 | } 612 | 613 | void ICACHE_FLASH_ATTR 614 | MQTT_Task(os_event_t *e) 615 | { 616 | MQTT_Client* client = (MQTT_Client*)e->par; 617 | uint8_t dataBuffer[MQTT_BUF_SIZE]; 618 | uint16_t dataLen; 619 | if (e->par == 0) 620 | return; 621 | switch (client->connState) { 622 | 623 | case TCP_RECONNECT_REQ: 624 | break; 625 | case TCP_RECONNECT: 626 | mqtt_tcpclient_delete(client); 627 | MQTT_Connect(client); 628 | INFO("TCP: Reconnect to: %s:%d\r\n", client->host, client->port); 629 | client->connState = TCP_CONNECTING; 630 | break; 631 | case MQTT_DELETING: 632 | case TCP_DISCONNECTING: 633 | case TCP_RECONNECT_DISCONNECTING: 634 | if (client->security) { 635 | #ifdef MQTT_SSL_ENABLE 636 | espconn_secure_disconnect(client->pCon); 637 | #else 638 | INFO("TCP: Do not support SSL\r\n"); 639 | #endif 640 | } 641 | else { 642 | espconn_disconnect(client->pCon); 643 | } 644 | break; 645 | case TCP_DISCONNECTED: 646 | INFO("MQTT: Disconnected\r\n"); 647 | mqtt_tcpclient_delete(client); 648 | break; 649 | case MQTT_DELETED: 650 | INFO("MQTT: Deleted client\r\n"); 651 | mqtt_client_delete(client); 652 | break; 653 | case MQTT_KEEPALIVE_SEND: 654 | mqtt_send_keepalive(client); 655 | break; 656 | case MQTT_DATA: 657 | if (QUEUE_IsEmpty(&client->msgQueue) || client->sendTimeout != 0) { 658 | break; 659 | } 660 | if (QUEUE_Gets(&client->msgQueue, dataBuffer, &dataLen, MQTT_BUF_SIZE) == 0) { 661 | client->mqtt_state.pending_msg_type = mqtt_get_type(dataBuffer); 662 | client->mqtt_state.pending_msg_id = mqtt_get_id(dataBuffer, dataLen); 663 | 664 | 665 | client->sendTimeout = MQTT_SEND_TIMOUT; 666 | INFO("MQTT: Sending, type: %d, id: %04X\r\n", client->mqtt_state.pending_msg_type, client->mqtt_state.pending_msg_id); 667 | if (client->security) { 668 | #ifdef MQTT_SSL_ENABLE 669 | espconn_secure_send(client->pCon, dataBuffer, dataLen); 670 | #else 671 | INFO("TCP: Do not support SSL\r\n"); 672 | #endif 673 | } 674 | else { 675 | espconn_send(client->pCon, dataBuffer, dataLen); 676 | } 677 | 678 | client->mqtt_state.outbound_message = NULL; 679 | break; 680 | } 681 | break; 682 | } 683 | } 684 | 685 | /** 686 | * @brief MQTT initialization connection function 687 | * @param client: MQTT_Client reference 688 | * @param host: Domain or IP string 689 | * @param port: Port to connect 690 | * @param security: 1 for ssl, 0 for none 691 | * @retval None 692 | */ 693 | void ICACHE_FLASH_ATTR 694 | MQTT_InitConnection(MQTT_Client *mqttClient, uint8_t* host, uint32_t port, uint8_t security) 695 | { 696 | uint32_t temp; 697 | INFO("MQTT_InitConnection\r\n"); 698 | os_memset(mqttClient, 0, sizeof(MQTT_Client)); 699 | temp = os_strlen(host); 700 | mqttClient->host = (uint8_t*)os_zalloc(temp + 1); 701 | os_strcpy(mqttClient->host, host); 702 | mqttClient->host[temp] = 0; 703 | mqttClient->port = port; 704 | mqttClient->security = security; 705 | 706 | } 707 | 708 | /** 709 | * @brief MQTT initialization mqtt client function 710 | * @param client: MQTT_Client reference 711 | * @param clientid: MQTT client id 712 | * @param client_user:MQTT client user 713 | * @param client_pass:MQTT client password 714 | * @param client_pass:MQTT keep alive timer, in second 715 | * @retval None 716 | */ 717 | void ICACHE_FLASH_ATTR 718 | MQTT_InitClient(MQTT_Client *mqttClient, uint8_t* client_id, uint8_t* client_user, uint8_t* client_pass, uint32_t keepAliveTime, uint8_t cleanSession) 719 | { 720 | uint32_t temp; 721 | INFO("MQTT_InitClient\r\n"); 722 | 723 | os_memset(&mqttClient->connect_info, 0, sizeof(mqtt_connect_info_t)); 724 | 725 | temp = os_strlen(client_id); 726 | mqttClient->connect_info.client_id = (uint8_t*)os_zalloc(temp + 1); 727 | os_strcpy(mqttClient->connect_info.client_id, client_id); 728 | mqttClient->connect_info.client_id[temp] = 0; 729 | 730 | if (client_user) 731 | { 732 | temp = os_strlen(client_user); 733 | mqttClient->connect_info.username = (uint8_t*)os_zalloc(temp + 1); 734 | os_strcpy(mqttClient->connect_info.username, client_user); 735 | mqttClient->connect_info.username[temp] = 0; 736 | } 737 | 738 | if (client_pass) 739 | { 740 | temp = os_strlen(client_pass); 741 | mqttClient->connect_info.password = (uint8_t*)os_zalloc(temp + 1); 742 | os_strcpy(mqttClient->connect_info.password, client_pass); 743 | mqttClient->connect_info.password[temp] = 0; 744 | } 745 | 746 | 747 | mqttClient->connect_info.keepalive = keepAliveTime; 748 | mqttClient->connect_info.clean_session = cleanSession; 749 | 750 | mqttClient->mqtt_state.in_buffer = (uint8_t *)os_zalloc(MQTT_BUF_SIZE); 751 | mqttClient->mqtt_state.in_buffer_length = MQTT_BUF_SIZE; 752 | mqttClient->mqtt_state.out_buffer = (uint8_t *)os_zalloc(MQTT_BUF_SIZE); 753 | mqttClient->mqtt_state.out_buffer_length = MQTT_BUF_SIZE; 754 | mqttClient->mqtt_state.connect_info = &mqttClient->connect_info; 755 | 756 | mqtt_msg_init(&mqttClient->mqtt_state.mqtt_connection, mqttClient->mqtt_state.out_buffer, mqttClient->mqtt_state.out_buffer_length); 757 | 758 | QUEUE_Init(&mqttClient->msgQueue, QUEUE_BUFFER_SIZE); 759 | 760 | system_os_task(MQTT_Task, MQTT_TASK_PRIO, mqtt_procTaskQueue, MQTT_TASK_QUEUE_SIZE); 761 | system_os_post(MQTT_TASK_PRIO, 0, (os_param_t)mqttClient); 762 | } 763 | void ICACHE_FLASH_ATTR 764 | MQTT_InitLWT(MQTT_Client *mqttClient, uint8_t* will_topic, uint8_t* will_msg, uint8_t will_qos, uint8_t will_retain) 765 | { 766 | uint32_t temp; 767 | temp = os_strlen(will_topic); 768 | mqttClient->connect_info.will_topic = (uint8_t*)os_zalloc(temp + 1); 769 | os_strcpy(mqttClient->connect_info.will_topic, will_topic); 770 | mqttClient->connect_info.will_topic[temp] = 0; 771 | 772 | temp = os_strlen(will_msg); 773 | mqttClient->connect_info.will_message = (uint8_t*)os_zalloc(temp + 1); 774 | os_strcpy(mqttClient->connect_info.will_message, will_msg); 775 | mqttClient->connect_info.will_message[temp] = 0; 776 | 777 | 778 | mqttClient->connect_info.will_qos = will_qos; 779 | mqttClient->connect_info.will_retain = will_retain; 780 | } 781 | /** 782 | * @brief Begin connect to MQTT broker 783 | * @param client: MQTT_Client reference 784 | * @retval None 785 | */ 786 | void ICACHE_FLASH_ATTR 787 | MQTT_Connect(MQTT_Client *mqttClient) 788 | { 789 | if (mqttClient->pCon) { 790 | // Clean up the old connection forcefully - using MQTT_Disconnect 791 | // does not actually release the old connection until the 792 | // disconnection callback is invoked. 793 | mqtt_tcpclient_delete(mqttClient); 794 | } 795 | mqttClient->pCon = (struct espconn *)os_zalloc(sizeof(struct espconn)); 796 | mqttClient->pCon->type = ESPCONN_TCP; 797 | mqttClient->pCon->state = ESPCONN_NONE; 798 | mqttClient->pCon->proto.tcp = (esp_tcp *)os_zalloc(sizeof(esp_tcp)); 799 | mqttClient->pCon->proto.tcp->local_port = espconn_port(); 800 | mqttClient->pCon->proto.tcp->remote_port = mqttClient->port; 801 | mqttClient->pCon->reverse = mqttClient; 802 | espconn_regist_connectcb(mqttClient->pCon, mqtt_tcpclient_connect_cb); 803 | espconn_regist_reconcb(mqttClient->pCon, mqtt_tcpclient_recon_cb); 804 | 805 | mqttClient->keepAliveTick = 0; 806 | mqttClient->reconnectTick = 0; 807 | 808 | 809 | os_timer_disarm(&mqttClient->mqttTimer); 810 | os_timer_setfn(&mqttClient->mqttTimer, (os_timer_func_t *)mqtt_timer, mqttClient); 811 | os_timer_arm(&mqttClient->mqttTimer, 1000, 1); 812 | 813 | if (UTILS_StrToIP(mqttClient->host, &mqttClient->pCon->proto.tcp->remote_ip)) { 814 | INFO("TCP: Connect to ip %s:%d\r\n", mqttClient->host, mqttClient->port); 815 | if (mqttClient->security) 816 | { 817 | #ifdef MQTT_SSL_ENABLE 818 | espconn_secure_connect(mqttClient->pCon); 819 | #else 820 | INFO("TCP: Do not support SSL\r\n"); 821 | #endif 822 | } 823 | else 824 | { 825 | espconn_connect(mqttClient->pCon); 826 | } 827 | } 828 | else { 829 | INFO("TCP: Connect to domain %s:%d\r\n", mqttClient->host, mqttClient->port); 830 | espconn_gethostbyname(mqttClient->pCon, mqttClient->host, &mqttClient->ip, mqtt_dns_found); 831 | } 832 | mqttClient->connState = TCP_CONNECTING; 833 | } 834 | 835 | void ICACHE_FLASH_ATTR 836 | MQTT_Disconnect(MQTT_Client *mqttClient) 837 | { 838 | mqttClient->connState = TCP_DISCONNECTING; 839 | system_os_post(MQTT_TASK_PRIO, 0, (os_param_t)mqttClient); 840 | os_timer_disarm(&mqttClient->mqttTimer); 841 | } 842 | 843 | void ICACHE_FLASH_ATTR 844 | MQTT_DeleteClient(MQTT_Client *mqttClient) 845 | { 846 | mqttClient->connState = MQTT_DELETING; 847 | system_os_post(MQTT_TASK_PRIO, 0, (os_param_t)mqttClient); 848 | os_timer_disarm(&mqttClient->mqttTimer); 849 | } 850 | 851 | void ICACHE_FLASH_ATTR 852 | MQTT_OnConnected(MQTT_Client *mqttClient, MqttCallback connectedCb) 853 | { 854 | mqttClient->connectedCb = connectedCb; 855 | } 856 | 857 | void ICACHE_FLASH_ATTR 858 | MQTT_OnDisconnected(MQTT_Client *mqttClient, MqttCallback disconnectedCb) 859 | { 860 | mqttClient->disconnectedCb = disconnectedCb; 861 | } 862 | 863 | void ICACHE_FLASH_ATTR 864 | MQTT_OnData(MQTT_Client *mqttClient, MqttDataCallback dataCb) 865 | { 866 | mqttClient->dataCb = dataCb; 867 | } 868 | 869 | void ICACHE_FLASH_ATTR 870 | MQTT_OnPublished(MQTT_Client *mqttClient, MqttCallback publishedCb) 871 | { 872 | mqttClient->publishedCb = publishedCb; 873 | } 874 | 875 | void ICACHE_FLASH_ATTR 876 | MQTT_OnTimeout(MQTT_Client *mqttClient, MqttCallback timeoutCb) 877 | { 878 | mqttClient->timeoutCb = timeoutCb; 879 | } 880 | -------------------------------------------------------------------------------- /aliyun_mqtt_app/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(mqtt_connection_t)); 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 | int blength = *length; 189 | *length = 0; 190 | 191 | for(i = 1; i < blength; ++i) 192 | { 193 | totlen += (buffer[i] & 0x7f) << (7 * (i - 1)); 194 | if((buffer[i] & 0x80) == 0) 195 | { 196 | ++i; 197 | break; 198 | } 199 | } 200 | totlen += i; 201 | 202 | if(i + 2 >= blength) 203 | return NULL; 204 | topiclen = buffer[i++] << 8; 205 | topiclen |= buffer[i++]; 206 | 207 | if(i + topiclen >= blength) 208 | return NULL; 209 | 210 | i += topiclen; 211 | 212 | if(mqtt_get_qos(buffer) > 0) 213 | { 214 | if(i + 2 >= blength) 215 | return NULL; 216 | i += 2; 217 | } 218 | 219 | if(totlen < i) 220 | return NULL; 221 | 222 | if(totlen <= blength) 223 | *length = totlen - i; 224 | else 225 | *length = blength - i; 226 | return (const char*)(buffer + i); 227 | } 228 | 229 | uint16_t ICACHE_FLASH_ATTR mqtt_get_id(uint8_t* buffer, uint16_t length) 230 | { 231 | if(length < 1) 232 | return 0; 233 | 234 | switch(mqtt_get_type(buffer)) 235 | { 236 | case MQTT_MSG_TYPE_PUBLISH: 237 | { 238 | int i; 239 | int topiclen; 240 | 241 | for(i = 1; i < length; ++i) 242 | { 243 | if((buffer[i] & 0x80) == 0) 244 | { 245 | ++i; 246 | break; 247 | } 248 | } 249 | 250 | if(i + 2 >= length) 251 | return 0; 252 | topiclen = buffer[i++] << 8; 253 | topiclen |= buffer[i++]; 254 | 255 | if(i + topiclen >= length) 256 | return 0; 257 | i += topiclen; 258 | 259 | if(mqtt_get_qos(buffer) > 0) 260 | { 261 | if(i + 2 >= length) 262 | return 0; 263 | //i += 2; 264 | } else { 265 | return 0; 266 | } 267 | 268 | return (buffer[i] << 8) | buffer[i + 1]; 269 | } 270 | case MQTT_MSG_TYPE_PUBACK: 271 | case MQTT_MSG_TYPE_PUBREC: 272 | case MQTT_MSG_TYPE_PUBREL: 273 | case MQTT_MSG_TYPE_PUBCOMP: 274 | case MQTT_MSG_TYPE_SUBACK: 275 | case MQTT_MSG_TYPE_UNSUBACK: 276 | case MQTT_MSG_TYPE_SUBSCRIBE: 277 | { 278 | // This requires the remaining length to be encoded in 1 byte, 279 | // which it should be. 280 | if(length >= 4 && (buffer[1] & 0x80) == 0) 281 | return (buffer[2] << 8) | buffer[3]; 282 | else 283 | return 0; 284 | } 285 | 286 | default: 287 | return 0; 288 | } 289 | } 290 | 291 | mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_connect(mqtt_connection_t* connection, mqtt_connect_info_t* info) 292 | { 293 | struct mqtt_connect_variable_header* variable_header; 294 | 295 | init_message(connection); 296 | 297 | if(connection->message.length + sizeof(*variable_header) > connection->buffer_length) 298 | return fail_message(connection); 299 | variable_header = (void*)(connection->buffer + connection->message.length); 300 | connection->message.length += sizeof(*variable_header); 301 | 302 | variable_header->lengthMsb = 0; 303 | #if defined(PROTOCOL_NAMEv31) 304 | variable_header->lengthLsb = 6; 305 | memcpy(variable_header->magic, "MQIsdp", 6); 306 | variable_header->version = 3; 307 | #elif defined(PROTOCOL_NAMEv311) 308 | variable_header->lengthLsb = 4; 309 | memcpy(variable_header->magic, "MQTT", 4); 310 | variable_header->version = 4; 311 | #else 312 | #error "Please define protocol name" 313 | #endif 314 | 315 | variable_header->flags = 0; 316 | variable_header->keepaliveMsb = info->keepalive >> 8; 317 | variable_header->keepaliveLsb = info->keepalive & 0xff; 318 | 319 | if(info->clean_session) 320 | variable_header->flags |= MQTT_CONNECT_FLAG_CLEAN_SESSION; 321 | 322 | if(info->client_id != NULL && info->client_id[0] != '\0') 323 | { 324 | if(append_string(connection, info->client_id, strlen(info->client_id)) < 0) 325 | return fail_message(connection); 326 | } 327 | else 328 | return fail_message(connection); 329 | 330 | if(info->will_topic != NULL && info->will_topic[0] != '\0') 331 | { 332 | if(append_string(connection, info->will_topic, strlen(info->will_topic)) < 0) 333 | return fail_message(connection); 334 | 335 | if(append_string(connection, info->will_message, strlen(info->will_message)) < 0) 336 | return fail_message(connection); 337 | 338 | variable_header->flags |= MQTT_CONNECT_FLAG_WILL; 339 | if(info->will_retain) 340 | variable_header->flags |= MQTT_CONNECT_FLAG_WILL_RETAIN; 341 | variable_header->flags |= (info->will_qos & 3) << 3; 342 | } 343 | 344 | if(info->username != NULL && info->username[0] != '\0') 345 | { 346 | if(append_string(connection, info->username, strlen(info->username)) < 0) 347 | return fail_message(connection); 348 | 349 | variable_header->flags |= MQTT_CONNECT_FLAG_USERNAME; 350 | } 351 | 352 | if(info->password != NULL && info->password[0] != '\0') 353 | { 354 | if(append_string(connection, info->password, strlen(info->password)) < 0) 355 | return fail_message(connection); 356 | 357 | variable_header->flags |= MQTT_CONNECT_FLAG_PASSWORD; 358 | } 359 | 360 | return fini_message(connection, MQTT_MSG_TYPE_CONNECT, 0, 0, 0); 361 | } 362 | 363 | 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) 364 | { 365 | init_message(connection); 366 | 367 | if(topic == NULL || topic[0] == '\0') 368 | return fail_message(connection); 369 | 370 | if(append_string(connection, topic, strlen(topic)) < 0) 371 | return fail_message(connection); 372 | 373 | if(qos > 0) 374 | { 375 | if((*message_id = append_message_id(connection, 0)) == 0) 376 | return fail_message(connection); 377 | } 378 | else 379 | *message_id = 0; 380 | 381 | if(connection->message.length + data_length > connection->buffer_length) 382 | return fail_message(connection); 383 | memcpy(connection->buffer + connection->message.length, data, data_length); 384 | connection->message.length += data_length; 385 | 386 | return fini_message(connection, MQTT_MSG_TYPE_PUBLISH, 0, qos, retain); 387 | } 388 | 389 | mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_puback(mqtt_connection_t* connection, uint16_t message_id) 390 | { 391 | init_message(connection); 392 | if(append_message_id(connection, message_id) == 0) 393 | return fail_message(connection); 394 | return fini_message(connection, MQTT_MSG_TYPE_PUBACK, 0, 0, 0); 395 | } 396 | 397 | mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_pubrec(mqtt_connection_t* connection, uint16_t message_id) 398 | { 399 | init_message(connection); 400 | if(append_message_id(connection, message_id) == 0) 401 | return fail_message(connection); 402 | return fini_message(connection, MQTT_MSG_TYPE_PUBREC, 0, 0, 0); 403 | } 404 | 405 | mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_pubrel(mqtt_connection_t* connection, uint16_t message_id) 406 | { 407 | init_message(connection); 408 | if(append_message_id(connection, message_id) == 0) 409 | return fail_message(connection); 410 | return fini_message(connection, MQTT_MSG_TYPE_PUBREL, 0, 1, 0); 411 | } 412 | 413 | mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_pubcomp(mqtt_connection_t* connection, uint16_t message_id) 414 | { 415 | init_message(connection); 416 | if(append_message_id(connection, message_id) == 0) 417 | return fail_message(connection); 418 | return fini_message(connection, MQTT_MSG_TYPE_PUBCOMP, 0, 0, 0); 419 | } 420 | 421 | mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_subscribe(mqtt_connection_t* connection, const char* topic, int qos, uint16_t* message_id) 422 | { 423 | init_message(connection); 424 | 425 | if(topic == NULL || topic[0] == '\0') 426 | return fail_message(connection); 427 | 428 | if((*message_id = append_message_id(connection, 0)) == 0) 429 | return fail_message(connection); 430 | 431 | if(append_string(connection, topic, strlen(topic)) < 0) 432 | return fail_message(connection); 433 | 434 | if(connection->message.length + 1 > connection->buffer_length) 435 | return fail_message(connection); 436 | connection->buffer[connection->message.length++] = qos; 437 | 438 | return fini_message(connection, MQTT_MSG_TYPE_SUBSCRIBE, 0, 1, 0); 439 | } 440 | 441 | mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_unsubscribe(mqtt_connection_t* connection, const char* topic, uint16_t* message_id) 442 | { 443 | init_message(connection); 444 | 445 | if(topic == NULL || topic[0] == '\0') 446 | return fail_message(connection); 447 | 448 | if((*message_id = append_message_id(connection, 0)) == 0) 449 | return fail_message(connection); 450 | 451 | if(append_string(connection, topic, strlen(topic)) < 0) 452 | return fail_message(connection); 453 | 454 | return fini_message(connection, MQTT_MSG_TYPE_UNSUBSCRIBE, 0, 1, 0); 455 | } 456 | 457 | mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_pingreq(mqtt_connection_t* connection) 458 | { 459 | init_message(connection); 460 | return fini_message(connection, MQTT_MSG_TYPE_PINGREQ, 0, 0, 0); 461 | } 462 | 463 | mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_pingresp(mqtt_connection_t* connection) 464 | { 465 | init_message(connection); 466 | return fini_message(connection, MQTT_MSG_TYPE_PINGRESP, 0, 0, 0); 467 | } 468 | 469 | mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_disconnect(mqtt_connection_t* connection) 470 | { 471 | init_message(connection); 472 | return fini_message(connection, MQTT_MSG_TYPE_DISCONNECT, 0, 0, 0); 473 | } 474 | -------------------------------------------------------------------------------- /aliyun_mqtt_app/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 | -------------------------------------------------------------------------------- /aliyun_mqtt_app/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 | -------------------------------------------------------------------------------- /aliyun_mqtt_app/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 | -------------------------------------------------------------------------------- /aliyun_mqtt_app/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 | -------------------------------------------------------------------------------- /aliyun_mqtt_app/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 | -------------------------------------------------------------------------------- /aliyun_mqtt_app/user/aliyun_mqtt.c: -------------------------------------------------------------------------------- 1 | /* 2 | * aliyun_mqtt.c 3 | */ 4 | 5 | #include "ets_sys.h" 6 | #include "osapi.h" 7 | #include "user_interface.h" 8 | #include "mem.h" 9 | 10 | #include "driver/uart.h" 11 | 12 | //#include "user_config.h" 13 | #include "aliyun_mqtt.h" 14 | 15 | #include "md5.h" 16 | 17 | /****************************************************************/ 18 | #define DEBUG 1 19 | 20 | #ifdef DEBUG 21 | #define debug(fmt, args...) os_printf(fmt, ##args) 22 | #define debugX(level, fmt, args...) if(DEBUG>=level) os_printf(fmt, ##args); 23 | #else 24 | #define debug(fmt, args...) 25 | #define debugX(level, fmt, args...) 26 | #endif /* DEBUG */ 27 | 28 | /****************************************************************/ 29 | // global variable 30 | s_mqtt g_aliyun_mqtt; 31 | 32 | /****************************************************************/ 33 | 34 | /* 35 | * function: gen_mqtt_password 36 | * parameter: u8 output_pass[] - 生成的密码 37 | * return: u16 - output_pass[]字符串长度 38 | * description: 生成阿里云的mqtt密码 39 | * 因为密码需要根据DEVICE_ID、DEVICE_NAME、PRODUCT_KEY和DEVICE_SECRET 40 | * 动态生成 41 | */ 42 | static u16 ICACHE_FLASH_ATTR 43 | gen_mqtt_password(u8 input_timestamp_3[], u8 output_pass[]) { 44 | 45 | #define HASH_STR "clientId"DEVICE_ID"deviceName"DEVICE_NAME"productKey"PRODUCT_KEY"timestamp%s" 46 | #define HASH_KEY DEVICE_SECRET 47 | 48 | int i; 49 | u8 temp[8]; 50 | u8 output[16]; 51 | u8 *p = output_pass; 52 | u8 *pStr = os_malloc(os_strlen(HASH_STR)+os_strlen(input_timestamp_3)); 53 | 54 | os_sprintf(pStr, HASH_STR, input_timestamp_3); 55 | debug("pStr:%s\r\n", pStr); 56 | 57 | HMAC_MD5(pStr, os_strlen(pStr), HASH_KEY, output); 58 | 59 | for (i = 0; i < 16; i++) { 60 | if (output[i] < 0x10) { 61 | os_memset(temp, 0, sizeof(temp)); 62 | os_sprintf(temp, "%d", 0); 63 | os_strcat(p, temp); 64 | } 65 | os_memset(temp, 0, sizeof(temp)); 66 | os_sprintf(temp, "%x", output[i]); 67 | os_strcat(p, temp); 68 | } 69 | debug("pass:%s\r\n", output_pass); 70 | 71 | os_free(pStr); 72 | 73 | return os_strlen(output_pass); 74 | } 75 | 76 | /* 77 | * function: aliyun_mqtt_init 78 | * 79 | */ 80 | void ICACHE_FLASH_ATTR 81 | aliyun_mqtt_init(void) { 82 | 83 | /* TODO: 84 | * 三种生成timestamp的方式,目前默认是写死在代码里。 85 | * - SNTP_TIMESTAMP:使用sntp生成,暂时未实现 86 | * - RAMDOM_TIMESTAMP:使用随机函数生成 87 | * - defalut:使用宏定义方式 88 | */ 89 | #ifdef SNTP_TIMESTAMP 90 | u8 *timestamp_str = TIMESTAMP_STR; 91 | #elif defined(RAMDOM_TIMESTAMP) 92 | u8 timestamp_str[4] = { 0 }; 93 | u32 number = os_random(); 94 | os_sprintf(timestamp_str, "%d", number % 1000); 95 | timestamp_str[3] = '\0'; 96 | #else 97 | u8 *timestamp_str = TIMESTAMP_STR; 98 | #endif 99 | 100 | debug("timestamp_str:%s\r\n", timestamp_str); 101 | 102 | // mqtt host 103 | os_strncpy(g_aliyun_mqtt.host, MQTT_HOST, BUF_SIZE); 104 | // mqtt port 105 | g_aliyun_mqtt.port = MQTT_PORT; 106 | // mqtt client id,拼接timestamp 107 | os_sprintf(g_aliyun_mqtt.client_id, MQTT_CLIENT_ID, timestamp_str); 108 | // mqtt username 109 | os_strncpy(g_aliyun_mqtt.username, MQTT_USERNAME, BUF_SIZE); 110 | // mqtt password 111 | gen_mqtt_password(timestamp_str, g_aliyun_mqtt.password); 112 | // mqtt keepalive 113 | g_aliyun_mqtt.keepalive = 120; 114 | 115 | debug("mqtt host:%s\r\n" 116 | "mqtt port:%d\r\n" 117 | "mqtt client id:%s\r\n" 118 | "mqtt username:%s\r\n" 119 | "mqtt password:%s\r\n", g_aliyun_mqtt.host, g_aliyun_mqtt.port, 120 | g_aliyun_mqtt.client_id, g_aliyun_mqtt.username, 121 | g_aliyun_mqtt.password); 122 | 123 | } 124 | 125 | /* 126 | * function: test_hmac_md5 127 | * description: hmacmd5测试,成功 128 | */ 129 | void ICACHE_FLASH_ATTR 130 | test_hmac_md5(void) { 131 | 132 | #define TEST_KEY "secret" 133 | #define TEST_MSG "clientId12345deviceNamedeviceproductKeypktimestamp789" 134 | 135 | int i; 136 | u8 output[16]; 137 | HMAC_MD5(TEST_MSG, os_strlen(TEST_MSG), TEST_KEY, output); 138 | /* It should be output: 14B198324FE55E1D3C88F2E705E201EE */ 139 | /* 对比 */ 140 | /* Digest: 14b198324fe55e1d3c88f2e705e201ee */ 141 | 142 | debug("Digest: "); 143 | for (i = 0; i < 16; i++) { 144 | if (output[i] < 0x10) { 145 | debug("%d", 0); 146 | } 147 | debug("%x", output[i]); 148 | } 149 | debug("\n"); 150 | 151 | } 152 | 153 | -------------------------------------------------------------------------------- /aliyun_mqtt_app/user/md5.c: -------------------------------------------------------------------------------- 1 | /* 2 | * filename: md5.c 3 | */ 4 | 5 | #include "ets_sys.h" 6 | #include "osapi.h" 7 | #include "mem.h" 8 | #include "user_interface.h" 9 | 10 | #define MEMCPY os_memcpy 11 | #define STRLEN os_strlen 12 | #define STRNCMP os_strncmp 13 | #define MEMCMP os_memcmp 14 | 15 | #define MEMSET os_memset 16 | #define STRNCPY os_strncpy 17 | #define MALLOC os_malloc 18 | #define FREE os_free 19 | 20 | #include "md5.h" 21 | 22 | //#define MD5_TEST 23 | 24 | /****************************************************************/ 25 | #define DEBUG 26 | 27 | #ifdef DEBUG 28 | #define debug(fmt, args...) os_printf(fmt, ##args) 29 | #define debugX(level, fmt, args...) if(DEBUG>=level) os_printf(fmt, ##args); 30 | #else 31 | #define debug(fmt, args...) 32 | #define debugX(level, fmt, args...) 33 | #endif /* DEBUG */ 34 | 35 | /****************************************************************/ 36 | 37 | unsigned char PADDING[] = { 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; 40 | 41 | void ICACHE_FLASH_ATTR 42 | MD5Init(MD5_CTX *context) { 43 | context->count[0] = 0; 44 | context->count[1] = 0; 45 | context->state[0] = 0x67452301; 46 | context->state[1] = 0xEFCDAB89; 47 | context->state[2] = 0x98BADCFE; 48 | context->state[3] = 0x10325476; 49 | } 50 | 51 | void ICACHE_FLASH_ATTR 52 | MD5Update(MD5_CTX *context, unsigned char *input, unsigned int inputlen) { 53 | unsigned int i = 0, index = 0, partlen = 0; 54 | index = (context->count[0] >> 3) & 0x3F; 55 | partlen = 64 - index; 56 | context->count[0] += inputlen << 3; 57 | if (context->count[0] < (inputlen << 3)) 58 | context->count[1]++; 59 | context->count[1] += inputlen >> 29; 60 | 61 | if (inputlen >= partlen) { 62 | MEMCPY(&context->buffer[index], input, partlen); 63 | MD5Transform(context->state, context->buffer); 64 | for (i = partlen; i + 64 <= inputlen; i += 64) 65 | MD5Transform(context->state, &input[i]); 66 | index = 0; 67 | } else { 68 | i = 0; 69 | } 70 | MEMCPY(&context->buffer[index], &input[i], inputlen - i); 71 | } 72 | 73 | void ICACHE_FLASH_ATTR 74 | MD5Final(MD5_CTX *context, unsigned char digest[16]) { 75 | unsigned int index = 0, padlen = 0; 76 | unsigned char bits[8]; 77 | index = (context->count[0] >> 3) & 0x3F; 78 | padlen = (index < 56) ? (56 - index) : (120 - index); 79 | MD5Encode(bits, context->count, 8); 80 | MD5Update(context, PADDING, padlen); 81 | MD5Update(context, bits, 8); 82 | MD5Encode(digest, context->state, 16); 83 | } 84 | void ICACHE_FLASH_ATTR 85 | MD5Encode(unsigned char *output, unsigned int *input, unsigned int len) { 86 | unsigned int i = 0, j = 0; 87 | while (j < len) { 88 | output[j] = input[i] & 0xFF; 89 | output[j + 1] = (input[i] >> 8) & 0xFF; 90 | output[j + 2] = (input[i] >> 16) & 0xFF; 91 | output[j + 3] = (input[i] >> 24) & 0xFF; 92 | i++; 93 | j += 4; 94 | } 95 | } 96 | void ICACHE_FLASH_ATTR 97 | MD5Decode(unsigned int *output, unsigned char *input, unsigned int len) { 98 | unsigned int i = 0, j = 0; 99 | while (j < len) { 100 | output[i] = (input[j]) | (input[j + 1] << 8) | (input[j + 2] << 16) 101 | | (input[j + 3] << 24); 102 | i++; 103 | j += 4; 104 | } 105 | } 106 | 107 | void ICACHE_FLASH_ATTR 108 | MD5Transform(unsigned int state[4], unsigned char block[64]) { 109 | unsigned int a = state[0]; 110 | unsigned int b = state[1]; 111 | unsigned int c = state[2]; 112 | unsigned int d = state[3]; 113 | unsigned int x[64]; 114 | MD5Decode(x, block, 64); 115 | FF(a, b, c, d, x[0], 7, 0xd76aa478); 116 | FF(d, a, b, c, x[1], 12, 0xe8c7b756); 117 | FF(c, d, a, b, x[2], 17, 0x242070db); 118 | FF(b, c, d, a, x[3], 22, 0xc1bdceee); 119 | FF(a, b, c, d, x[4], 7, 0xf57c0faf); 120 | FF(d, a, b, c, x[5], 12, 0x4787c62a); 121 | FF(c, d, a, b, x[6], 17, 0xa8304613); 122 | FF(b, c, d, a, x[7], 22, 0xfd469501); 123 | FF(a, b, c, d, x[8], 7, 0x698098d8); 124 | FF(d, a, b, c, x[9], 12, 0x8b44f7af); 125 | FF(c, d, a, b, x[10], 17, 0xffff5bb1); 126 | FF(b, c, d, a, x[11], 22, 0x895cd7be); 127 | FF(a, b, c, d, x[12], 7, 0x6b901122); 128 | FF(d, a, b, c, x[13], 12, 0xfd987193); 129 | FF(c, d, a, b, x[14], 17, 0xa679438e); 130 | FF(b, c, d, a, x[15], 22, 0x49b40821); 131 | 132 | GG(a, b, c, d, x[1], 5, 0xf61e2562); 133 | GG(d, a, b, c, x[6], 9, 0xc040b340); 134 | GG(c, d, a, b, x[11], 14, 0x265e5a51); 135 | GG(b, c, d, a, x[0], 20, 0xe9b6c7aa); 136 | GG(a, b, c, d, x[5], 5, 0xd62f105d); 137 | GG(d, a, b, c, x[10], 9, 0x2441453); 138 | GG(c, d, a, b, x[15], 14, 0xd8a1e681); 139 | GG(b, c, d, a, x[4], 20, 0xe7d3fbc8); 140 | GG(a, b, c, d, x[9], 5, 0x21e1cde6); 141 | GG(d, a, b, c, x[14], 9, 0xc33707d6); 142 | GG(c, d, a, b, x[3], 14, 0xf4d50d87); 143 | GG(b, c, d, a, x[8], 20, 0x455a14ed); 144 | GG(a, b, c, d, x[13], 5, 0xa9e3e905); 145 | GG(d, a, b, c, x[2], 9, 0xfcefa3f8); 146 | GG(c, d, a, b, x[7], 14, 0x676f02d9); 147 | GG(b, c, d, a, x[12], 20, 0x8d2a4c8a); 148 | 149 | HH(a, b, c, d, x[5], 4, 0xfffa3942); 150 | HH(d, a, b, c, x[8], 11, 0x8771f681); 151 | HH(c, d, a, b, x[11], 16, 0x6d9d6122); 152 | HH(b, c, d, a, x[14], 23, 0xfde5380c); 153 | HH(a, b, c, d, x[1], 4, 0xa4beea44); 154 | HH(d, a, b, c, x[4], 11, 0x4bdecfa9); 155 | HH(c, d, a, b, x[7], 16, 0xf6bb4b60); 156 | HH(b, c, d, a, x[10], 23, 0xbebfbc70); 157 | HH(a, b, c, d, x[13], 4, 0x289b7ec6); 158 | HH(d, a, b, c, x[0], 11, 0xeaa127fa); 159 | HH(c, d, a, b, x[3], 16, 0xd4ef3085); 160 | HH(b, c, d, a, x[6], 23, 0x4881d05); 161 | HH(a, b, c, d, x[9], 4, 0xd9d4d039); 162 | HH(d, a, b, c, x[12], 11, 0xe6db99e5); 163 | HH(c, d, a, b, x[15], 16, 0x1fa27cf8); 164 | HH(b, c, d, a, x[2], 23, 0xc4ac5665); 165 | 166 | II(a, b, c, d, x[0], 6, 0xf4292244); 167 | II(d, a, b, c, x[7], 10, 0x432aff97); 168 | II(c, d, a, b, x[14], 15, 0xab9423a7); 169 | II(b, c, d, a, x[5], 21, 0xfc93a039); 170 | II(a, b, c, d, x[12], 6, 0x655b59c3); 171 | II(d, a, b, c, x[3], 10, 0x8f0ccc92); 172 | II(c, d, a, b, x[10], 15, 0xffeff47d); 173 | II(b, c, d, a, x[1], 21, 0x85845dd1); 174 | II(a, b, c, d, x[8], 6, 0x6fa87e4f); 175 | II(d, a, b, c, x[15], 10, 0xfe2ce6e0); 176 | II(c, d, a, b, x[6], 15, 0xa3014314); 177 | II(b, c, d, a, x[13], 21, 0x4e0811a1); 178 | II(a, b, c, d, x[4], 6, 0xf7537e82); 179 | II(d, a, b, c, x[11], 10, 0xbd3af235); 180 | II(c, d, a, b, x[2], 15, 0x2ad7d2bb); 181 | II(b, c, d, a, x[9], 21, 0xeb86d391); 182 | state[0] += a; 183 | state[1] += b; 184 | state[2] += c; 185 | state[3] += d; 186 | } 187 | 188 | /* 189 | * function: MD5Digest 190 | * parameter: void const *strContent - 需要MD5的字符串 191 | * u16 iLength - 字符串长度 192 | * u8 output[16] - 输出 193 | * description: 生成MD5摘要 194 | */ 195 | void ICACHE_FLASH_ATTR 196 | MD5Digest(void const *strContent, u16 iLength, u8 output[16]) { 197 | u8 *q = (u8*) strContent; 198 | 199 | MD5_CTX md5; 200 | MD5Init(&md5); 201 | MD5Update(&md5, q, iLength); 202 | MD5Final(&md5, output); 203 | } 204 | 205 | /* 206 | * function: HMAC_MD5 207 | * parameter: u8 *inBuffer - 需要加密的字符串 208 | * u16 len - 字符串长度 209 | * u8 *ky - 初始密钥 210 | * u8 output[16] - 输出 211 | */ 212 | void ICACHE_FLASH_ATTR 213 | HMAC_MD5(u8 *inBuffer, u16 len, u8 *ky, u8 output[16]) { 214 | int i, j; 215 | 216 | u8 *tempBuffer = (u8 *) MALLOC(len + 64); //第一次HASH的参数 217 | u8 Buffer2[80]; //第二次HASH 218 | 219 | u8 key[64]; 220 | u8 ipad[64], opad[64]; 221 | 222 | MEMSET(key, 0, 64); 223 | 224 | if (os_strlen(ky) > 64) { 225 | MD5Digest(ky, STRLEN(ky), key); 226 | } else { 227 | STRNCPY(key, ky, 64); 228 | } 229 | 230 | for (i = 0; i < 64; i++) { 231 | ipad[i] = 0x36; 232 | opad[i] = 0x5c; 233 | } 234 | 235 | for (i = 0; i < 64; i++) { 236 | ipad[i] = key[i] ^ ipad[i]; //K ⊕ ipad 237 | opad[i] = key[i] ^ opad[i]; //K ⊕ opad 238 | } 239 | 240 | for (i = 0; i < 64; i++) { 241 | tempBuffer[i] = ipad[i]; 242 | } 243 | 244 | for (i = 64; i < len + 64; i++) { 245 | tempBuffer[i] = inBuffer[i - 64]; 246 | } 247 | 248 | MD5Digest(tempBuffer, len + 64, output); 249 | 250 | for (j = 0; j < 64; j++) { 251 | Buffer2[j] = opad[j]; 252 | } 253 | 254 | for (i = 64; i < 80; i++) { 255 | Buffer2[i] = output[i - 64]; 256 | } 257 | 258 | MD5Digest(Buffer2, 80, output); 259 | 260 | FREE(tempBuffer); 261 | } 262 | 263 | #ifdef MD5_TEST 264 | 265 | void ICACHE_FLASH_ATTR 266 | md5_test(void) { 267 | int i; 268 | u8 encrypt[] = "admin"; 269 | u8 decrypt[16]; 270 | 271 | MD5Digest(encrypt, STRLEN((char *) encrypt), decrypt); 272 | 273 | debug("md5 test\r\n"); 274 | debug("*********************************\r\n"); 275 | debug("before encrypt:%s\r\nafter encrypt 16bit:", encrypt); 276 | for (i = 4; i < 12; i++) { 277 | debug("%02x", decrypt[i]); // 7a57a5a743894a0e 278 | } 279 | 280 | debug("\r\nbefore encrypt:%s\r\nafter encrypt 32bit:", encrypt); 281 | for (i = 0; i < 16; i++) { 282 | debug("%02x", decrypt[i]); // 21232f297a57a5a743894a0e4a801fc3 283 | } 284 | debug("\r\n"); 285 | debug("*********************************\r\n"); 286 | 287 | debug("hmacmd5 test\r\n"); 288 | u8 output[16]; 289 | HMAC_MD5("", 0, "", output); // 74e6f7298a9c2d168935f58c001bad88 290 | debug("Digest: "); 291 | for (i = 0; i < 16; i++) { 292 | if (output[i] < 0x10) { 293 | debug("%d", 0); 294 | } 295 | debug("%x", output[i]); 296 | } 297 | debug("\n"); 298 | 299 | // b9092bfe47f21e2930a864b457f7c26d 300 | u8 *key = "key"; 301 | HMAC_MD5(encrypt, STRLEN((char *) encrypt), key, output); 302 | debug("Digest: "); 303 | for (i = 0; i < 16; i++) { 304 | if (output[i] < 0x10) { 305 | debug("%d", 0); 306 | } 307 | debug("%x", output[i]); 308 | } 309 | debug("\n"); 310 | 311 | // 超过16个字节的key 312 | // e5d88b25c472411491dced7d1f0e42d3 313 | u8 *key16 = "12345678901234567"; 314 | HMAC_MD5(encrypt, STRLEN((char *) encrypt), key16, output); 315 | debug("Digest 16: "); 316 | for (i = 0; i < 16; i++) { 317 | if (output[i] < 0x10) { 318 | debug("%d", 0); 319 | } 320 | debug("%x", output[i]); 321 | } 322 | debug("\n"); 323 | 324 | // 超过64个字节的key 325 | // 4a646bce9962a8953c4a88e9af844907 326 | u8 *key64 = "12345678901234567890123456789012345678901234567890123456789012345"; 327 | HMAC_MD5(encrypt, STRLEN((char *) encrypt), key64, output); 328 | debug("Digest 64: "); 329 | for (i = 0; i < 16; i++) { 330 | if (output[i] < 0x10) { 331 | debug("%d", 0); 332 | } 333 | debug("%x", output[i]); 334 | } 335 | debug("\n"); 336 | 337 | } 338 | 339 | #endif 340 | -------------------------------------------------------------------------------- /aliyun_mqtt_app/user/user_main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * user_main.c 3 | */ 4 | 5 | #include "ets_sys.h" 6 | #include "osapi.h" 7 | #include "gpio.h" 8 | #include "user_interface.h" 9 | #include "mem.h" 10 | #include "driver/uart.h" 11 | 12 | #include "mqtt/mqtt.h" 13 | #include "mqtt/debug.h" 14 | 15 | #include "user_config.h" 16 | #include "aliyun_mqtt.h" 17 | #include "user_wifi.h" 18 | 19 | //****************************************************************************/ 20 | // sdk v3.0.0 21 | 22 | #if ((SPI_FLASH_SIZE_MAP == 0) || (SPI_FLASH_SIZE_MAP == 1)) 23 | #error "The flash map is not supported" 24 | #elif (SPI_FLASH_SIZE_MAP == 2) 25 | #define SYSTEM_PARTITION_OTA_SIZE 0x6A000 26 | #define SYSTEM_PARTITION_OTA_2_ADDR 0x81000 27 | #define SYSTEM_PARTITION_RF_CAL_ADDR 0xfb000 28 | #define SYSTEM_PARTITION_PHY_DATA_ADDR 0xfc000 29 | #define SYSTEM_PARTITION_SYSTEM_PARAMETER_ADDR 0xfd000 30 | #define SYSTEM_PARTITION_CUSTOMER_PRIV_PARAM_ADDR 0x7c000 31 | #elif (SPI_FLASH_SIZE_MAP == 3) 32 | #define SYSTEM_PARTITION_OTA_SIZE 0x6A000 33 | #define SYSTEM_PARTITION_OTA_2_ADDR 0x81000 34 | #define SYSTEM_PARTITION_RF_CAL_ADDR 0x1fb000 35 | #define SYSTEM_PARTITION_PHY_DATA_ADDR 0x1fc000 36 | #define SYSTEM_PARTITION_SYSTEM_PARAMETER_ADDR 0x1fd000 37 | #define SYSTEM_PARTITION_CUSTOMER_PRIV_PARAM_ADDR 0x7c000 38 | #elif (SPI_FLASH_SIZE_MAP == 4) 39 | #define SYSTEM_PARTITION_OTA_SIZE 0x6A000 40 | #define SYSTEM_PARTITION_OTA_2_ADDR 0x81000 41 | #define SYSTEM_PARTITION_RF_CAL_ADDR 0x3fb000 42 | #define SYSTEM_PARTITION_PHY_DATA_ADDR 0x3fc000 43 | #define SYSTEM_PARTITION_SYSTEM_PARAMETER_ADDR 0x3fd000 44 | #define SYSTEM_PARTITION_CUSTOMER_PRIV_PARAM_ADDR 0x7c000 45 | #elif (SPI_FLASH_SIZE_MAP == 5) 46 | #define SYSTEM_PARTITION_OTA_SIZE 0x6A000 47 | #define SYSTEM_PARTITION_OTA_2_ADDR 0x101000 48 | #define SYSTEM_PARTITION_RF_CAL_ADDR 0x1fb000 49 | #define SYSTEM_PARTITION_PHY_DATA_ADDR 0x1fc000 50 | #define SYSTEM_PARTITION_SYSTEM_PARAMETER_ADDR 0x1fd000 51 | #define SYSTEM_PARTITION_CUSTOMER_PRIV_PARAM_ADDR 0xfc000 52 | #elif (SPI_FLASH_SIZE_MAP == 6) 53 | #define SYSTEM_PARTITION_OTA_SIZE 0x6A000 54 | #define SYSTEM_PARTITION_OTA_2_ADDR 0x101000 55 | #define SYSTEM_PARTITION_RF_CAL_ADDR 0x3fb000 56 | #define SYSTEM_PARTITION_PHY_DATA_ADDR 0x3fc000 57 | #define SYSTEM_PARTITION_SYSTEM_PARAMETER_ADDR 0x3fd000 58 | #define SYSTEM_PARTITION_CUSTOMER_PRIV_PARAM_ADDR 0xfc000 59 | #else 60 | #error "The flash map is not supported" 61 | #endif 62 | 63 | #define SYSTEM_PARTITION_CUSTOMER_PRIV_PARAM SYSTEM_PARTITION_CUSTOMER_BEGIN 64 | 65 | uint32 priv_param_start_sec; 66 | 67 | static const partition_item_t at_partition_table[] = { 68 | {SYSTEM_PARTITION_BOOTLOADER, 0x0, 0x1000}, 69 | {SYSTEM_PARTITION_OTA_1, 0x1000, SYSTEM_PARTITION_OTA_SIZE}, 70 | {SYSTEM_PARTITION_OTA_2, SYSTEM_PARTITION_OTA_2_ADDR, SYSTEM_PARTITION_OTA_SIZE}, 71 | {SYSTEM_PARTITION_RF_CAL, SYSTEM_PARTITION_RF_CAL_ADDR, 0x1000}, 72 | {SYSTEM_PARTITION_PHY_DATA, SYSTEM_PARTITION_PHY_DATA_ADDR, 0x1000}, 73 | {SYSTEM_PARTITION_SYSTEM_PARAMETER, SYSTEM_PARTITION_SYSTEM_PARAMETER_ADDR, 0x3000}, 74 | {SYSTEM_PARTITION_CUSTOMER_PRIV_PARAM, SYSTEM_PARTITION_CUSTOMER_PRIV_PARAM_ADDR, 0x1000}, 75 | }; 76 | 77 | void ICACHE_FLASH_ATTR user_pre_init(void) 78 | { 79 | if (!system_partition_table_regist( 80 | at_partition_table, 81 | sizeof(at_partition_table) / sizeof(at_partition_table[0]), 82 | SPI_FLASH_SIZE_MAP)) 83 | { 84 | os_printf("system_partition_table_regist fail\r\n"); 85 | while (1) 86 | ; 87 | } 88 | } 89 | 90 | //****************************************************************************/ 91 | 92 | MQTT_Client mqttClient; 93 | 94 | // topic 95 | #define BASE_TOPIC "/" PRODUCT_KEY "/" DEVICE_NAME 96 | #define GET_TOPIC BASE_TOPIC "/get" 97 | #define UPDATE_TOPIC BASE_TOPIC "/update" 98 | 99 | /*****************************************************************************/ 100 | // 以下是esp8266例程里的mqtt示例,只改动了小部分。 101 | void wifiConnectCb(uint8_t status) 102 | { 103 | if (status == STATION_GOT_IP) 104 | { 105 | MQTT_Connect(&mqttClient); 106 | } 107 | else 108 | { 109 | MQTT_Disconnect(&mqttClient); 110 | } 111 | } 112 | 113 | void mqttConnectedCb(uint32_t *args) 114 | { 115 | MQTT_Client *client = (MQTT_Client *)args; 116 | INFO("MQTT: Connected\r\n"); 117 | 118 | MQTT_Subscribe(client, GET_TOPIC, 0); 119 | 120 | /* 121 | * MQTT_Publish函数参数说明 122 | * @param client: MQTT_Client reference 123 | * @param topic: string topic will publish to 124 | * @param data: buffer data send point to 125 | * @param data_length: length of data 126 | * @param qos: qos 127 | * @param retain: retain 128 | */ 129 | MQTT_Publish(client, UPDATE_TOPIC, "hello", 6, 0, 0); 130 | } 131 | 132 | void mqttDisconnectedCb(uint32_t *args) 133 | { 134 | MQTT_Client *client = (MQTT_Client *)args; 135 | INFO("MQTT: Disconnected\r\n"); 136 | } 137 | 138 | void mqttPublishedCb(uint32_t *args) 139 | { 140 | MQTT_Client *client = (MQTT_Client *)args; 141 | INFO("MQTT: Published\r\n"); 142 | } 143 | 144 | void mqttDataCb(uint32_t *args, const char *topic, uint32_t topic_len, 145 | const char *data, uint32_t data_len) 146 | { 147 | char *topicBuf = (char *)os_zalloc(topic_len + 1), *dataBuf = 148 | (char *)os_zalloc(data_len + 1); 149 | 150 | MQTT_Client *client = (MQTT_Client *)args; 151 | 152 | os_memcpy(topicBuf, topic, topic_len); 153 | topicBuf[topic_len] = 0; 154 | 155 | os_memcpy(dataBuf, data, data_len); 156 | dataBuf[data_len] = 0; 157 | 158 | INFO("Receive topic: %s, data: %s \r\n", topicBuf, dataBuf); 159 | os_free(topicBuf); 160 | os_free(dataBuf); 161 | } 162 | 163 | /****************************************************************************** 164 | * FunctionName : user_rf_cal_sector_set 165 | * Description : SDK just reversed 4 sectors, used for rf init data and paramters. 166 | * We add this function to force users to set rf cal sector, since 167 | * we don't know which sector is free in user's application. 168 | * sector map for last several sectors : ABCCC 169 | * A : rf cal 170 | * B : rf init data 171 | * C : sdk parameters 172 | * Parameters : none 173 | * Returns : rf cal sector 174 | *******************************************************************************/ 175 | uint32 ICACHE_FLASH_ATTR 176 | user_rf_cal_sector_set(void) 177 | { 178 | enum flash_size_map size_map = system_get_flash_size_map(); 179 | uint32 rf_cal_sec = 0; 180 | 181 | switch (size_map) 182 | { 183 | case FLASH_SIZE_4M_MAP_256_256: 184 | rf_cal_sec = 128 - 5; 185 | break; 186 | 187 | case FLASH_SIZE_8M_MAP_512_512: 188 | rf_cal_sec = 256 - 5; 189 | break; 190 | 191 | case FLASH_SIZE_16M_MAP_512_512: 192 | case FLASH_SIZE_16M_MAP_1024_1024: 193 | rf_cal_sec = 512 - 5; 194 | break; 195 | 196 | case FLASH_SIZE_32M_MAP_512_512: 197 | case FLASH_SIZE_32M_MAP_1024_1024: 198 | rf_cal_sec = 1024 - 5; 199 | break; 200 | 201 | default: 202 | rf_cal_sec = 0; 203 | break; 204 | } 205 | 206 | return rf_cal_sec; 207 | } 208 | 209 | /*****************************************************************************/ 210 | 211 | void user_init(void) 212 | { 213 | uart_init(BIT_RATE_74880, BIT_RATE_74880); 214 | //uart_init(BIT_RATE_115200, BIT_RATE_115200); 215 | 216 | // 测试 hmacmd5 生成mqtt passwrod 217 | //test_hmac_md5(); 218 | 219 | aliyun_mqtt_init(); 220 | 221 | //MQTT_InitConnection(&mqttClient, "192.168.11.122", 1880, 0); 222 | MQTT_InitConnection(&mqttClient, g_aliyun_mqtt.host, g_aliyun_mqtt.port, 0); 223 | 224 | //MQTT_InitClient(&mqttClient, "client_id", "user", "pass", 120, 1); 225 | MQTT_InitClient(&mqttClient, g_aliyun_mqtt.client_id, g_aliyun_mqtt.username, 226 | g_aliyun_mqtt.password, g_aliyun_mqtt.keepalive, 1); 227 | 228 | // 遗愿消息 229 | // 阿里云mqtt不需要设置遗愿消息 230 | //MQTT_InitLWT(&mqttClient, "/lwt", "offline", 0, 0); 231 | 232 | // 设置mqtt的回调函数 233 | MQTT_OnConnected(&mqttClient, mqttConnectedCb); 234 | MQTT_OnDisconnected(&mqttClient, mqttDisconnectedCb); 235 | MQTT_OnPublished(&mqttClient, mqttPublishedCb); 236 | MQTT_OnData(&mqttClient, mqttDataCb); 237 | 238 | // 连接wifi 239 | wifi_connect(wifiConnectCb); 240 | 241 | INFO("\r\nSystem started ...\r\n"); 242 | } 243 | -------------------------------------------------------------------------------- /aliyun_mqtt_app/user/user_wifi.c: -------------------------------------------------------------------------------- 1 | /* 2 | * user_wifi.c 3 | */ 4 | 5 | #include "user_interface.h" 6 | #include "osapi.h" 7 | #include "espconn.h" 8 | #include "os_type.h" 9 | #include "mem.h" 10 | 11 | #include "user_wifi.h" 12 | 13 | //*****************************************************************************/ 14 | 15 | // 如果不需要debug,则注释下面的语句 16 | #define DEBUG 1 17 | 18 | // 如果连接成功,每隔2s检查一次wifi状态 19 | #define WIFI_CHECK_TIMER_INTERVAL (2*1000) 20 | // 如果连接失败,每500ms检测一次 21 | #define WIFI_CLOSE_CHECK_TIMER_INTERVAL (500) 22 | 23 | //*****************************************************************************/ 24 | // debug 25 | #define PR os_printf 26 | 27 | #ifdef DEBUG 28 | #define debug(fmt, args...) PR(fmt, ##args) 29 | #define debugX(level, fmt, args...) if(DEBUG>=level) PR(fmt, ##args); 30 | #else 31 | #define debug(fmt, args...) 32 | #define debugX(level, fmt, args...) 33 | #endif /* DEBUG */ 34 | 35 | //*****************************************************************************/ 36 | // gloabl variable 37 | static os_timer_t g_wifi_check_timer; 38 | 39 | 40 | 41 | // 用户wifi回调函数 42 | WifiCallback wifiCb = NULL; 43 | // 记录wifi状态 44 | static u8 wifiStatus = STATION_IDLE, lastWifiStatus = STATION_IDLE; 45 | 46 | //*****************************************************************************/ 47 | /* 48 | * function: wifi_handle_event_cb 49 | * description: wifi事件处理回调函数,由esp8266自动触发 50 | */ 51 | static void ICACHE_FLASH_ATTR 52 | wifi_handle_event_cb(System_Event_t *evt) { 53 | // 下面是官方示例代码 54 | // 但是,我们不需要这些代码来检查wifi状态 55 | #if 0 56 | debug("event %x\n", evt->event); 57 | switch (evt->event) { 58 | case EVENT_STAMODE_CONNECTED: 59 | debug("connect to ssid %s, channel %d\n", 60 | evt->event_info.connected.ssid, 61 | evt->event_info.connected.channel); 62 | break; 63 | case EVENT_STAMODE_DISCONNECTED: 64 | debug("disconnect from ssid %s, reason %d\n", 65 | evt->event_info.disconnected.ssid, 66 | evt->event_info.disconnected.reason); 67 | break; 68 | case EVENT_STAMODE_AUTHMODE_CHANGE: 69 | debug("mode: %d -> %d\n", evt->event_info.auth_change.old_mode, 70 | evt->event_info.auth_change.new_mode); 71 | break; 72 | case EVENT_STAMODE_GOT_IP: 73 | debug("ip:" IPSTR ",mask:" IPSTR ",gw:" IPSTR, 74 | IP2STR(&evt->event_info.got_ip.ip), 75 | IP2STR(&evt->event_info.got_ip.mask), 76 | IP2STR(&evt->event_info.got_ip.gw)); 77 | debug("\n"); 78 | break; 79 | case EVENT_SOFTAPMODE_STACONNECTED: 80 | debug("station: " MACSTR "join, AID = %d\n", 81 | MAC2STR(evt->event_info.sta_connected.mac), 82 | evt->event_info.sta_connected.aid); 83 | break; 84 | case EVENT_SOFTAPMODE_STADISCONNECTED: 85 | debug("station: " MACSTR "leave, AID = %d\n", 86 | MAC2STR(evt->event_info.sta_disconnected.mac), 87 | evt->event_info.sta_disconnected.aid); 88 | break; 89 | default: 90 | break; 91 | } 92 | #endif 93 | } 94 | 95 | //*****************************************************************************/ 96 | // 有关wifi定时检查的函数 97 | 98 | /* 99 | * function: wifi_check_timer_cb 100 | * description: wiif检查回调函数 101 | * wiif连接成功时每 2s 检查一次 102 | * wiif断开时每 500ms 检查一次 103 | */ 104 | static void ICACHE_FLASH_ATTR 105 | wifi_check_timer_cb(void) { 106 | struct ip_info ipConfig; 107 | 108 | wifi_get_ip_info(STATION_IF, &ipConfig); 109 | wifiStatus = wifi_station_get_connect_status(); 110 | 111 | if (wifiStatus == STATION_GOT_IP && ipConfig.ip.addr != 0) { 112 | // 重新初始化 wifi 检查定时器 113 | wifi_check_init(WIFI_CHECK_TIMER_INTERVAL); 114 | 115 | } else { // wifi断开 116 | debug("wifi connect fail!\r\n"); 117 | // 重新初始化 wifi 检查定时器 118 | wifi_check_init(WIFI_CLOSE_CHECK_TIMER_INTERVAL); 119 | //wifi_station_disconnect(); 120 | //wifi_station_connect(); // 尝试重连 121 | } 122 | 123 | // user callback 124 | if (wifiStatus != lastWifiStatus) { 125 | lastWifiStatus = wifiStatus; 126 | if (wifiCb) { 127 | wifiCb(wifiStatus); 128 | } 129 | } 130 | } 131 | 132 | /* 133 | * function: wifi_check_init 134 | * parameter: u16 interval - 定时回调时间 135 | * description: wifi检查初始化 136 | */ 137 | void ICACHE_FLASH_ATTR 138 | wifi_check_init(u16 interval) { 139 | /* 140 | * 如果调用 wifi_station_set_reconnect_policy 关闭重连功能, 141 | * 且未调用 wifi_set_event_handler_cb 注册 Wi-Fi 事件回调, 142 | * 则 wifi_station_get_connect_status 接口失效,无法准确获得连接状态。 143 | */ 144 | 145 | // 设置 ESP8266 Station 连接 AP 失败或断开后是否重连。 146 | wifi_station_set_reconnect_policy(TRUE); 147 | wifi_set_event_handler_cb(wifi_handle_event_cb); 148 | 149 | os_timer_disarm(&g_wifi_check_timer); 150 | os_timer_setfn(&g_wifi_check_timer, (os_timer_func_t *) wifi_check_timer_cb, NULL); 151 | os_timer_arm(&g_wifi_check_timer, interval, 0); 152 | } 153 | 154 | //*****************************************************************************/ 155 | 156 | /* 157 | * function: user_set_station_config 158 | * parameter: u8* ssid - WiFi SSID 159 | * u8 password - WiFi password 160 | * return: void 161 | * description: 设置wifi信息 162 | */ 163 | void ICACHE_FLASH_ATTR 164 | user_set_station_config(u8* ssid, u8* password) { 165 | struct station_config stationConf; 166 | stationConf.bssid_set = 0; //need not check MAC address of AP 167 | os_memcpy(&stationConf.ssid, ssid, 32); 168 | os_memcpy(&stationConf.password, password, 64); 169 | wifi_station_set_config(&stationConf); 170 | } 171 | 172 | 173 | //*****************************************************************************/ 174 | // 下面是主要对外的接口函数 175 | 176 | /* 177 | * function: wifi_connect 178 | * parameter: WifiCallback cb - wifi回调函数 179 | * return: void 180 | * description: 连接wifi,需要传递一个回调函数 181 | */ 182 | void ICACHE_FLASH_ATTR 183 | wifi_connect(WifiCallback cb) { 184 | wifi_set_opmode(STATION_MODE); // set wifi mode 185 | wifiCb = cb; // wifi callback 186 | 187 | // 上电是否自动连接 188 | // TRUE - 执行完 user_init 函数后则自动连接 189 | wifi_station_set_auto_connect(TRUE); 190 | 191 | user_set_station_config(WIFI_SSID, WIFI_PASS); 192 | wifi_station_disconnect(); 193 | wifi_station_connect(); 194 | 195 | // wifi timer check 196 | wifi_check_init(WIFI_CHECK_TIMER_INTERVAL); 197 | 198 | } 199 | 200 | -------------------------------------------------------------------------------- /screenshot/build_success.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AngelLiang/esp8266_aliyun_mqtt_app/df6dce586e2ac0db5fe0fa027dc8125cb1deea10/screenshot/build_success.png -------------------------------------------------------------------------------- /screenshot/mqtt_connect_success.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AngelLiang/esp8266_aliyun_mqtt_app/df6dce586e2ac0db5fe0fa027dc8125cb1deea10/screenshot/mqtt_connect_success.png -------------------------------------------------------------------------------- /screenshot/project_list.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AngelLiang/esp8266_aliyun_mqtt_app/df6dce586e2ac0db5fe0fa027dc8125cb1deea10/screenshot/project_list.png -------------------------------------------------------------------------------- /screenshot/topic_get_helloworld.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AngelLiang/esp8266_aliyun_mqtt_app/df6dce586e2ac0db5fe0fa027dc8125cb1deea10/screenshot/topic_get_helloworld.png --------------------------------------------------------------------------------