MQTT服务端
我做的这个App是作为MQTT的一个客户端,因此必须要有一个MQTT服务端来让它连接上,之后就可以发布、订阅消息了;有一些公共MQTT服务器(可以自行百度),我在腾讯云创建了一个自己的MQTT服务端,下面介绍如何创建。
登录腾讯云。进入控制台,在搜索框搜索”物联网通信“
点击创建新产品(可以把产品理解为一个MQTT服务器),我之前已经创建过一些了,所以下面显示有几个产品
填写相关信息
然后点击自己刚新建的产品,进入创建一个新设备
我们的物理设备要连接刚新建的”MQTT服务器“,需要提供一些验证信息,这些信息在我们新建设备之后可以得到
点击我们刚新建的设备,可以查看设备的信息,其中设备密钥是我们的物理设备连接时需要的信息
下面用桌面软件MQTT.fx
尝试连接,打开软件,如左图:
5/6/7步需要自己刚才新建的产品、设备密钥信息,根据官方文档,如右图:
1 2 3
| Broker Address: [产品ID].iotcloud.tencentdevices.com Broker Port: 1883或8883 Client ID: 产品ID+设备名 (也可以直接复制新建设备时设备密钥的Client ID)
|
产品ID |
设备密钥 |
|
|
接下来填写用户信息,然后点击ok保存即可
填写信息 |
查看自己设备的用户名、密码信息(最后2个就是) |
|
|
接下来可以进行订阅和发布主题了,首先点击connect连接
主题不能随便填,首先回到腾讯云刚新建的设备,点击设备进去,默认提供3个主题,其中2个一个只能发布,一个只能订阅,只有一个既能发布也能订阅,当然,可以自己新建几个主题,根据自己需要
把发布主题粘贴到MQTT.fx软件,就可以发布主题了,发布后在产品(不是设备)的云日志可以查看刚发布的内容
订阅也是这样,订阅后需要在腾讯云 设备
界面选择在线调试,然后选择MQTT.fx订阅的主题,发送消息后MQTT.fx即可收到消息,此处不演示
Android MQTT客户端
代码工程已开源,GitHub请点击前去下载,Gitee请点击前去下载
使用Android Studio(自行百度下载),新建一个空白工程
添加MQTT依赖
在自己[project]下的 build.gradle
添加如下代码
1 2 3 4 5 6 7 8
| repositories { google() mavenCentral() maven { url "https://repo.eclipse.org/content/repositories/paho-releases/" } }
|
在[project]/app下的build.gradle
添加如下代码
1 2 3 4
| dependencies { compile 'org.eclipse.paho:org.eclipse.paho.android.service:1.1.1' compile 'org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.1.1' }
|
然后选择顶部弹出的 Sync Now
信息
撸代码
修改AndroidManifest.xml
,添加权限
1 2 3 4
| <uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
修改视图文件activity_main.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258
| <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" >
<TextView android:layout_marginTop="20dp" android:layout_marginLeft="20dp" android:layout_marginBottom="10dp" android:id="@+id/house_env" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="室内环境" android:textStyle="bold" android:textSize="20dp" /> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <TextView android:id="@+id/show_temp" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="10dp" android:layout_marginLeft="20dp" android:layout_marginBottom="10dp"
android:text="温度(°C)" android:textSize="20dp" />
<TextView android:id="@+id/temp" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="10dp" android:layout_marginLeft="20dp" android:layout_marginBottom="10dp" android:text="0" android:textSize="20dp" />
<TextView android:id="@+id/show_humi" android:layout_width="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="10dp" android:layout_marginLeft="20dp" android:layout_marginBottom="10dp" android:text="湿度(%RH)" android:textSize="20dp" /> <TextView android:id="@+id/humi" android:layout_width="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="10dp" android:layout_marginLeft="20dp" android:layout_marginBottom="10dp" android:text="0" android:textSize="20dp" />
</LinearLayout>
<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" > <TextView android:id="@+id/show_light" android:layout_width="wrap_content" android:layout_height="wrap_content"
android:layout_marginLeft="20dp" android:layout_marginTop="10dp" android:layout_marginBottom="10dp" android:text="光照强度" android:textSize="20dp" /> <TextView android:id="@+id/light" android:layout_width="wrap_content" android:layout_height="wrap_content"
android:layout_marginLeft="20dp" android:layout_marginTop="10dp" android:layout_marginBottom="10dp" android:text="0" android:textSize="20dp" />
</LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal">
<TextView android:id="@+id/ledsta1" android:layout_width="wrap_content" android:layout_height="wrap_content"
android:layout_marginLeft="20dp" android:layout_marginTop="10dp" android:layout_marginBottom="10dp" android:text="LED状态" android:textSize="20dp" /> <TextView android:id="@+id/ledsta2" android:layout_width="wrap_content" android:layout_height="wrap_content"
android:layout_marginLeft="20dp" android:layout_marginTop="10dp" android:layout_marginBottom="10dp" android:text="关" android:textSize="20dp" />
<TextView android:id="@+id/beepsta1" android:layout_width="wrap_content" android:layout_height="wrap_content"
android:layout_marginLeft="20dp" android:layout_marginTop="10dp" android:layout_marginBottom="10dp" android:text="蜂鸣器状态" android:textSize="20dp" /> <TextView android:id="@+id/beepsta2" android:layout_width="wrap_content" android:layout_height="wrap_content"
android:layout_marginLeft="20dp" android:layout_marginTop="10dp" android:layout_marginBottom="10dp" android:text="关" android:textSize="20dp" /> </LinearLayout> <TextView android:id="@+id/sets" android:layout_column="1" android:layout_width="wrap_content" android:layout_height="wrap_content"
android:layout_marginLeft="20dp" android:layout_marginTop="10dp" android:layout_marginBottom="10dp" android:text="设置" android:textStyle="bold" android:textSize="20dp" />
<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal">
<TextView android:id="@+id/set_temp" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="20dp" android:layout_marginTop="10dp" android:layout_marginBottom="10dp" android:text="报警温度(当前温度超过该值蜂鸣器将报警)" android:textSize="15dp" />
<TextView android:id="@+id/seekbarval1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="10dp" android:layout_marginLeft="10dp" android:text="40"/> </LinearLayout> <SeekBar android:id="@+id/seekBar1" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="10dp" android:layout_marginBottom="10dp" android:layout_gravity="center" android:max="100" android:progress="40"/>
<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal">
<TextView android:id="@+id/set_tlight" android:layout_width="wrap_content" android:layout_height="wrap_content"
android:layout_marginLeft="20dp" android:layout_marginTop="10dp" android:layout_marginBottom="10dp" android:text="最低光照(当前光照小于该值将点亮led灯)" android:textSize="15dp" />
<TextView android:id="@+id/seekbarval2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="10dp" android:layout_marginLeft="20dp" android:text="12"/> </LinearLayout> <SeekBar android:id="@+id/seekBar2" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="10dp" android:layout_marginBottom="10dp" android:layout_gravity="center" android:max="100" android:progress="12"/>
<LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content">
</LinearLayout> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" > <Button android:layout_marginLeft="100dp" android:layout_marginTop="20dp" android:id="@+id/connectbtn" android:layout_height="wrap_content" android:layout_width="wrap_content" android:textColor="@color/white" android:text="连接"/>
<Button android:layout_marginTop="20dp" android:layout_marginRight="20dp" android:layout_marginLeft="20dp" android:id="@+id/exitbtn" android:layout_height="wrap_content" android:layout_width="wrap_content" android:textColor="@color/white" android:text="退出"/>
</LinearLayout> <TextView android:layout_margin="5dp" android:id="@+id/msgTxt" android:layout_height="wrap_content" android:layout_width="wrap_content" android:scrollbars="vertical" android:text=""/>
</LinearLayout>
|
效果图
接下来修改MainActivity.java
,添加控制操作,上面只是完成一个界面的创建
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288
| package com.ajream.mqttdemo4;
import android.annotation.SuppressLint; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.widget.Button; import android.widget.SeekBar; import android.widget.TextView; import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken; import org.eclipse.paho.client.mqttv3.MqttCallback; import org.eclipse.paho.client.mqttv3.MqttClient; import org.eclipse.paho.client.mqttv3.MqttConnectOptions; import org.eclipse.paho.client.mqttv3.MqttException; import org.eclipse.paho.client.mqttv3.MqttMessage; import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence; import org.json.JSONException; import org.json.JSONObject;
import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit;
public class MainActivity extends AppCompatActivity {
private Button connectbtn; private Button exitbtn;
private TextView temptv; private TextView humitv; private TextView lighttv; private TextView ledtv; private TextView beeptv; private TextView bar1tv; private TextView bar2tv; private TextView showmsgtv;
private SeekBar tempbar; private SeekBar lightbar;
private String host = "tcp://xxxxxxx.iotcloud.tencentdevices.com:1883"; private String userName = "xxxxxxxxxx"; private String passWord = "xxxxxxxxxx"; private String mqtt_id = "xxxxxxxxxxxxxxxxxxx"; private String mqtt_sub_topic = "xxxxxxxxxx/AndroidClient/data"; private String mqtt_pub_topic = "xxxxxxxxxx/AndroidClient/data";
private ScheduledExecutorService scheduler; private MqttClient mqttClient; private MqttConnectOptions options; private Handler handler;
private String msgToPublish = ""; private String alarmTempMsg = ""; private String minLightMsg = ""; JSONObject msgGet;
@SuppressLint("HandlerLeak") @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main);
connectbtn = findViewById(R.id.connectbtn); exitbtn = findViewById(R.id.exitbtn); temptv = findViewById(R.id.temp); humitv = findViewById(R.id.humi); lighttv = findViewById(R.id.light); ledtv = findViewById(R.id.ledsta2); beeptv = findViewById(R.id.beepsta2); bar1tv = findViewById(R.id.seekbarval1); bar2tv = findViewById(R.id.seekbarval2); showmsgtv = findViewById(R.id.msgTxt);
tempbar = findViewById(R.id.seekBar1); lightbar = findViewById(R.id.seekBar2);
alarmTempMsg = String.valueOf(tempbar.getProgress()); minLightMsg = String.valueOf(lightbar.getProgress());
connectbtn.setOnClickListener(view -> { Mqtt_init(); startReconnect(); });
exitbtn.setOnClickListener(view -> { android.os.Process.killProcess(android.os.Process.myPid()); });
tempbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { Toast.makeText(MainActivity.this, "设置报警温度为: " + progress, Toast.LENGTH_LONG).show(); bar1tv.setText(check(progress)); alarmTempMsg = check(progress); }
@Override public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override public void onStopTrackingTouch(SeekBar seekBar) {
msgToPublish = "{\"atemp\":\"" + alarmTempMsg + "\",\"mlight\":\"" + minLightMsg+"\"}"; publishMsg(mqtt_pub_topic, msgToPublish);
} });
lightbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { @Override public void onProgressChanged(SeekBar seekBar, int i, boolean b) { Toast.makeText(MainActivity.this, "设置最低光照为: " + i, Toast.LENGTH_LONG).show(); bar2tv.setText(check(i)); minLightMsg = check(i); }
@Override public void onStartTrackingTouch(SeekBar seekBar) { }
@Override public void onStopTrackingTouch(SeekBar seekBar) { msgToPublish = "{\"atemp\":\"" + alarmTempMsg + "\",\"mlight\":\"" + minLightMsg+"\"}"; publishMsg(mqtt_pub_topic, msgToPublish); } });
handler = new Handler() { @SuppressLint("SetTextI18n")
public void handleMessage(Message msg) { super.handleMessage(msg); switch (msg.what) { case 1: break; case 2: break; case 3:
showmsgtv.setText(msg.obj.toString()); JSONObject msgGet = null; try { msgGet = new JSONObject(msg.obj.toString()); temptv.setText(msgGet.get("temp").toString()); humitv.setText(msgGet.get("humi").toString()); lighttv.setText(msgGet.get("light").toString()); if(Integer.parseInt(msgGet.get("ledsta").toString())==0) ledtv.setText("关"); else ledtv.setText("开"); if(msgGet.get("beepsta").toString().charAt(0)=='0') beeptv.setText("关"); else beeptv.setText("开"); } catch (JSONException e) { e.printStackTrace(); } break;
case 30: Toast.makeText(MainActivity.this,"连接失败" ,Toast.LENGTH_SHORT).show(); break; case 31: Toast.makeText(MainActivity.this,"连接成功" ,Toast.LENGTH_SHORT).show(); try { mqttClient.subscribe(mqtt_sub_topic,1); } catch (MqttException e) { e.printStackTrace(); } break; default: break; } } }; }
private String check(int progress) { int curValue = 100 * progress/Math.abs(100); return String.valueOf(curValue); }
private void publishMsg(String topic, String message2) { if (mqttClient == null || !mqttClient.isConnected()) { return; } MqttMessage message = new MqttMessage(); message.setPayload(message2.getBytes()); try { mqttClient.publish(topic, message); } catch (MqttException e) { e.printStackTrace(); } }
private void Mqtt_init() { try { mqttClient = new MqttClient(host, mqtt_id, new MemoryPersistence());
options = new MqttConnectOptions();
options.setCleanSession(false);
options.setUserName(userName);
options.setPassword(passWord.toCharArray());
options.setConnectionTimeout(10); options.setKeepAliveInterval(20);
mqttClient.setCallback(new MqttCallback() { @Override public void connectionLost(Throwable cause) {
} @Override public void deliveryComplete(IMqttDeliveryToken token) { System.out.println("deliveryComplete---------" + token.isComplete()); } @Override public void messageArrived(String topicName, MqttMessage message) throws Exception { System.out.println("getMsg: "); Message msg = new Message(); msg.what = 3; msg.obj = message.toString(); handler.sendMessage(msg); } }); } catch (Exception e) { e.printStackTrace(); } }
private void Mqtt_connect() { new Thread(new Runnable() { @Override public void run() { try { if(!(mqttClient.isConnected())) { mqttClient.connect(options); Message msg = new Message(); msg.what = 31; handler.sendMessage(msg); } } catch (Exception e) { e.printStackTrace(); Message msg = new Message(); msg.what = 30; handler.sendMessage(msg); } } }).start(); } private void startReconnect() { scheduler = Executors.newSingleThreadScheduledExecutor(); scheduler.scheduleAtFixedRate(new Runnable() { @Override public void run() { if (!mqttClient.isConnected()) { Mqtt_connect(); } } }, 0 * 1000, 10 * 1000, TimeUnit.MILLISECONDS); } }
|
来两张运行截图