搭建MQTT服务器实现Android客户端与ESP8266之间即时通信

  • 1、MQTT服务器端
  • 2、Android客户端
  • 3、ESP8266端
  • 4、结语


1、MQTT服务器端

MQTT是一个基于客户端-服务器的消息发布/订阅传输协议,假如你发布一个topic那么其他订阅了这个topic的设备就可以收到你发送的信息,反之亦然。关于mqtt是什么这里不再赘述。我们的目的是Android端和ESP8266连接到MQTT服务端,双方之间进行通信,实现8266对温湿度采集在Android端进行监控,Android端也可以控制8266进行一些业务逻辑操作,比如控制继电器开合进而控制一切开关型电器。

首先你需要一台服务器,关于服务器有很多选择,阿里云腾讯云皆可,且都有学生优惠,我这里使用阿里云的Windows server 2012版。购置一台服务器后首先安装JDK,建议1.8版本以上。学过Java应该都会,实在不行百度一下,很简单。接下来就是下载一个MQTT服务端软件,这里我们选择apache-apollo,安装和使用过程简单方便。前往下载 提取码:2cfq

1 在服务器里下载之后解压到C盘

android studio mqtt 跨界面 mqtt安卓服务端_物联网


2 打开命令行进入到apache-apollo-1.7.1\bin目录下,输入apollo.cmd create apache-apollo(apache-apollo并非固定,随便都行)。完成后会在C盘生成一个apache-apollo文件夹

android studio mqtt 跨界面 mqtt安卓服务端_服务器_02


3 apache-apollo下的etc\users.properties存储了连接MQTT服务器的用户名,groups.properties则存储了密码,默认用户名为admin,密码为password,这里不作修改。

android studio mqtt 跨界面 mqtt安卓服务端_java_03


4 然后打开命令行进入C:\apache-apollo\broker\bin目录下输入

apollo-broker run,MQTT服务器就开始运行了,关闭命令行后MQTT服务器随之关闭。上面会显示各种连接的地址和端口

android studio mqtt 跨界面 mqtt安卓服务端_c++_04


5 我们MQTT基于TCP连接所以会用到61613端口,注意一定要在云服务器的安全组规则里开放61613端口,否则无法连接。完成后你可以在浏览器输入http://127.0.0.1:61680登录MQTT服务器管理页面,出现下图则服务器端配置就成功结束了,在这里你可以看到有谁连接和订阅。

android studio mqtt 跨界面 mqtt安卓服务端_android_05


6 C:\apache-apollo-1.7.1\examples\mqtt\websocket目录下有一个index.html测试网页,你可以用它进行一个简单的发送消息的测试

android studio mqtt 跨界面 mqtt安卓服务端_物联网_06


7 如果你不想自己搭建服务器也可以选择其他物联网平台,比如中国移动ONENET平台,在开发者中心创建一个旧版MQTT协议的产品,然后添加设备,里面的产品id就相当于用户名,鉴权信息就是密码,设备id就是客户端id,服务器地址和端口是183.230.40.39:6002。知道这些就可以了,下文会依次说到。

2、Android客户端

1 开发环境为Android Studio 3.6,当然也需要JDK,先看看效果图

android studio mqtt 跨界面 mqtt安卓服务端_android_07

android studio mqtt 跨界面 mqtt安卓服务端_java_08


8266传过来温湿度,这里控制led开关。

2 下面看代码,先添加依赖。

implementation 'org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.2.2'
implementation 'org.eclipse.paho:org.eclipse.paho.android.service:1.1.1'

3 在Androidmainifest.xml里添加权限

<uses-permission android:name="android.permission.WAKE_LOCK" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.INTERNET" />

这一部分要放在application里

<service android:name="org.eclipse.paho.android.service.MqttService"/>

4主要代码

private void initClient() throws MqttException {

        //连接参数设置
        // 获取默认的临时文件路径
        String tmpDir = System.getProperty("java.io.tmpdir");       
        MqttDefaultFilePersistence dataStore = new MqttDefaultFilePersistence(tmpDir);
        String serverURI = "tcp://*****:61613";//服务器IP地址和端口号
        String clientId = "***";//客户端id,随便写,不要和别人一样就行
        MqttConnectOptions options = new MqttConnectOptions();
        options.setCleanSession(false);
        options.setUserName("******");//创建MQTT服务器时的用户名,默认admin
        options.setPassword("******".toCharArray());//创建MQTT服务器时的用户名,默认password
        options.setAutomaticReconnect(true);
        mClient = new MqttAndroidClient(getApplicationContext(), serverURI, clientId,dataStore);

        //连接回调
        mClient.setCallback(new MqttCallbackExtended() {
			//连接服务器成功时触发,可在这时订阅想要订阅的topic
            @Override
            public void connectComplete(boolean reconnect, String serverURI) {
                Log.e("connectComplete","connectComplete");
               
            }

            //连接丢失时触发
            @Override
            public void connectionLost(Throwable cause) {
                Log.e("connectionLost","connectionLost");
            }

            //接收到订阅的消息,可以进行一些逻辑业务处理,这是最重要的部分
            @Override
            public void messageArrived(String topic, MqttMessage message) throws Exception {
                Log.e("messageArrived",message.toString());              
            }
            @Override
            public void deliveryComplete(IMqttDeliveryToken token) {
                Log.e("deliveryComplete","deliveryComplete");
            }
        });
        mClient.connect(options);//开始连接

    }

5 过程中可能会出现连接不上,可以发送不能接收消息,类加载异常等等细节问题,不要担心,都可以解决。我在接收的时候会有收不到消息的问题,重启一下MQTT服务器,就是重新Apollo-broker run 就能收到,可能是因为服务器配置低,太卡?但是在连接onenet服务器时就不会出现这个问题程序不需要改,只需改用户名,密码,客户端ID和IP地址端口号就行,上面已经说过。

6 完整代码

3、ESP8266端

0 说在最前面,arduino我也是现学现卖,以前只学过51单片机,不足之处请见谅。

1 开发环境为arduino IDE ,需要一个ESP8266模块,这里用的是ESP8266-01S,一个烧写器用于下载程序,一个DHT11温湿度传感器,一些杜邦线,简单说一下过程,传感器获取环境数据通过8266发布出去,然后手机订阅就可以收到这些数据。8266有两个IO口,一个用于连接传感器,另一个则控制继电器。一个取巧的连接方式,直接插在下载器上,下载器有标识,对应接口可以连接传感器和继电器。

android studio mqtt 跨界面 mqtt安卓服务端_物联网_09

android studio mqtt 跨界面 mqtt安卓服务端_android_10


也可直接插在物联网继电器上。

2 首先你可以在arduino 官网下载软件,安装完成后需要下载esp8266扩展,在 文件–>首选项 里找到附加开发板管理器地址添加以下内容

http://arduino.esp8266.com/stable/package_esp8266com_index.json

android studio mqtt 跨界面 mqtt安卓服务端_物联网_11


3 之后点击工具 - 开发板 - 开发板管理器,进入开发板管理器界面:搜索esp8266并安装。

android studio mqtt 跨界面 mqtt安卓服务端_c++_12


4 再进入工具 - 管理库界面,搜索EspMqttClient并安装,然后重启一下。

android studio mqtt 跨界面 mqtt安卓服务端_c++_13


5 点击文件 - 示例 - 翻到最下方EspMqttClient点击SampleMQTTClient创建一个项目。主要代码

EspMQTTClient client(
  "WifiSSID",//8266需要联网,你的无线网名称
  "WifiPassword",//无线网密码
  "*********",  // MQTT服务器ip
  "MQTTUsername",   // 用户名,默认admin
  "MQTTPassword",   // 密码,默认password
  "TestClient",     // 客户端id,任意填写
  61613              // MQTT服务器端口
);

订阅一个topic,回调也在里面,可以进行一些业务逻辑操作。

client.subscribe("LED_STATUS", [](const String & payload) {
    Serial.println(payload);
  });

发布消息,前者是topic,后者是内容。

client.publish("mytopic/test", "This is a message");

6 还要导入DHT11的包,否则无法使用。

7 不只是arduino IDE,还有其他编程软件,比如安信可公司的AiThinkerIDE,不过这个需要网8266里烧录固件,下载和烧录在这里有详细的说明,就不再细说了,具体可以前往看我同学的说明,他采用的是AiThinkerIDE连接ONENET平台,也是手机端控制。

8 8266也一样可以连接其他MQTT服务器,onenet,阿里云等等,同Android,也是只需修改那几个参数,用户名密码等。

9 完整代码

4、结语

以上仅是把我自己的实验心得分享出来,菜鸟一个,大神轻喷。若有错误地方欢迎指正,感谢阅读。