STM32+W5500+MQTT+Android實現遠程數據採集及控制

2020-12-13 電子工程世界網

0 前言

最近在學習MQTT,發現MQTT還是挺好用的,於是花了點時間做了一個簡單的應用示例,希望能給需要做這方面的人一些參考。
相關背景知識:http://www.embed-net.com/thread-224-1-1.html
具體功能為:
1,STM32F405為主控晶片,它通過傳感器採集環境數據,比如溫度,溼度,光照度,大氣壓強等;
2,主控晶片通過W5500模塊將測量的數據通過MQTT協議方式發布到MQTT伺服器(伺服器域名和IP見固件程序);
3,主控訂閱LED燈控制的消息,當接收到對應的控制指令後點亮或者熄滅對應的LED燈;
4,安卓手機端訂閱傳感器數據的消息,當接收到消息後將傳感器數據在界面顯示;
5,安卓手機可發送點亮或者熄滅LED燈的指令到伺服器,然後伺服器會將該指令轉發給STM32主控,然後STM32主控解析該指令並執行指令。

1 單片機端實現
MQTT協議是基於TCP的協議,所以我們只需要在單片機端實現TCP客戶端代碼之後就很容易移植MQTT了,STM32F4+W5500實現TCP客戶端的代碼我們以前已經實現過,代碼下載地址為:
http://www.embed-net.com/thread-87-1-1.html
當然,如果你想在代碼裡面直接使用伺服器域名方式進行連接,我們還得在TCP客戶端代碼裡面集成DNS的代碼,當然在上面這個連接裡面也有相關的代碼。
MQTT代碼源碼下載地址:
http://www.eclipse.org/paho/
在STM32這邊我們使用的是C/C++ MQTT Embedded clients代碼。
硬體連接如下圖所示:

1.1 MQTT的移植
MQTT的移植非常簡單,將C/C++ MQTT Embedded clients的代碼添加到工程中,然後我們只需要再次封裝4個函數即可:

int transport_sendPacketBuffer(unsigned char* buf, int buflen);
int transport_getdata(unsigned char* buf, int count);
int transport_open(void);
int transport_close(void);

transport_sendPacketBuffer:通過網絡以TCP的方式發送數據;
transport_getdata:TCP方式從伺服器端讀取數據,該函數目前屬於阻塞函數;
transport_open:打開一個網絡接口,其實就是和伺服器建立一個TCP連接;
transport_close:關閉網絡接口。
如果已經移植好了socket方式的TCP客戶端的程序,那麼這幾個函數的封裝也是非常簡單的,程序代碼如下所示:


int transport_sendPacketBuffer(unsigned char* buf, int buflen)
{
return send(SOCK_TCPS,buf,buflen);
}

int transport_getdata(unsigned char* buf, int count)
{
return recv(SOCK_TCPS,buf,count);
}


int transport_open(void)
{
int32_t ret;
//新建一個Socket並綁定本地埠5000
ret = socket(SOCK_TCPS,Sn_MR_TCP,5000,0×00);
if(ret != SOCK_TCPS){
printf(「%d:Socket Error」,SOCK_TCPS);
while(1);
}else{
printf(「%d:Opened」,SOCK_TCPS);
}

//連接TCP伺服器
ret = connect(SOCK_TCPS,domain_ip,1883);//埠必須為1883
if(ret != SOCK_OK){
printf(「%d:Socket Connect Error」,SOCK_TCPS);
while(1);
}else{
printf(「%d:Connected」,SOCK_TCPS);
}
return 0;
}

int transport_close(void)
{
close(SOCK_TCPS);
return 0;
}

完成了這幾個函數,然後我們就可以根據官方提供的示例代碼實現我們自己的代碼了,比如我們向代理伺服器發送一個消息的代碼如下所示:


int mqtt_publish(char *pTopic,char *pMessage)
{
int32_t len,rc;
MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
unsigned char buf[200];
MQTTString topicString = MQTTString_initializer;
int msglen = strlen(pMessage);
int buflen = sizeof(buf);

data.clientID.cstring = 「me」;
data.keepAliveInterval = 5;
data.cleansession = 1;
len = MQTTSerialize_connect(buf, buflen, &data);

topicString.cstring = pTopic;
len += MQTTSerialize_publish(buf + len, buflen – len, 0, 0, 0, 0, topicString, (unsigned char*)pMessage, msglen);

len += MQTTSerialize_disconnect(buf + len, buflen – len);
transport_open();
rc = transport_sendPacketBuffer(buf,len);
transport_close();
if (rc == len)
printf(「Successfully published」);
else
printf(「Publish failed」);
return 0;
}[page]

下面我們看下主函數的代碼,思路也比較清晰:

int main(void)
{
static char meassage[200];
int rc;
char *led;
char led_value;
float temperature,humidity,light,pressure;
srand(0);
//配置LED燈引腳
LED_Config();
//初始化配置網絡
network_init();
while(1){
memset(meassage,0,sizeof(meassage));
//訂閱消息
rc = mqtt_subscrib(「pyboard_led」,meassage);
printf(「rc = %d」,rc);
if(rc >= 0){
printf(「meassage = %s」,meassage);
//解析JSON格式字符串並點亮相應的LED燈
cJSON *root = cJSON_Parse(meassage);
if(root != NULL){
led = cJSON_GetObjectItem(root,」led」)->valuestring;
printf(「led = %s」,led);
led_value = cJSON_GetObjectItem(root,」value」)->valueint;
if(!strcmp(led,」red」)){
if(led_value){
LED_On(LED_RED);
}else{
LED_Off(LED_RED);
}
}else if(!strcmp(led,」green」)){
if(led_value){
LED_On(LED_GREEN);
}else{
LED_Off(LED_GREEN);
}
}else if(!strcmp(led,」blue」)){
if(led_value){
LED_On(LED_BLUE);
}else{
LED_Off(LED_BLUE);
}
}else if(!strcmp(led,」yellow」)){
if(led_value){
LED_On(LED_YELLOW);
printf(「Yellow On」);
}else{
LED_Off(LED_YELLOW);
printf(「Yellow Off」);
}
}
// 釋放內存空間
cJSON_Delete(root);
}else{
printf(「Error before: [%s]」,cJSON_GetErrorPtr());
}
}
delay_ms(500);
//獲取傳感器測量數據,該示例使用隨機數
temperature = rand()P;
humidity = rand()0;
light = rand()00;
pressure = rand()00;
//將數據合成為JSON格式數據
sprintf(meassage,」{」temperature」:%.1f,」humidity」:%.1f,」light」:%.1f,」pressure」:%.1f}」,temperature,humidity,light,pressure);
//將數據發送出去
mqtt_publish(「pyboard_value」,meassage);
}
}

完整工程代碼可在後面的附件下載。

2 手機端代碼實現
手機端我們也使用官方提供的Java庫Java client and utilities,下載地址:
http://www.eclipse.org/paho/
將jar文件添加到工程中即可,程序界面如下所示:

上面4個條目分別顯示STM32單片機通過W5500發送到伺服器端的傳感器測量數據;
下面4個圖片分別控制板子上的4個LED燈;
消息發送我們採用線程的方式發送,接收採用回調函數方式接收消息。

2.1 實現消息發送
發送消息的代碼如下所示:


class PublishThread extends Thread {
String topic;
MqttMessage message;
int qos = 0;
MemoryPersistence persistence = new MemoryPersistence();
PublishThread(String topic,String message){
this.topic = topic;
this.message = new MqttMessage(message.getBytes());
}
public void sendMessage(String topic,String message){
this.topic = topic;
this.message = new MqttMessage(message.getBytes());
run();
}
@Override
public void run() {
try {
MqttClient sampleClient = new MqttClient(broker, clientId, persistence);
MqttConnectOptions connOpts = new MqttConnectOptions();
connOpts.setCleanSession(true);
connOpts.setKeepAliveInterval(1);
System.out.println(「Connecting to broker: 」 + broker);
sampleClient.connect(connOpts);
System.out.println(「Connected」);
System.out.println(「Publishing message: 」 + message.toString());
message.setQos(qos);
sampleClient.publish(topic, message);
System.out.println(「Message published」);
sampleClient.disconnect();
System.out.println(「Disconnected」);
}catch(MqttException me) {
System.out.println(「reason 「+me.getReasonCode());
System.out.println(「msg 「+me.getMessage());
System.out.println(「loc 「+me.getLocalizedMessage());
System.out.println(「cause 「+me.getCause());
System.out.println(「excep 「+me);
me.printStackTrace();
}
}
}

