当前位置:   article > 正文

Android+MQTT(Android APP 连接至MQTT服务器)_mqtt app

mqtt app

这段时间因为毕设的需求,接触学习了一下用Android app连接MQTT服务器,然后对下位机(STM32/ESP8266)进行数据通讯的一个小设计,本篇文章介绍app+MQTT服务器这一段。

实现原理:

这里设计的是一个监测控制智能风扇的APP,可以实时监测当前温度、湿度及下位机的传感器、控制器件的一些状态。

一、设计流程:

  1. Android app项目创建;
  2. UI控制界面设计;
  3. 导入MQTT jar包;
  4. 配置联网权限;
  5. 配置MQTT服务器连接参数;
  6. MQTT.fx实现联调;

二、设计实现

1、Android app项目创建

项目创建这里就不过多赘述了!

2、UI控制界面设计

我这里主要是以毕设的需求设计的,所以比较简单;

模拟器界面

  手机app界面

这个显示界面代码相对简单,有需要的可以参考一下,代码如下:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3.     xmlns:app="http://schemas.android.com/apk/res-auto"
  4.     xmlns:tools="http://schemas.android.com/tools"
  5.     android:layout_width="match_parent"
  6.     android:layout_height="match_parent"
  7.     android:orientation="vertical"
  8.     tools:context=".MainActivity">
  9.  
  10.     <LinearLayout
  11.         android:layout_width="match_parent"
  12.         android:orientation="vertical"
  13.         android:background="#078307"
  14.         android:layout_height="match_parent">
  15.  
  16.         <LinearLayout
  17.             android:layout_width="match_parent"
  18.             android:layout_height="78dp">
  19.             <TextView
  20.                 android:layout_width="match_parent"
  21.                 android:layout_marginTop="10dp"
  22.                 android:text="智能温控风扇系统设计"
  23.                 android:textSize="24sp"
  24.                 android:layout_marginLeft="6dp"
  25.                 android:layout_gravity="center"
  26.                 android:textColor="@color/white"
  27.                 android:layout_height="wrap_content"/>
  28.         </LinearLayout>
  29.  
  30.         <LinearLayout
  31.             android:layout_width="match_parent"
  32.             android:background="#FAF6F6"
  33.             android:orientation="vertical"
  34.             android:layout_height="710dp">
  35.  
  36.             <LinearLayout
  37.                 android:layout_width="match_parent"
  38.                 android:layout_marginTop="20dp"
  39.                 android:layout_height="wrap_content">
  40.                 <androidx.cardview.widget.CardView
  41.                     android:layout_width="match_parent"
  42.                     android:layout_height="200dp"
  43.                     android:layout_marginLeft="10dp"
  44.                     android:layout_marginRight="10dp"
  45.                     app:cardCornerRadius="20dp">
  46.                     <ImageView
  47.                         android:id="@+id/m_im_1"
  48.                         android:layout_width="wrap_content"
  49.                         android:src="@drawable/img_3"
  50.                         android:layout_height="wrap_content"/>
  51.  
  52.                 </androidx.cardview.widget.CardView>
  53.             </LinearLayout>
  54.  
  55.             <LinearLayout
  56.                 android:layout_width="match_parent"
  57.                 android:layout_marginTop="30dp"
  58.                 android:orientation="vertical"
  59.                 android:layout_height="300dp">
  60.  
  61.                 <LinearLayout
  62.                     android:layout_width="match_parent"
  63.                     android:layout_marginTop="30sp"
  64.                     android:orientation="horizontal"
  65.                     android:layout_height="wrap_content">
  66.                     <TextView
  67.                         android:id="@+id/m_temp"
  68.                         android:layout_width="wrap_content"
  69.                         android:text="温度:0 ℃"
  70.                         android:textSize="16sp"
  71.                         android:layout_weight="1"
  72.                         android:textColor="@color/black"
  73.                         android:layout_marginLeft="30dp"
  74.                         android:layout_height="wrap_content"/>
  75.                     <TextView
  76.                         android:id="@+id/m_humi"
  77.                         android:layout_weight="1"
  78.                         android:layout_width="wrap_content"
  79.                         android:text="湿度:0 %"
  80.                         android:textSize="16sp"
  81.                         android:textColor="@color/black"
  82.                         android:layout_marginLeft="30dp"
  83.                         android:layout_height="wrap_content"/>
  84.                 </LinearLayout>
  85.  
  86.                 <LinearLayout
  87.                     android:layout_width="match_parent"
  88.                     android:layout_marginTop="50dp"
  89.                     android:padding="30dp"
  90.                     android:layout_height="wrap_content">
  91.                     <TextView
  92.                         android:layout_width="wrap_content"
  93.                         android:text="MQTT连接状态:"
  94.                         android:textColor="@color/black"
  95.                         android:textSize="16sp"
  96.                         android:layout_height="wrap_content"/>
  97.                     <TextView
  98.                         android:id="@+id/m_mqtt"
  99.                         android:layout_width="wrap_content"
  100.                         android:text=" "
  101.                         android:textColor="@color/black"
  102.                         android:textSize="16sp"
  103.                         android:layout_height="wrap_content"/>
  104.                 </LinearLayout>
  105.  
  106.             </LinearLayout>
  107.  
  108.         </LinearLayout>
  109.  
  110.  
  111.  
  112.  
  113.         <LinearLayout
  114.             android:layout_width="match_parent"
  115.             android:orientation="vertical"
  116.             android:layout_height="match_parent">
  117.  
  118.             <LinearLayout
  119.                 android:layout_width="match_parent"
  120.                 android:layout_height="wrap_content">
  121.                 <ImageButton
  122.                     android:layout_width="30dp"
  123.                     android:layout_marginLeft="10dp"
  124.                     android:layout_marginRight="10dp"
  125.                     android:layout_weight="1"
  126.                     android:layout_height="40dp"/>
  127.                 <ImageButton
  128.                     android:layout_width="30dp"
  129.                     android:layout_marginRight="10dp"
  130.                     android:layout_weight="1"
  131.                     android:layout_height="40dp"/>
  132.                 <ImageButton
  133.                     android:layout_width="30dp"
  134.                     android:layout_marginRight="10dp"
  135.                     android:layout_weight="1"
  136.                     android:layout_height="40dp"/>
  137.                 <ImageButton
  138.                     android:layout_width="30dp"
  139.                     android:layout_marginRight="10dp"
  140.                     android:layout_weight="1"
  141.                     android:layout_height="40dp"/>
  142.  
  143.             </LinearLayout>
  144.             <LinearLayout
  145.                 android:layout_width="match_parent"
  146.                 android:orientation="horizontal"
  147.                 android:layout_height="wrap_content">
  148.                 <TextView
  149.                     android:layout_width="wrap_content"
  150.                     android:text="我的"
  151.                     android:gravity="center"
  152.                     android:textSize="16sp"
  153.                     android:layout_weight="1"
  154.                     android:layout_marginLeft="10dp"
  155.                     android:textColor="@color/white"
  156.                     android:layout_height="wrap_content"/>
  157.                 <TextView
  158.                     android:layout_width="wrap_content"
  159.                     android:text="我的"
  160.                     android:gravity="center"
  161.                     android:textSize="16sp"
  162.                     android:layout_weight="1"
  163.                     android:layout_marginLeft="10dp"
  164.                     android:textColor="@color/white"
  165.                     android:layout_height="wrap_content"/>
  166.                 <TextView
  167.                     android:layout_width="wrap_content"
  168.                     android:text="我的"
  169.                     android:gravity="center"
  170.                     android:textSize="16sp"
  171.                     android:layout_weight="1"
  172.                     android:layout_marginLeft="10dp"
  173.                     android:textColor="@color/white"
  174.                     android:layout_height="wrap_content"/>
  175.                 <TextView
  176.                     android:layout_width="wrap_content"
  177.                     android:text="我的"
  178.                     android:gravity="center"
  179.                     android:textSize="16sp"
  180.                     android:layout_weight="1"
  181.                     android:layout_marginRight="10dp"
  182.                     android:layout_marginLeft="10dp"
  183.                     android:textColor="@color/white"
  184.                     android:layout_height="wrap_content"/>
  185.  
  186.             </LinearLayout>
  187.  
  188.         </LinearLayout>
  189.  
  190.     </LinearLayout>
  191.  
  192. </LinearLayout>

