基於物聯網的智能開關系統設計


記錄一下,自己的第一個項目,雖然很簡單,但也了解了關於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\n", sntp_get_real_time(ts));    // 獲取真實時間

    if (ts == 0)        // 網絡時間獲取失敗
    {
        os_printf("did not get a valid time from sntp server\n");
    }
    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\r\n");

    // 【參數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\r\n");
}
//============================================================================

// MQTT成功發布消息
//============================================================================
void mqttPublishedCb(uint32_t *args)
{
    MQTT_Client* client = (MQTT_Client*)args;
    INFO("MQTT: Published\r\n");
}
//============================================================================

// 【接收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;                // 最后添'\0'

    os_memcpy(dataBuf, data, data_len);        // 緩存有效載荷
    dataBuf[data_len] = 0;                    // 最后添'\0'

    INFO("Receive topic: %s, data: %s \r\n", 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("\r\n------ Shadow_Report_Data:%s -- ",dataBuf);            // 上報到物影子的數據
    //os_printf("Report_Data_Length:%d ------\r\n\r\n",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("\r\nSystem started ...\r\n");
}
//===================================================================================================================

其他代碼我會盡快上傳的,另外這個項目需要對topic的訂閱和發布必須得非常熟悉。

建議購買【技小新】的物聯網開發板學習,但只能作為入門,雖然我也才入門.......

注意:SDK要使用技小新視頻里面的版本,如果找不到視頻中的版本,可以輸入視頻中的網址。

物聯網開發板的購買鏈接:https://item.taobao.com/item.htm?spm=a1z09.2.0.0.15e92e8deWtUFD&id=623696943330&_u=c2d1kccp1c25或者https://detail.tmall.com/item.htm?spm=a230r.1.14.16.2e2b1de7koSLxu&id=603272487818&ns=1&abbucket=12(類似於這種40多塊的,可以到技小新旗艦店看看)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM