0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內(nèi)不再提示

項目分享|基于ELF 1開發(fā)板的MQTT遠程溫濕度監(jiān)測系統(tǒng)

ElfBoard ? 2024-04-26 09:54 ? 次閱讀

今天非常榮幸向各位小伙伴詳細展示一個由共創(chuàng)社成員完成的MQTT遠程溫濕度監(jiān)控系統(tǒng)項目。該項目借助ELF 1開發(fā)板作為核心技術支撐,成功實現(xiàn)了對各類環(huán)境空間中溫濕度數(shù)據(jù)的實時、遠程、穩(wěn)定監(jiān)測。該系統(tǒng)不僅集成了先進的數(shù)據(jù)采集模塊,用于精確感知現(xiàn)場環(huán)境變化,同時利用MQTT協(xié)議的輕量級特性,確保了數(shù)據(jù)在復雜網(wǎng)絡環(huán)境下的可靠傳輸。在此接下來,就為各位小伙伴詳盡展示這一項目的相關細節(jié)。

1、Linux開發(fā)板開發(fā)環(huán)境搭建

(1)開發(fā)板動態(tài)分配ip地址

(開發(fā)板與家用路由器連接,路由器支持DHCP自動IP地址分配)

root@ELF1:~# udhcpc -i eth0

wKgZomYrABiAL5FMAAD4aceXtZc667.png

(2)將nfs服務器掛載到開發(fā)板的/mnt目錄

(其中“192.168.1.10”是Ubuntu的ens36的ip)

root@ELF1:~# mount -t nfs -o nolock,vers=3 192.168.1.10:/home/book/nfs_rootfs /mnt

wKgZomYrAEeARo1OAACjstu0MMc843.png

可以看到開發(fā)板的/mnt目錄已經(jīng)有了文件。

2、Ubuntu編譯環(huán)境搭建:

(1)將paho mqtt的官方庫克隆到Ubuntu的“~/nfs_rootfs”路徑

book@100ask:~/nfs_rootfs$ git clone https://github.com/eclipse/paho.mqtt.c.git

(2)修改“~/nfs_rootfs/paho_mqtt/paho.mqtt.c”路徑下的Makefile文件

wKgaomYrAH2ARc4LAAI3XHXO5U4881.png

修改prefix所代表的工具鏈路徑:

wKgaomYrAImAKsMsAABDGqaG_Yo240.png

修改編譯器:

wKgZomYrAMuAXkLTAABqJSDRCjI959.png

(3)編譯后得到鏈接庫

book@100ask:~/nfs_rootfs/paho_mqtt/paho.mqtt.c$ make

arm-gcc編譯生成的.so庫文件,保存在paho.mqtt.c/build/output里面。

將.so庫文件安裝到本地PC:

book@100ask:~/nfs_rootfs/paho_mqtt/paho.mqtt.c$ sudo make install

(4)將.so庫文件安裝到開發(fā)板的“/lib”路徑,開發(fā)板才能運行paho mqtt編譯后的可執(zhí)行文件

root@ELF1:~# install /mnt/paho_mqtt/paho.mqtt.c/build/output/libpaho-mqtt3* /lib

以上開發(fā)環(huán)境搭建完成!

3、工程文件的建立

(1)將“~/nfs_rootfs/paho_mqtt/paho.mqtt.c”

路徑中的src文件夾拷貝到“~/nfs_rootfs/mqtt_iot”路徑下

book@100ask:~$ cp -r ~/nfs_rootfs/paho_mqtt/paho.mqtt.c ~/nfs_rootfs/mqtt_iot

(2)在“~/nfs_rootfs/mqtt_iot”路徑下添加文件:

wKgZomYrAJqAZRDVAADUJjIvdQg640.png

4、阿里云服務器設置:

(1)服務器的注冊及產(chǎn)品、設備設置可以參照ElfBoard官方文檔:《01-1 ELF1、ELF1S開發(fā)板_軟件教程_V1》第5章-5.4小節(jié)。

(2)工程文件中所需要的服務器參數(shù)查找

查看服務器地址

wKgaomYrAUKAE9kLAACdn25W2ow817.png

查看DeviceName、DeviceSecret

wKgZomYrAUKAD6CFAAD8FOKLADA186.png

查看MQTT連接參數(shù)

wKgZomYrAUOAKv9VAAENTNejk3o069.png

5.工程文件的編譯執(zhí)行

(1)編譯工程文件,得到可在Linux開發(fā)板上執(zhí)行的Main二進制文件

book@100ask:~/nfs_rootfs/mqtt_iot$ arm-buildroot-linux-gnueabihf-gcc main.c mqtt_iot.c -o main -lpaho-mqtt3c -lpthread

MQTT的異步通信收發(fā),依賴的庫是libpaho-mqtt3a,MQTT的同步通信收發(fā),依賴的庫就是libpaho-mqtt3c。此外工程編譯的時候需要鏈接線程的庫pthread,所以編譯的時候要加上-lpthread。

(2)開發(fā)板運行程序

root@ELF1:/mnt/mqtt_iot# ./main

(3)實驗結果

Linux開發(fā)板將采集到的溫度、濕度數(shù)據(jù)每5s上傳一次阿里服務器,串口窗口顯示數(shù)據(jù)發(fā)送成功字符。此外通過阿里服務器日志服務可以看到濕度、溫度數(shù)據(jù)。

wKgZomYrAaqASiKBAAICBtwiVjM910.pngwKgaomYrAaqAe9CMAAFOAY5XFMU291.png

通過阿里服務器調試窗口給開發(fā)板發(fā)送LED1、LED2控制指令。

wKgZomYrAaqAFxCkAAEUD_6woBA592.pngwKgZomYrAcaALfm-AAGP2LpxajM518.png

6、下面將貼出工程文件的代碼,并介紹其思路

(1)main.c文件

//main.c //定義線程句柄 pthread_t discon_t; pthread_t thread_AT20Read_t; pthread_t thread_ledctrl_t; static int isConnected = 0;//表明客戶端和服務器是斷開還是連接狀態(tài)(1-連接狀態(tài),-1斷開狀態(tài)) static void *thread_AT20Read(void *paramater) { int fd = -1; unsigned int databuf[2]; int c1,t1; float hum,temp; int ret = 0; msgbuf pubMsg = {2, 0}; while(fd < 0){ fd = open(AHT20_DEV, O_RDWR); if(fd < 0){ printf("can't open file %s\r\n", AHT20_DEV); sleep(1); }else{ printf("open file %s successfully\r\n", AHT20_DEV); } } while(1){ ret = read(fd, databuf, sizeof(databuf)); if(ret == 0){ c1 = databuf[0]*1000/1024/1024; t1 = databuf[1] *200*10/1024/1024-500; hum = (float)c1/10.0; temp = (float)t1/10.0; //printf("hum = %0.2f temp = %0.2f \r\n",hum,temp); pubMsg.mtext[0] = (unsigned int)(hum*100); pubMsg.mtext[1] = (unsigned int)(temp*100); int ret1 = msgsnd(pubmsg_d, &pubMsg.mtype, sizeof(pubMsg.mtext), IPC_NOWAIT); // 非阻塞發(fā)送 if(ret1 != 0) { printf("Failed to send message.\r\n"); } } sleep(5); } } static void *thread_ledctrl(void *paramater) { int on=1; int led; int fd; msgbuf subMsg = {1, 0}; fd = open(LED_BRIGHTNESS, O_WRONLY); if(fd < 0) { perror("open device leds"); exit(1); } system(LED1_OFF); system(LED2_OFF); while(1) { int res = msgrcv(submsg_d, &subMsg, sizeof(subMsg.mtext), 0, 0);//阻塞 if(res < 0) continue; else{ if((subMsg.mtext[0] & 0x01)== 1){ system(LED1_ON); }else{ system(LED1_OFF); } if((subMsg.mtext[0] & 0x02)== 0x02){ system(LED2_ON); }else{ system(LED2_OFF); } } } } //斷開和mqtt服務器連接的線程入口函數(shù) static void *mqtt_disconnect_t(void* argv) { int retval; while(1) { char ch; ch = getchar(); if(ch=='Q' || ch=='q') { printf("Try to exit mqtt task\n"); if(mqtt_disconnect() == EXIT_SUCCESS) break; } } isConnected = -1; pthread_exit(&retval); // 退出線程 return NULL; } int main(void) { //初始化mqtt成功建立客戶端和服務器的連接后,將主動斷開服務器的任務放到一個線程里面去 //成功建立客戶端和服務器的連接且訂閱主題后才創(chuàng)建斷開連接的線程 if(mqtt_iot() == 0) { isConnected = 1; pthread_create(&discon_t, 0, mqtt_disconnect_t, NULL); } //AT20 read thread int ret = pthread_create(&thread_AT20Read_t, NULL, thread_AT20Read, NULL); if(ret != 0) { printf("Failed to create AT20Read thread.\n"); return -1; } //led control thread ret = pthread_create(&thread_ledctrl_t, NULL, thread_ledctrl, NULL); if(ret != 0) { printf("Failed to create ledctrl thread.\n"); return -1; } while(1) { //printf("isConnected state:%d\n",isConnected); sleep(5); } return 0; }

(2)mqtt_iot.c文件

//mqtt_iot.c volatile MQTTClient_deliveryToken deliveredtoken; pthread_t threads[2]; sem_t discon_sem;//信號量 int pubmsg_d = -1; int submsg_d = -1; msgbuf subMsg = {1, 0}; msgbuf pubMsg = {2, 0}; pthread_t thread_mqtt_publish_t; MQTTClient client; //定義一個MQTT客戶端client MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer; //傳遞給MQTTClient_setCallbacks的回調函數(shù),消息發(fā)送成功后,調用此回調函數(shù) void delivered(void *context, MQTTClient_deliveryToken dt) { printf("Message with token value %d delivery confirmed\n", dt); deliveredtoken = dt; } //傳遞給MQTT-Client_setCallbacks的回調函數(shù) 消息到達后,調用此回調函數(shù) int msgarrvd(void *context, char *topicName, int topicLen, MQTTClient_message *message) { printf("---------------------------------------------------------------\n"); printf("Message arrived\n"); printf(" topic: %s\n", topicName); printf(" message: %.*s\n", message->payloadlen, (char*)message->payload); printf("---------------------------------------------------------------\n"); subMsg.mtext[0] = 0; unsigned short len = message->payloadlen; char *buf = (char*)message->payload; for(unsigned short i=0; i='0') subMsg.mtext[0] = subMsg.mtext[0]*10 + buf[i] - '0'; } int ret = msgsnd(submsg_d, &subMsg.mtype, sizeof(subMsg.mtext), IPC_NOWAIT); // 非阻塞發(fā)送 if(ret != 0) { printf("Failed to send message.\r\n"); } MQTTClient_freeMessage(&message); // 釋放消息 MQTTClient_free(topicName); // 釋放主題名 return 1; } //傳遞給MQTTClient_setCallbacks的回調函數(shù) 連接異常斷開后調用此回調函數(shù) void connlost(void *context, char *cause) { printf("\nConnection lost\n"); printf(" cause: %s\n", cause); } //實現(xiàn)MQTT的發(fā)布 void *mqtt_publish(void *argv) { MQTTClient_message pubmsg = MQTTClient_message_initializer; MQTTClient_deliveryToken token; char data[9]; int rc; pubmsg.qos = QOS; pubmsg.retained = 0; while(1) { //接收消息(消息隊列的ID,存放消息的指針,指定接收消息的大小,0-讀取消息隊列中第一個數(shù)據(jù),阻塞) int res = msgrcv(pubmsg_d, &pubMsg, sizeof(pubMsg.mtext), 0, 0); if(res < 0) continue; { //printf("Publish_hum: %d\n", pubMsg.mtext[0]); //printf("Publish_temp: %d\n", pubMsg.mtext[1]); sprintf(data, "%d,%d", pubMsg.mtext[0],pubMsg.mtext[1]); pubmsg.payload = data; pubmsg.payloadlen = sizeof(data); if((rc = MQTTClient_publishMessage(client, PUB_TOPIC, &pubmsg, &token)) != MQTTCLIENT_SUCCESS) { printf("Failed to publish message, return code %d\n", rc); break; } rc = MQTTClient_waitForCompletion(client, token, TIMEOUT); printf("Message with delivery token %d delivered\n", token); } } if((rc = MQTTClient_disconnect(client, 10000)) != MQTTCLIENT_SUCCESS) //斷開和服務器的連接 { printf("Failed to disconnect, return code %d\n", rc); } pthread_exit(&threads[PubThread]); return NULL; } //封裝主動斷開連接服務器的函數(shù) int mqtt_disconnect(void) { int rc = EXIT_SUCCESS; //兩個參數(shù):MQTT客戶端和斷開連接超時時間 if ((rc = MQTTClient_disconnect(client, 10000)) != MQTTCLIENT_SUCCESS) //斷開和服務器的連接 { printf("Failed to disconnect, return code %d\n", rc); rc = EXIT_FAILURE; } else { printf("MQTT disconnect success\n"); MQTTClient_destroy(&client); } return rc; } // mqtt建立客戶端、連接服務器、訂閱主題的封裝入口函數(shù) int mqtt_iot(void) { int rc = EXIT_SUCCESS; //創(chuàng)建客戶端 if ((rc = MQTTClient_create(&client, ADDRESS, CLIENTID, MQTTCLIENT_PERSISTENCE_NONE, NULL)) != MQTTCLIENT_SUCCESS) { printf("Failed to create client, return code %d\n", rc); goto exit; } //設置回調函數(shù)(連接丟失處理回調函數(shù),處理訂閱消息的回調函數(shù),成功發(fā)布消息后的回調函數(shù)) if((rc = MQTTClient_setCallbacks(client, NULL, connlost, msgarrvd, delivered)) != MQTTCLIENT_SUCCESS) { printf("Failed to set callbacks, return code %d\n", rc); goto destroy_exit; } conn_opts.username = USERNAME; conn_opts.password = PASSWORD; conn_opts.keepAliveInterval = 60;//?;钪芷冢蛻舳讼蚍掌靼l(fā)送心跳包的周期,單位秒 conn_opts.cleansession = 1; //連接服務器 if((rc = MQTTClient_connect(client, &conn_opts)) != MQTTCLIENT_SUCCESS) { printf("Failed to connect, return code %d\n", rc); goto destroy_exit; } //訂閱主題(傳入客戶端句柄、訂閱的主題以及消息質量) if ((rc = MQTTClient_subscribe(client, SUB_TOPIC, QOS)) != MQTTCLIENT_SUCCESS) { printf("Failed to subscribe, return code %d\n", rc); goto destroy_exit; } //初始化信號量 if(sem_init(&discon_sem, 1, 0) != 0) { printf("Failed to init semaphore\n"); return -1; } //創(chuàng)建隊列 pubmsg_d = msgget(0x1234, IPC_CREAT); submsg_d = msgget(0x5678, IPC_CREAT); if(pubmsg_d == -1 || submsg_d==-1) //返回錯誤碼-1 { printf("Failed to create a mqtt message, pubid:%d, subid:%d\n", pubmsg_d, submsg_d); return -1; } else { printf("Publish message id: %d\n", pubmsg_d); printf("Subscribe message id: %d\n", submsg_d); } int ret = pthread_create(&thread_mqtt_publish_t, NULL, mqtt_publish, NULL); if(ret != 0) { printf("Failed to create mqtt_publish thread.\n"); return -1; } printf("MQTT connect success, press 'Q' or 'q' to disconnect mqtt server\n"); return 0; destroy_exit: MQTTClient_destroy(&client); //釋放客戶端的資源, 參數(shù)-同步客戶端的句柄 return -1; exit: return -1; }

至此,就完成了關于ELF 1開發(fā)板研發(fā)的MQTT遠程溫濕度監(jiān)測系統(tǒng)介紹。希望這套實踐案例能夠成為各位小伙伴的寶貴參考,啟迪創(chuàng)新思維,推進各位嵌入式愛好者在學習的道路上不斷前進。

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權轉載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學習之用,如有內(nèi)容侵權或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 嵌入式
    +關注

    關注

    5045

    文章

    18816

    瀏覽量

    298459
  • 監(jiān)測系統(tǒng)

    關注

    8

    文章

    2612

    瀏覽量

    81078
  • 開發(fā)板
    +關注

    關注

    25

    文章

    4771

    瀏覽量

    96158
收藏 人收藏

    評論

    相關推薦

    【小e開發(fā)板申請】基于WIFI的家庭溫濕度情況播報系統(tǒng)

    的智能家居系統(tǒng),包括家庭溫濕度,報警,洗衣機,冰箱,空調等等連接在一起的一個智能居住環(huán)境。項目描述:初步方案:開發(fā)板作為一個終端,進行溫濕度
    發(fā)表于 12-22 11:57

    基于單片機的遠程溫濕度監(jiān)測系統(tǒng)。(有報酬)

    基于單片機的遠程溫濕度監(jiān)測系統(tǒng)。單片機監(jiān)測溫濕度,在LCD上面顯示出來。用zigbee再把溫濕度
    發(fā)表于 05-14 16:26

    【鈦極小龜試用申請】鈦極小龜云環(huán)境監(jiān)測溫濕度遠程調控實驗

    項目名稱:鈦極小龜云環(huán)境監(jiān)測溫濕度遠程調控實驗試用計劃:本人從事多年軟件開發(fā)工作, 擅長Java,Android程序
    發(fā)表于 11-13 17:09

    鴻蒙軟、硬件綜合案例——農(nóng)業(yè)大棚溫濕度監(jiān)測控制系統(tǒng)

    農(nóng)業(yè)大棚溫濕度監(jiān)測控制系統(tǒng),包括三部分:鴻蒙手表應用端:實時顯示土壤濕度、空氣溫濕度,可控制風扇與水泵華為云ECS:提供MQTT服務Hi38
    發(fā)表于 12-11 10:01

    庫房無線溫濕度監(jiān)控方案 無線溫濕度監(jiān)控系統(tǒng) 倉儲物流無線溫濕度

    數(shù)據(jù)的實時顯示、曲線顯示、數(shù)據(jù)存儲等功能。 四、無線溫濕度監(jiān)控拓撲圖 五 系統(tǒng)功能 、特點1系統(tǒng)軟件功能:通過監(jiān)測軟件實現(xiàn)對
    發(fā)表于 03-01 10:15

    NUC980開發(fā)板DIY項目大挑戰(zhàn)合集

    開發(fā)板,采用Rt-Thread系統(tǒng)搭建平臺,測定環(huán)境的溫濕度。工程框圖:以下為本項目的總體框圖。原作者:Cainhu、weizheng110
    發(fā)表于 06-08 14:32

    【天啟教育M1開發(fā)板試用體驗】MQTT溫濕度

    【目的】建立一個溫濕度計,并通過MQTT上傳到服務器1、連接wifi:2、設置mqtt服務器連接信息:3、連接成功后,獲取溫濕度,并上傳給服
    發(fā)表于 09-15 09:44

    ELF 1開發(fā)板試用】+傳感器檢測

    ELF 1開發(fā)板通過幾種傳感器的測試,如溫濕度、六軸傳感器等,而在配備功能擴展板的情況下,還能進行光照強度的檢測。 溫濕度檢測
    發(fā)表于 11-29 11:59

    ELF 1開發(fā)板試用】板載資源測試4:體驗溫濕度傳感器

    飛凌嵌入式ELF1開發(fā)板(以下簡稱為“開發(fā)板”)將溫濕度傳感器器AHT20集成在了底板上,此次依舊做最基礎的測試,以下是測試過程記錄。一、實驗名稱E
    發(fā)表于 12-18 11:09

    基于 LabVIEW 的溫濕度監(jiān)測系統(tǒng)設計與實現(xiàn)

    基于LabVIEW的溫濕度監(jiān)測系統(tǒng)123456
    發(fā)表于 11-24 16:59 ?60次下載

    基于手機短信的設施農(nóng)業(yè)溫濕度遠程監(jiān)測系統(tǒng)的設計

    基于手機短信的設施農(nóng)業(yè)溫濕度遠程監(jiān)測系統(tǒng)的設計
    發(fā)表于 01-04 15:02 ?0次下載

    GPRS和3G通信的糧倉溫濕度遠程監(jiān)測系統(tǒng)

    為了解決現(xiàn)有糧倉溫濕度監(jiān)測系統(tǒng)存在的自動化程度低、性價比較低、傳輸距離受限等問題,本文設計了一種基于GPRS 和 3G 通信的糧倉溫濕度遠程
    發(fā)表于 04-24 10:56 ?7次下載
    GPRS和3G通信的糧倉<b class='flag-5'>溫濕度</b><b class='flag-5'>遠程</b><b class='flag-5'>監(jiān)測</b><b class='flag-5'>系統(tǒng)</b>

    【天啟教育M1開發(fā)板試用體驗】MQTT溫濕度

    ? 本文來源電子發(fā)燒友社區(qū),作者:劉建華, 帖子地址: https://bbs.elecfans.com/jishu_2305668_1_1.html 【目的】建立一個溫濕度計,并通過MQTT上傳
    的頭像 發(fā)表于 10-17 11:31 ?648次閱讀
    【天啟教育M<b class='flag-5'>1</b><b class='flag-5'>開發(fā)板</b>試用體驗】<b class='flag-5'>MQTT</b><b class='flag-5'>溫濕度</b>計

    溫濕度遠程監(jiān)控系統(tǒng)概述

    中易云溫濕度監(jiān)控系統(tǒng)專為溫濕度監(jiān)控設計,使用各種物聯(lián)網(wǎng)溫濕度監(jiān)控硬件及云平臺,在檢測環(huán)境溫濕度數(shù)據(jù)的同時,還可以
    的頭像 發(fā)表于 12-16 15:36 ?2988次閱讀

    項目分享|基于ELF 1開發(fā)板遠程監(jiān)測及人臉識別項目

    今天非常榮幸地向各位小伙伴分享一個由共創(chuàng)社成員完成的遠程監(jiān)測及人臉識別項目,該項目依托ELF1開發(fā)板
    的頭像 發(fā)表于 03-13 16:41 ?419次閱讀
    <b class='flag-5'>項目</b>分享|基于<b class='flag-5'>ELF</b> <b class='flag-5'>1</b><b class='flag-5'>開發(fā)板</b>的<b class='flag-5'>遠程</b><b class='flag-5'>監(jiān)測</b>及人臉識別<b class='flag-5'>項目</b>