基于物联网的智能开关系统设计

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

基于stm32的物联网WiFi智能家居控制系统(含电路图+源代码+系统资料)

基于ZigBee设计的物联网LED控制系统