2.2 實現消息接收
接收消息的代碼如下所示:


class SubscribeThread extends Thread{
final String topic;
MemoryPersistence persistence = new MemoryPersistence();
SubscribeThread(String topic){
this.topic = topic;
}
@Override
public void run(){
try {
final MqttClient sampleClient = new MqttClient(broker, clientId, persistence);
final MqttConnectOptions connOpts = new MqttConnectOptions();
connOpts.setCleanSession(true);
System.out.println(「Connecting to broker: 」 + broker);
connOpts.setKeepAliveInterval(5);
sampleClient.setCallback(new MqttCallback() {
@Override
public void connectionLost(Throwable throwable) {
System.out.println(「connectionLost」);
try {
sampleClient.connect(connOpts);
sampleClient.subscribe(topic);
}catch (MqttException e){
e.printStackTrace();
}
}

@Override
public void messageArrived(String topic, MqttMessage mqttMessage) throws Exception {
System.out.println(「messageArrived:」+mqttMessage.toString());
System.out.println(topic);
System.out.println(mqttMessage.toString());
try {
JSONTokener jsonParser = new JSONTokener(mqttMessage.toString());
JSONObject person = (JSONObject) jsonParser.nextValue();
temperature = person.getDouble(「temperature」);
humidity = person.getDouble(「humidity」);
light = person.getDouble(「light」);
pressure = person.getDouble(「pressure」);
System.out.println(「temperature = 」 + temperature);
System.out.println(「humidity = 」 + humidity);
runOnUiThread(new Runnable() {
@Override
public void run() {
temperatureTextView.setText(String.format(「%.1f」, temperature));
humidityTextView.setText(String.format(「%.1f」, humidity));
lightTextView.setText(String.format(「%.1f」, light));
pressureTextView.setText(String.format(「%.1f」, pressure));
}
});
} catch (JSONException ex) {
ex.printStackTrace();
}
}

@Override
public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) {
System.out.println(「deliveryComplete」);
}
});
sampleClient.connect(connOpts);
sampleClient.subscribe(topic);
} catch(MqttException me) {
System.out.println(「reason 「+me.getReasonCode());
System.out.println(「msg 「+me.getMessage());
System.out.println(「loc 「+me.getLocalizedMessage());
System.out.println(「cause 「+me.getCause());
System.out.println(「excep 「+me);
me.printStackTrace();
}
}
}

3 實測效果
1,單片機端定時更新傳感器數據,手機端也會同步更新;
2,手機端點擊4個LED控制的按鈕,板子上也會點亮或者熄滅對應的LED;

4 源碼下載


4.1 STM32端源碼下載
 MQTT_STM32_W5500.rar
4.2 手機端源碼下載
 MQTT_Android.rar
4.3 手機端apk下載
 stm32_w5500_mqtt_app.rar

關鍵字:STM32  W5500  MQTT  Android  遠程數據採集 編輯:什麼魚 引用地址:http://news.eeworld.com.cn/mcu/2015/0930/article_22632.html 本網站轉載的所有的文章、圖片、音頻視頻文件等資料的版權歸版權所有人所有,本站採用的非本站原創文章及圖片等內容無法一一聯繫確認版權者。如果本網所選內容的文章作者及編輯認為其作品不宜公開自由傳播,或不應無償使用,請及時通過電子郵件或電話通知我們,以迅速採取適當措施,避免給雙方造成不必要的經濟損失。

推薦閱讀

STM32MxCube配置串口

