基于物联网的智能开关系统设计
Posted llingfeng
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于物联网的智能开关系统设计相关的知识,希望对你有一定的参考价值。
记录一下,自己的第一个项目,虽然很简单,但也了解了关于MQTT的部分知识。
这是APP的界面
这是物联网的界面,用的是百度云,之前用阿里云上传数据没成功。
app的教程是根据B站一位大佬学的:https://www.bilibili.com/video/BV1G7411t7zs
讲的挺好的,零基础,我一点java都不会也能听懂。
至于百度云的使用方法就是看文档了,(虽然很烦)
下面是ESP8266的核心代码
/* main.c -- MQTT client example * * Copyright (c) 2014-2015, Tuan PM <tuanpm at live dot com> * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of Redis nor the names of its contributors may be used * to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // // 工程: MQTT_Data-Visualization // 注:在《MQTT_JX》例程上修改 // // // // // 平台: 物联网开发板 ESP8266 V1.0 // ①:按照创建【物影子】时获取到的MQTT连接参数,修改<mqtt_config.h> // // // // // 功能: ①:设置【物影子】MQTT相关参数 // ②:将<dht11.c>添加到<modules>,将<dht11.h>添加到<include/modules> // // // // // ②:ESP8266接入百度云【物影子】 // ③:需注意,<dht11.c>中,须改为<#include modules/dht11.h> // // // // // ③:每5秒向【物影子】上报【温湿度数据】 // ④:在<mqtt.c>定时函数中,添加:每5秒向【物影子】上报【温湿度数据】 // // // // // 版本: V1.0 // ⑤:取消【订阅"SW_LED"】【向"SW_LED"发布消息】操作 // // // ⑥:led_flag :0代表继电器关,1代表继电器开 // ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // 头文件 //============================== #include "ets_sys.h" #include "driver/uart.h" #include "osapi.h" #include "mqtt.h" #include "wifi.h" #include "config.h" #include "debug.h" #include "gpio.h" #include "user_interface.h" #include "user_config.h" #include "mem.h" #include "sntp.h" //添加,iic LED头文件 #include "driver/oled.h" // OLED #include "c_types.h" // 变量类型 #include "eagle_soc.h" // GPIO函数、宏定义 #include "modules/dht11.h" // DHT11 #include "dht11.h" // DHT11 //============================== // 类型定义 //================================= typedef unsigned long u32_t; //================================= // 全局变量 //============================================================================ MQTT_Client mqttClient; // MQTT客户端_结构体【此变量非常重要】 static ETSTimer sntp_timer; // SNTP定时器 char *dataBuf="{"SW_LED":1}"; //传入数据所对应的字符串 char *topicBuf=NULL; //topic所对应的字符串 char led_flag = 0;//表示灯的状态,灯灭 //============================================================================ os_timer_t OS_Timer_1; // 软件定时器 // 定时的回调函数 //========================================================================================== void ICACHE_FLASH_ATTR OS_Timer_1_cb(void) { if(DHT11_Read_Data_Complete() == 0) // 读取DHT11温湿度值,读取成功才能显示值 { // OLED显示温湿度 //--------------------------------------------------------------------------------- DHT11_NUM_Char(); // DHT11数据值转成字符串 OLED_ShowString(0,2,DHT11_Data_Char[0]); // DHT11_Data_Char[0] == 【湿度字符串】 OLED_ShowString(0,6,DHT11_Data_Char[1]); // DHT11_Data_Char[1] == 【温度字符串】 } } // 软件定时器初始化(ms毫秒) //========================================================================================== void ICACHE_FLASH_ATTR OS_Timer_1_Init_JX(u32 time_ms, u8 time_repetitive) { os_timer_disarm(&OS_Timer_1); // 关闭定时器 os_timer_setfn(&OS_Timer_1,(os_timer_func_t *)OS_Timer_1_cb, NULL); // 设置定时器 os_timer_arm(&OS_Timer_1, time_ms, time_repetitive); // 使能定时器 } //========================================================================================== // 毫秒延时函数 //=========================================== void ICACHE_FLASH_ATTR delay_ms(u32 C_time) { for(;C_time>0;C_time--) os_delay_us(1000); } //=========================================== // SNTP定时函数:获取当前网络时间 //============================================================================ void sntpfn() { u32_t ts = 0; ts = sntp_get_current_timestamp(); // 获取当前的偏移时间 os_printf("current time : %s ", sntp_get_real_time(ts)); // 获取真实时间 if (ts == 0) // 网络时间获取失败 { os_printf("did not get a valid time from sntp server "); } else //(ts != 0) // 网络时间获取成功 { os_timer_disarm(&sntp_timer); // 关闭SNTP定时器 MQTT_Connect(&mqttClient); // 开始MQTT连接 } } //============================================================================ // WIFI连接状态改变:参数 = wifiStatus //============================================================================ void wifiConnectCb(uint8_t status) { // 成功获取到IP地址 //--------------------------------------------------------------------- if(status == STATION_GOT_IP) { ip_addr_t * addr = (ip_addr_t *)os_zalloc(sizeof(ip_addr_t)); // 在官方例程的基础上,增加2个备用服务器 //--------------------------------------------------------------- sntp_setservername(0, "us.pool.ntp.org"); // 服务器_0【域名】 sntp_setservername(1, "ntp.sjtu.edu.cn"); // 服务器_1【域名】 ipaddr_aton("210.72.145.44", addr); // 点分十进制 => 32位二进制 sntp_setserver(2, addr); // 服务器_2【IP地址】 os_free(addr); // 释放addr sntp_init(); // SNTP初始化 // 设置SNTP定时器[sntp_timer] //----------------------------------------------------------- os_timer_disarm(&sntp_timer); os_timer_setfn(&sntp_timer, (os_timer_func_t *)sntpfn, NULL); os_timer_arm(&sntp_timer, 1000, 1); // 1s定时 } // IP地址获取失败 //---------------------------------------------------------------- else { MQTT_Disconnect(&mqttClient); // WIFI连接出错,TCP断开连接 } } //============================================================================ // MQTT已成功连接:ESP8266发送【CONNECT】,并接收到【CONNACK】 //============================================================================ void mqttConnectedCb(uint32_t *args) { MQTT_Client* client = (MQTT_Client*)args; // 获取mqttClient指针 INFO("MQTT: Connected "); // 【参数2:主题过滤器 / 参数3:订阅Qos】 //----------------------------------------------------------------- MQTT_Subscribe(client, "$baidu/iot/general/a", 0); // 订阅主题"SW_LED",QoS=0 // MQTT_Subscribe(client, "SW_LED", 1); // MQTT_Subscribe(client, "SW_LED", 2); // 【参数2:主题名 / 参数3:发布消息的有效载荷 / 参数4:有效载荷长度 / 参数5:发布Qos / 参数6:Retain】 //----------------------------------------------------------------------------------------------------------------------------------------- // MQTT_Publish(client, "SW_LED", "ESP8266_Online", strlen("ESP8266_Online"), 0, 0); // 向主题"SW_LED"发布"ESP8266_Online",Qos=0、retain=0 // MQTT_Publish(client, "SW_LED", "ESP8266_Online", strlen("ESP8266_Online"), 1, 0); // MQTT_Publish(client, "SW_LED", "ESP8266_Online", strlen("ESP8266_Online"), 2, 0); } //============================================================================ // MQTT成功断开连接 //============================================================================ void mqttDisconnectedCb(uint32_t *args) { MQTT_Client* client = (MQTT_Client*)args; INFO("MQTT: Disconnected "); } //============================================================================ // MQTT成功发布消息 //============================================================================ void mqttPublishedCb(uint32_t *args) { MQTT_Client* client = (MQTT_Client*)args; INFO("MQTT: Published "); } //============================================================================ // 【接收MQTT的[PUBLISH]数据】函数 【参数1:主题 / 参数2:主题长度 / 参数3:有效载荷 / 参数4:有效载荷长度】 //=============================================================================================================== void mqttDataCb(uint32_t *args, const char* topic, uint32_t topic_len, const char *data, uint32_t data_len) { topicBuf = (char*)os_zalloc(topic_len+1); // 申请【主题】空间 dataBuf = (char*)os_zalloc(data_len+1); // 申请【有效载荷】空间 //dataBuf是从topic订阅而来的消息,通过与{"SW_LED":1}对比去控制继电器的状态 MQTT_Client* client = (MQTT_Client*)args; // 获取MQTT_Client指针 os_memcpy(topicBuf, topic, topic_len); // 缓存主题 topicBuf[topic_len] = 0; // 最后添‘ ‘ os_memcpy(dataBuf, data, data_len); // 缓存有效载荷 dataBuf[data_len] = 0; // 最后添‘ ‘ INFO("Receive topic: %s, data: %s ", topicBuf, dataBuf); // 串口打印【主题】【有效载荷】 //######################################################################################## //注释掉的原因:无法在串口打印出来 // 【参数2:主题名 / 参数3:发布消息的有效载荷 / 参数4:有效载荷长度 / 参数5:发布Qos / 参数6:Retain】 //MQTT_Publish(client, "$baidu/iot/shadow/TH_ESP8266/update", dataBuf, strlen(dataBuf), 0, 0);// 向主题"$baidu/iot/general/a"发布"dataBuf",Qos=0、retain=0 //os_printf(" ------ Shadow_Report_Data:%s -- ",dataBuf); // 上报到物影子的数据 //os_printf("Report_Data_Length:%d ------ ",strlen(dataBuf)); // 上报数据长度 //######################################################################################## // 根据接收到的主题名/有效载荷,控制LED的亮/灭 //----------------------------------------------------------------------------------- if( os_strcmp(topicBuf,"$baidu/iot/general/a") == 0 ) { if( os_strcmp(dataBuf,"{"SW_LED":1}") == 0 ) // 有效载荷 == "SW_LED:1" { GPIO_OUTPUT_SET(GPIO_ID_PIN(4),0); // LED灭 led_flag = 0; } else if( os_strcmp(dataBuf,"{"SW_LED":0}") == 0 ) // 有效载荷 == "SW_LED;0" { GPIO_OUTPUT_SET(GPIO_ID_PIN(4),1); // LED亮 led_flag = 1; } } //######################################################################################## //必须释放后,才能再次赋值 os_free(topicBuf); // 释放【主题】空间 os_free(dataBuf); // 释放【有效载荷】空间 } //=============================================================================================================== /****************************************************************************** * FunctionName : user_rf_cal_sector_set * Description : SDK只是反转了4个扇区,用于rf init数据和参数。 * 我们增加这个功能是为了迫使用户设置rf cal扇区,因为 * 我们不知道用户的应用中哪个扇区是免费的。 * 最后几个扇区的扇区图 : ABCCC * A : rf cal * B : rf init data * C : sdk parameters * Parameters参数 : none * Returns 返回值 : rf cal sector *******************************************************************************/ uint32 ICACHE_FLASH_ATTR user_rf_cal_sector_set(void) { enum flash_size_map size_map = system_get_flash_size_map(); uint32 rf_cal_sec = 0; switch (size_map) { case FLASH_SIZE_4M_MAP_256_256: rf_cal_sec = 128 - 5; break; case FLASH_SIZE_8M_MAP_512_512: rf_cal_sec = 256 - 5; break; case FLASH_SIZE_16M_MAP_512_512: case FLASH_SIZE_16M_MAP_1024_1024: rf_cal_sec = 512 - 5; break; case FLASH_SIZE_32M_MAP_512_512: case FLASH_SIZE_32M_MAP_1024_1024: rf_cal_sec = 1024 - 5; break; case FLASH_SIZE_64M_MAP_1024_1024: rf_cal_sec = 2048 - 5; break; case FLASH_SIZE_128M_MAP_1024_1024: rf_cal_sec = 4096 - 5; break; default: rf_cal_sec = 0; break; } return rf_cal_sec; } // user_init:进入用户应用程序,在这里初始化用户函数 //=================================================================================================================== void user_init(void) { uart_init(BIT_RATE_115200, BIT_RATE_115200); // 串口波特率设为115200 os_delay_us(60000); //########################################################################### PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO4_U, FUNC_GPIO4); // GPIO4输出高 # GPIO_OUTPUT_SET(GPIO_ID_PIN(4),1); // LED初始化 # //########################################################################### CFG_Load(); // 加载/更新系统参数【WIFI参数、MQTT参数】 // 网络连接参数赋值:服务端域名【mqtt_test_jx.mqtt.iot.gz.baidubce.com】、网络连接端口【1883】、安全类型【0:NO_TLS】 //------------------------------------------------------------------------------------------------------------------- MQTT_InitConnection(&mqttClient, sysCfg.mqtt_host, sysCfg.mqtt_port, sysCfg.security); // MQTT连接参数赋值:客户端标识符【..】、MQTT用户名【..】、MQTT密钥【..】、保持连接时长【120s】、清除会话【1:clean_session】 //---------------------------------------------------------------------------------------------------------------------------- MQTT_InitClient(&mqttClient, sysCfg.device_id, sysCfg.mqtt_user, sysCfg.mqtt_pass, sysCfg.mqtt_keepalive, 1); // 设置遗嘱参数(如果云端没有对应的遗嘱主题,则MQTT连接会被拒绝) //-------------------------------------------------------------- // MQTT_InitLWT(&mqttClient, "Will", "ESP8266_offline", 0, 0); // 设置MQTT相关函数 //-------------------------------------------------------------------------------------------------- MQTT_OnConnected(&mqttClient, mqttConnectedCb); // 设置【MQTT成功连接】函数的另一种调用方式 MQTT_OnDisconnected(&mqttClient, mqttDisconnectedCb); // 设置【MQTT成功断开】函数的另一种调用方式 MQTT_OnPublished(&mqttClient, mqttPublishedCb); // 设置【MQTT成功发布】函数的另一种调用方式 MQTT_OnData(&mqttClient, mqttDataCb); // 设置【接收MQTT数据】函数的另一种调用方式 // 连接WIFI:SSID[..]、PASSWORD[..]、WIFI连接成功函数[wifiConnectCb] //-------------------------------------------------------------------------- WIFI_Connect(sysCfg.sta_ssid, sysCfg.sta_pwd, wifiConnectCb); // OLED显示初始化 //-------------------------------------------------------- OLED_Init(); // OLED初始化 OLED_ShowString(0,0,"Humidity:"); // 湿度 OLED_ShowString(0,4,"Temperature:"); // 温度 //-------------------------------------------------------- OS_Timer_1_Init_JX(3000,1); // 3秒定时(重复) INFO(" System started ... "); } //===================================================================================================================
其他代码我会尽快上传的,另外topic的订阅和发布必须得非常熟悉。
建议购买【技小新】的物联网开发板学习,但只能作为入门,虽然我也才入门.......
物联网开发板的购买链接:https://detail.tmall.com/item.htm?spm=a230r.1.14.16.353165e9rELAwD&id=621916769804&ns=1&abbucket=12(类似于这种40多块的,可以到技小新旗舰店看看)
以上是关于基于物联网的智能开关系统设计的主要内容,如果未能解决你的问题,请参考以下文章
#yyds干货盘点# 基于STM32+ESP8266+华为云设计的智能家居控制系统
毕业设计:基于单片机的智能鱼缸系统设计与实现 - 嵌入式 物联网 stm32 51单片机 智能鱼缸
基于STM32设计物联网在线智能称重系统(OneNet)_2022
基于STM32设计物联网在线智能称重系统(OneNet)_2022