3、导入MQTT jar包

进入正题,开始导入MQTT所需要的jar包:

jar包链接 链接:https://pan.baidu.com/s/1hLt1xiL67dhbJ3v3MKfUlw 
提取码:wmmh

下载jar包后直接复制这个jar包

 然后给粘贴至libs目录下

 点击OK即可

 导入

 然后鼠标右键给它添加依赖

点击OK

等待构建完成即可.

此时我们来到java代码界面敲MQTT就可以看到很多方法

 好,到了这一步就可以添加MQTT的配置代码了

在onCreate后面添加下列代码

 添加代码

  1. // MQTT初始化
  2.     private void Mqtt_init()
  3.     {
  4.         try {
  5.             //host为主机名,test为clientid即连接MQTT的客户端ID,一般以客户端唯一标识符表示,MemoryPersistence设置clientid的保存形式,默认为以内存保存
  6.             client = new MqttClient(host, mqtt_id,
  7.                     new MemoryPersistence());
  8.             //MQTT的连接设置
  9.             MqttConnectOptions options = new MqttConnectOptions();
  10.             //设置是否清空session,这里如果设置为false表示服务器会保留客户端的连接记录,这里设置为true表示每次连接到服务器都以新的身份连接
  11.             options.setCleanSession(false);
  12.             //设置连接的用户名
  13.             options.setUserName(userName);
  14.             //设置连接的密码
  15.             options.setPassword(passWord.toCharArray());
  16.             // 设置超时时间 单位为秒
  17.             options.setConnectionTimeout(10);
  18.             // 设置会话心跳时间 单位为秒 服务器会每隔1.5*20秒的时间向客户端发送个消息判断客户端是否在线,但这个方法并没有重连的机制
  19.             options.setKeepAliveInterval(20);
  20.             //设置回调
  21.             client.setCallback(new MqttCallback() {
  22.                 @Override
  23.                 public void connectionLost(Throwable cause) {
  24.                     //连接丢失后,一般在这里面进行重连
  25.                     System.out.println("connectionLost----------");
  26.                     //startReconnect();
  27.                 }
  28.                 @Override
  29.                 public void deliveryComplete(IMqttDeliveryToken token) {
  30.                     //publish后会执行到这里
  31.                     System.out.println("deliveryComplete---------"
  32.                             + token.isComplete());
  33.                 }
  34.                 @Override
  35.                 public void messageArrived(String topicName, MqttMessage message)
  36.                         throws Exception {
  37.                     //subscribe后得到的消息会执行到这里面
  38.                     System.out.println("messageArrived----------");
  39.                     Message msg = new Message();
  40.                     msg.what = 3;   //收到消息标志位
  41. //                    msg.obj = topicName + "---" +message.toString();
  42.                     msg.obj = message.toString();
  43.                     handler.sendMessage(msg);    // hander 回传
  44.                 }
  45.             });
  46.         } catch (Exception e) {
  47.             e.printStackTrace();
  48.         }
  49.     }
  50.  
  51.     // MQTT连接函数
  52.     private void Mqtt_connect() {
  53.         new Thread(new Runnable() {
  54.             @Override
  55.             public void run() {
  56.                 try {
  57.                     if(!(client.isConnected()) )  //如果还未连接
  58.                     {
  59.                         MqttConnectOptions options = null;
  60.                         client.connect(options);
  61.                         Message msg = new Message();
  62.                         msg.what = 31;
  63.                         handler.sendMessage(msg);
  64.                     }
  65.                 } catch (Exception e) {
  66.                     e.printStackTrace();
  67.                     Message msg = new Message();
  68.                     msg.what = 30;
  69.                     handler.sendMessage(msg);
  70.                 }
  71.             }
  72.         }).start();
  73.     }
  74.  
  75.     // MQTT重新连接函数
  76.     private void startReconnect() {
  77.         scheduler = Executors.newSingleThreadScheduledExecutor();
  78.         scheduler.scheduleAtFixedRate(new Runnable() {
  79.             @Override
  80.             public void run() {
  81.                 if (!client.isConnected()) {
  82.                     Mqtt_connect();
  83.                 }
  84.             }
  85.         }, 0*1000, 10 * 1000, TimeUnit.MILLISECONDS);
  86.     }
  87.  
  88.     // 订阅函数    (下发任务/命令)
  89.     private void publishmessageplus(String topic,String message2)
  90.     {
  91.         if (client == null || !client.isConnected()) {
  92.             return;
  93.         }
  94.         MqttMessage message = new MqttMessage();
  95.         message.setPayload(message2.getBytes());
  96.         try {
  97.             client.publish(topic,message);
  98.         } catch (MqttException e) {
  99.  
  100.             e.printStackTrace();
  101.         }
  102.     }
  103.     /* ========================================================================================== */


不出意外,这里会出现一堆报红

不用慌,这是因为有一些方法还没构建,有一些参数还没声明,我们一步一步来;

光标放置后按alt+Enter后,有部分参数就会自动构建,开干

 然后把下列处理代码添加至主函数(这个位置)

  1.         Mqtt_init();
  2.         startReconnect();
  3.  
  4.         handler = new Handler(Looper.myLooper()) {
  5.             @SuppressLint("SetTextI18n")
  6.             public void handleMessage(Message msg) {
  7.                 super.handleMessage(msg);
  8.                 switch (msg.what){
  9.                     case 1: //开机校验更新回传
  10.                         break;
  11.                     case 2:  // 反馈回传
  12.  
  13.                         break;
  14.                     case 3:  //MQTT 收到消息回传   UTF8Buffer msg=new UTF8Buffer(object.toString());
  15.                         
  16.                         System.out.println(msg.obj.toString());   // 显示MQTT数据
  17.                         break;
  18.                     case 30:  //连接失败
  19.                         Toast.makeText(MainActivity.this,"连接失败" ,Toast.LENGTH_SHORT).show();
  20.                         break;
  21.                     case 31:   //连接成功
  22.                         Toast.makeText(MainActivity.this,"连接成功" ,Toast.LENGTH_SHORT).show();
  23.                         try {
  24.                             client.subscribe(mqtt_sub_topic,1);
  25.                         } catch (MqttException e) {
  26.                             e.printStackTrace();
  27.                         }
  28.                         break;
  29.                     default:
  30.                         break;
  31.                 }
  32.             }
  33.         };
  34.         /* -------------------------------------------------------------------------------------- */

好,把这个配置代码加上去

  1.     private ScheduledExecutorService scheduler;
  2.     private MqttClient client;
  3.     private Handler handler;
  4.     private String host = "tcp://114.132.53.92:1883";     // TCP协议
  5.     private String userName = "aixin123456";
  6.     private String passWord = "aixin123456";
  7.     private String mqtt_id = "1353023461";
  8.     private String mqtt_sub_topic = "mqtt135";
  9.     private String mqtt_pub_topic = "esp135";

 那么到达这一步就不会有报错了!  解决

4、配置联网权限

在事件清单中添加联网权限

  1.     <!--允许程序打开网络套接字-->
  2.     <uses-permission android:name="android.permission.INTERNET" />
  3.     <!--允许程序获取网络状态-->
  4.     <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

5、配置服务器参数

这里的服务器连接的参数注意一定要修改,这里连接服务器地址可以填写我的服务器地址(“tcp://114.132.53.92:1883”),当然也可以使用官方公用的MQTT服务器地址或者用别人的都是可以的;然后就是用户名和密码,一定不要用这里我填写的这个,可以用自己的QQ加上一些英文,或者自定义一些内容都是可以的,注意不要用我这里填写的这个!!! 然后就是订阅和发布号可以随意起,建议不用下面这些!


    private String host = "tcp://114.132.53.92:1883";     // TCP协议
    private String userName = "aixin123456";
    private String passWord = "aixin123456";
    private String mqtt_id = "1353023461";
    private String mqtt_sub_topic = "mqtt135";
    private String mqtt_pub_topic = "esp135";

好!配置完以上步骤之后,咱们就可以下载到模拟机或者真机测试一下了,这里我用的真机测试,不用慌!直接下载运行,弹窗弹出连接成功!完美

真机运行画面

那么到这里我们的app已经成功连接了MQTT服务器了!

6、MQTT.fx实现联调

这里需要使用到一个测试软件 MQTT.fx

这里不提供软件安装包(我的找不到按转包在哪了),网上有教程,也可以去官网下载

这里的连接服务器地址填114.132.53.92或者是你自己app中连接的地址,端口1883,clientld_ID可以自己填

 用户名和密码也可以自己填写(需要注意的是,这里填写的这些其实是模拟你下位机的连接用户信息,也就是你STM32通过ESP8266连接MQTT服务器的信息) 

点击这里,填写发布号以及填写要发往app中的信息,点击Publish

然后就可以看的到Android Studio调试台下的接收到了数据,到了这里是不是就实现了下位机上传数据至MQTT服务器至客户端手机APP

这里再介绍一种简单的Json格式数据处理吧!

简单的Json数据格式模拟下位机数据

{"name":"ESP135","Temp":"26","Humi":"78"} 

这里我们就要在app中添加一个Json数据处理的函数,形参就是需要处理的字符串

  1.     // Json数据解析
  2.     private void parseJsonobj(String jsonobj){
  3.         // 解析json
  4.         try {
  5.             JSONObject jsonObject = new JSONObject(jsonobj);
  6.             String name = jsonObject.getString("name");
  7.             String temp = jsonObject.getString("Temp");
  8.             String humi = jsonObject.getString("Humi");
  9.             m_temp.setText("温度: "+temp+" ℃ ");
  10.             m_humi.setText("湿度: "+humi+" % ");
  11.         } catch (JSONException e) {
  12.             e.printStackTrace();
  13.         }
  14.     }


app中接收到的数据

 经过处理后就可以在我们app的控件中以指定格式显示

 这样是不是感觉就出来了!好到此那么我们上位机数据接收就差不多了

嗯,那么app向下位机发送数据呢!其实也就是订阅号与STM32+ESP的信息关联后,经过一个函数就可以下发数据了,下一篇下位机(STM32+ESP)再详细介绍吧!发送的函数已经添加在上述的代码中了;这里贴出来一个示例代码,简单介绍一下,一个按键然后下发数据 publishmessageplus(mqtt_pub_topic,"{\"set_curtain\": \"fB}");

  1.      // 关闭控件点击事件
  2.     private void button_guan(View v){
  3.         if(curtain_flag == 0){
  4.             curtain_flag = 1;
  5.             // 发送指令让下位机关闭窗帘
  6.             publishmessageplus(mqtt_pub_topic,"{\"set_curtain\": \"fB}");
  7.         }
  8.         mtv_1.setText("关闭");
  9.     }


————————————————
转载于:https://blog.csdn.net/x97666/article/details/125172129

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/386477
推荐阅读
相关标签
  

闽ICP备14008679号