基於上一次將第一章:STM32MxCube 基本使用方法,本章直接講敘述STM32配置串口2的。查看STM32F407電路圖:可得USART2接在PA2、PA3。下面新建STM32MxCube工程,開始配置。這裡我們配置IO(定義PF9、PF10引腳為LED)、RCC(使用HSE)、USART(串口)。配置USART(串口)USART的配置有好幾種,也是最常見的一種」UART異步串行通信」配置來講述。選擇USART2模式為「asynchronous」(異步通信)對應的引腳自動轉換為USART。對於系統時鐘應該都知道它的作用,就是驅動整個晶片工作的心臟,如果沒有了它,就等於人沒有了心跳。時鐘的快慢也就決定了程序的快慢。STM32

發表於 2020-05-04

STM32CubeMX學習教程之一:GPIO輸出之跑馬燈

完整源碼下載:https://github.com/simonliu009/STM32CubeMX-GPIO-Control軟體版本:STM32CubeMX V4.25.0 System Workbench V2.4固件庫版本:STM32Cube FW_F1 V1.6.1硬體:OneNet 麒麟座V2.3在STM32CubeMX中新建項目,選擇正確的MCU型號首先設置RCC和SYS,如下圖然後根據板子實際情況設置時鐘(麒麟座外部晶振是12M,STM32F103x的最高主頻是72M),如下圖GPIO設置 PC7, PC8, PA12和 PC10為GPIO_OUTPUT, (這是麒麟座V2.3的四個LED管腳),如下圖

發表於 2020-05-04

STM32CubeMX學習--(3)串口通信

Cube配置USART配置在Connectivity中選中USART1MODE = AsynchronousHardware Flow Control = DisableParameter Settings中配置Baud Rate = 115200Word Length = 8bitParity = NoneStop Bits =1Data Direction = Receive and TransmitOver Sampling = 16 SamplesNVIC Setting勾選Enable,Preemption Priority =2生成代碼修改代碼生成代碼後,即可使用HAL_UART_Transmit_IT(&amp

發表於 2020-04-29

STM32CubeMX系列教程 5.0版本環境開發——2.Uart串行通信功能

;                         PS:在明白原理的情況下建議自己手寫一次模擬UART。明白了之後,代碼重複的事就由STM32晶片的硬體功能來實現就可以了,你只需要會看邏輯分析儀或者示波器分析數據便可。 所謂硬體功能 就是你把數據填充到寄存器,然後配置好相關參數,他會自動幫你發送出去。通俗點說,自己手寫整個協議代碼實現實現就像你自己把一個快件送到到別人那裡再回來,而硬體功能則是你把快件給快遞員,快遞員幫你送過去。  明顯 後者會幫你節省大量時間和精力。它是一個硬體組成,並且你也為此付費

發表於 2020-04-29

串口通信(用CubeMX學習STM32)

前言: STM32串口介紹串行通信是單片機與外部設備或其他計算機交換信息的一個方式, 數據一位一位的按順序傳送, 其優點是只需要一條傳輸線, 協議簡單, 但是缺點就是傳送速度較慢。串口是單片機上非常便捷的一個工具, 當寫程序需要調試的時候, 它可以很方便的提供調試方法, 只要在一些關鍵代碼執行的地方, 通過串口給串口調試助手發送相關信息, 就可以使我們很方便的查看代碼在這個位置的執行情況。下面看一下我所使用的單片機上串口的原理圖接線外部的發送端TXD就是單片機串口的接收端USART_RX,   外部接收端RXD就是單片機串口的發送端USART_TXTXD : Transmit(TX) Data(D)  Receive(RX

發表於 2020-04-29

【STM32CubeMX】 串口通信(USART) Printf重定向

STM32CubeMX: Version 4.26.1MDK-ARM: Version 5.24.2開發板: 中移onenet 麒麟座MINI板晶片: STM32F103CBT61.STM32CubeMX設置設置外部時鐘源設置Debug設置串口 使用USART1 PA9,PA10設置時鐘頻率設置USART1詳細參數生成MDK-ARM工程2.重定向Printf 及 Scanf主要用到兩個函數HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout

發表於 2020-04-29

相關焦點

  • 具有數據加密的Android藍牙遠程控制
    為了使智能可穿戴設備更好的與手機相互配合,滿足於人們的需求,本文研究了藍牙遠程控制功能,實現了具有遠程控制功能的應用程式。由於通過藍牙傳送的數據能夠被追蹤竊取到,發送數據的安全性也尤為重要,通過比較本文採用RC4和RSA混合加密方式對發送的數據進行加密。為了適應不同品牌的智能手錶,首先實現了在手機之間的遠程控制功能。
  • 三菱PLC遠程監控與數據採集方案
    基於手機微信小程序或PC終端的三菱PLC遠程監控和數據採集方案的優勢和特點: 1. 遠程監控系統可以使異地的智力之源得到充分利用。可以使位於異地的專家通過網絡獲得遠程監控數據,進行分析處理,實現遠程監控。 2. 遠程監控系統可以使異地的物質資源得到充分利用。通過該技術的使用,可以使異地物資資源的共享和遠程實驗得以實現。
  • 通過Metasploit遠程控制Android設備
    可以直接在vps上面安裝metasploit,生成木馬並直接控制受害者的手機,這多簡單。但這裡我們還是用埠映射的方法。frp我們先用frp工具來實現埠映射,利用處在內網的攻擊機kali實現對處在外網的Android機器的入侵。
  • 如何實現對示波器的遠程控制
    但是很多情況下,需要把數字示波器採集到的數據進行數據處理和分析,並最終完成遠程的自動測試和分析的需求。所以今天我們就來說說如何實現對示波器的遠程控制。本文引用地址:http://www.eepw.com.cn/article/307876.htm
  • MQTT 教程詳解(入門篇)
    當然,消息推送的主流技術也有很多種,比如 C2DM 雲端推送平臺 ,這是一個用來幫助開發者從伺服器向Android應用程式發送數據的服務,簡單,輕量級,允許伺服器可以通知行動應用程式直接與伺服器進行通信,以便於從伺服器獲取應用程式更新和用戶數據,但是該服務需要依賴於 Google 官方提供的C2DM 伺服器,由於國內的網絡環境,
  • 如何遠程控制Android手機,為所欲為?
    1、控制鎖屏2、控制攝像機的使用@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) public int setCameraDisabled(boolean disableCamera) { if (isDeviceAdminActive()) {
  • 一種基於手機APP的PLC遠程控制系統實現
    本文引用地址:http://www.eepw.com.cn/article/201710/367558.htm基於手機APP的PLC遠程監控系統的優勢和特點:1. 遠程監控系統可以使異地的智力之源得到充分利用。可以使位於異地的專家通過網絡獲得遠程監控數據,進行分析處理,實現遠程監控。2. 遠程監控系統可以使異地的物質資源得到充分利用。
  • 基於STM32的多路電壓採集的設計與實現
    1.引言 近年來,數據採集及其應用受到了人們越來越廣泛的關注,數據採集系統也有了迅速的發展,它可以廣泛的應用於各種領域。 數據採集技術是信息科學的重要分支之一,數據採集也是從一個或多個信號獲取對象信息的過程。
  • 工業乙太網數據採集模塊:快速選型指南
    帶有一路RS485串口,支持Modbus主從站功能,方便擴展,一路10/100M自適應乙太網接口,支持Modbus TCP主從站,MQTT協議,以及支持TCP Server與TCP Client服務,可以直接接入SCADA、MES、OPC Server、物聯網雲平臺實現遠程數據採集功能。廣泛應用於工業自動化、數位化工廠改造升級等場所。
  • 向日葵遠程控制軟體 遠程監控實現「掌上看家 」
    作為國內首推「陽光遠控」的向日葵遠程控制廠商在遠程監控方面首推遠程攝像頭功能,輕鬆打造360度無死角、零成本家庭安防,完全滿足白領們隨時隨地遠程視頻監控的需求。那麼向日葵遠程攝像頭功能是如何實現家庭安防的呢?
  • 【零基礎學物聯網】MQTT篇 1-6 ESP8266發布MQTT消息
    我們將要利用ESP8266來實現最基本的MQTT消息發布。本節課的學習將需要您掌握ESP8266的基本操作,假如您對ESP8266的基本操作不太了解,您可以先通過以下小程序觀看我們製作的《零基礎入門學用物聯網 - 基礎知識篇》。假如您已經完成以上教程,那麼接下來您就可以繼續這節課的學習了。
  • 手機攝像頭會不會被人遠程控制
    要想實現這個目標,我們先了解一下遠程視頻監控系統。遠程視頻監控系統分為三部分:前端設備,中間傳輸部分,後端設備。 1、前端設備 前端設備用於採集被監控點的監控信息,負責圖像採集以及前端控制。它負責把音、視頻信號通過區域網或廣域網傳輸到遠程客戶端,同時可以接收客戶端發送的控制信號; 2、中間傳輸部分 圖像數據和控制數據從前端流通後端的通道。 3、後端設備 它是接收前端設備採集到的圖像數據和控制前端的設備,可以是手機或者電腦等等其它智能設備以及運行在這些設備上的遠程控制軟體的控制端。
  • DS12887在數據採集與監控中的應用
    現場變壓器遠程數據採集終端安裝在變壓器現場,通過RS485通訊接口採集多功能電能表的數據,對變壓器的電氣參數進行數據處理並存儲數據,再通過RS232通訊接口控制GPRS通訊模塊實現遠程無線數據的採樣監測,監控中心的伺服器主機上,安裝了低壓配電網臺區實時監測軟體,通過GPRS Modem即可與數據採集終端進行通信。
  • MicroPython使用MQTT協議接入OneNET雲平臺
    之前使用Arduino+ESP8266使用EDP協議成功接入了OneNET,實現了物聯網控制,本次使用板載ESP8266的ESP-MP-01 MicroPython開發板使用MQTT協議同樣成功接入,通過發布TOPIC成功實現智能設備控制。
  • MES系統是什麼,模塊包括哪些,採集數據和過程控制如何實現?
    Manufacturing Execution System 面向製造企業車間執行層的生產信息化管理系統,MES能通過信息傳遞對從訂單下達到產品完成的整個生產過程進行優化管理);wms(Warehouse Management System倉庫管理系統);qms(Quality Management System質量管理體系);spc(Statistical Process Control統計過程控制
  • DTU配網電力系統自動化數據採集傳輸
    方案需求配電自動化/智能化目的是為了實現配電網數據採集與監控,針對配電網電壓管理,實現配電網故障診斷,實時對數據採集、監視控制,與控制中心和配電調度自動化系統(SCADA)通信。DTU通過軟體組態配置既可實現靈活組合,具備多種方式的通信接口RS485、RS232和電力101等多種標準通信規約,除具備終端內部數據管理功能,對外還可轉發配電室或開閉站內電能表、PLC及直流屏數據,通過一個標準統一接口與主站系統通信完成數據傳輸。
  • 迅為迅為iTOP-i.MX6ULL 開發板-Mqtt 移植教程
    訂閱 (publish/subscribe)模式的輕量級協議,該協議構建於 TCP/IP 協議之上, MQTT 最大優點在於,可以以 極少的代碼和有限的帶寬,為連接遠程設備提供實時可靠的消息服務我們這裡使用的是 Mosquitto, Mosquitto 是 MQTT 的實現方法,因為 MQTT 是一種協議,就好比
  • 記一次MQTT協議壓測
    這些信令是雙向的、也有可能是一對多.我們用的MQTT協議,MQTT提供商有很多,比如融雲、阿里雲等MQTT協議概念MQTT協議是基於發布/訂閱模式的物聯網通信協議,憑藉簡單易實現、支持 QoS、報文小等特點,佔據了物聯網協議的半壁江山MQTT協議廣泛應用於物聯網、移動網際網路、智能硬體、車聯網、電力、能源等領域名詞發布訂閱主題會話保持QoS:QoS
  • 8051單片機C語言數據採集程序
    =1,w,PickCount;uint vol;Befor_Once_AD();//預先採集一次AD數據//---------------if (ComBuf[1]==0)ComBuf[1]=0x01;PickCount=ComBuf[1];for(w=1;w<=PickCount;w++){ADCLK=ADOUT=0;vol