【MQTT】Java SSM開發MQTT,一篇就夠了:服務器搭建+SSM框架容器+web端mqtt.js+arduino ESP8266開發接入
文章目錄
- 【MQTT】Java SSM開發MQTT,一篇就夠了:服務器搭建+SSM框架容器+web端mqtt.js+arduino ESP8266開發接入
- 最常用: win平臺cmd客戶端或Xshell端 常用的mosquitto指令
- 一、關於MQTT
- 二、關於mosquitto
- 三、下載paho.exe,win平臺MQTT調試工具
- 四、win10安裝mosquitto
- 五、win10使用 mosquitto
- 六、linux平臺centOS7 安裝 mosquitto
- 七、關於mosquitto中,內置主題的使用
- 八、融入SSM框架
- 1. pom.xml 導入jar包
- 2.MQTTUtil.class 工具類
- 3. MQTTClientService.class
- 4. BootService.class 由SSM框架加載完成後,啓動
- 5 啓動成功,使用客戶端訂閱發佈測試
- 九、處理web頁面,mqtt.js的使用
- 十、arduino開發 ESP8266 12F 中使用mqtt
最常用: win平臺cmd客戶端或Xshell端 常用的mosquitto指令
- 啓動
mosquitto -c conf.d -v
- 訂閱(
-i
設置名稱 )mosquitto_sub -h 192.168.8.21 -t hello/world -u chen -P chen -v -i chen1
- 發佈
mosquitto_pub -h 192.168.8.21 -u chen -P chen -t hello/world -m HELLO
- 增加用戶(
-c
會清除其他用戶)mosquitto_passwd -c ./passwd.d chen
- 追加用戶
mosquitto_passwd ./passwd.d chen
- 自己的配置可以放到指定目錄下,之後在conf中引用
include_dir /etc/mosquitto/conf
- 關閉防火牆
systemctl stop firewalld.service
一、關於MQTT
MQTT(消息隊列遙測傳輸)是ISO 標準(ISO/IEC PRF 20922)下基於發佈/訂閱範式的消息協議。它工作在 TCP/IP協議族上,是爲硬件性能低下的遠程設備以及網絡狀況糟糕的情況下而設計的發佈/訂閱型消息協議,我選用 mosquitto作爲消息中間件,來搭建自己的MQTTserver服務器。
二、關於mosquitto
是一款實現了消息推送協議 MQTT v3.1/v3.1.1 的開源消息代理軟件,提供輕量級的,支持可發佈/可訂閱的的消息推送模式,使設備對設備之間的短消息通信變得簡單,比如現在應用廣泛的低功耗傳感器, 手機、嵌入式計算機、微型控制器等移動設備。
三、下載paho.exe,win平臺MQTT調試工具
-
paho 用來測試MQTT服務器的主題訂閱和發佈,是個不錯的調試工具.
鏈接:https://pan.baidu.com/s/1gmEIdqWjUSHckAjt6omyAw
提取碼:gn6h -
安裝完成後,paho調試軟件的目錄圖
-
啓動界面
-
paho 調試工具,界面,很簡單實用,可以建立連接,連接MQTT服務器地址和端口號,訂閱主題,發佈主題內容。
-
在選項頁可以設置MQTT的username 和password.
四、win10安裝mosquitto
-
win端下載
鏈接:https://pan.baidu.com/s/1JLevb9LAI2i89892hBqm5Q 提取碼:c20n -
win端安裝過程:
- 雙擊進入安裝頁:
- 注意選擇合適的路徑:
- 安裝完成後,軟件目錄如下:
- 雙擊進入安裝頁:
五、win10使用 mosquitto
-
查看閱讀配置文件 mosquitto.conf ,其實,全是英文988行,看下去也是浪費時間,建議直接跳過。
-
直接點擊mosquitto.exe,會用默認的配置啓動程序,默認端口1883。不建議直接點擊啓動
-
cmd控制檯啓動mosquitto
-
進入mosquitto 安裝目錄下
-
在地址欄,直接輸入cmd,之後回傳確定,進入目錄下的CMD控制檯
-
新建 conf.d 文本文檔, 後綴 *.d 我這裏定義爲自己的配置文件,目的是區分系統配置。
-
寫入一下配置:
# 設置是否可以匿名登錄 allow_anonymous false # MQTT服務的端口 port 1883 # 配置websocket接入的兩行: listener 9001 protocol websockets
-
CMD控制端啓動
mosquitto -c conf.d -v
-
測試TCP連接服務
連接地址tcp://localhost:1883
訂閱test主題
之後發佈test主題內容HelloWorld,因爲本機客戶端有訂閱test,也就能收到自己發佈的
服務端收到對應主題訂閱處理轉發,測試通過。
-
測試通過websocket協議連接服務
使用在線websocket測試頁,:http://mqtt.p2hp.com/websocket/
訂閱和發佈test主題,消息爲Hello from websocket
,發送顯示頁如下:
原win10 paho客戶端也接收到消息:
-
測試完畢,這樣的話,MQTT 、mosquitto 基礎搭建和測試就已經完成。
至於 設置用戶賬號和密碼、設置訪問的主題控制,就很簡單了。 -
設置連接MQTT服務器的用戶的賬號和密碼
新建passwd.d 空白文本文件:
CMD控制檯,設置賬號和密碼:我設置的賬號爲 chen。之後輸入密碼,和確認密碼。
mosquitto_passwd passwd.d chen
打開passwd.d 文本,生成了賬號chen,和加密的密碼值,也就完成了生成用戶賬號和密碼。
chen:$6$P7bJLkI5DbwZ6Bbt$RGBz39ubQSWMSt4Va7+e3nAmNEnil3/GRVyaiuKoPdIVnyC4HaIZoICYlk4PtpYNxEwbybZtjFqCtTNXdpC07A==
-
測試賬號和密碼
使用賬號密碼連接成功:
故意使用錯誤賬號密碼連接失敗:
驗證完畢。 -
設置主題配置文件
新建acl.d
寫入配置:# 設置用戶 chen 有讀取/訂閱 主題 hello/world 的權限 user chen topic read hello/world # 設置用戶 chen 有寫入/發佈 主題 hello/world 的權限 user chen topic write hello/world # 若不加第一行user chen ,直接設置 topic ,就是對所有用戶生效 # topic write hh # topic read hh
修改conf.d,添加
acl_file acl.d
配置#設置用戶的主題權限 acl_file acl.d
-
重啓 mosquitto 服務端,進行連接測試
發佈test 主題,被拒絕:
發佈hello/world 主題,成功
驗證完畢!
-
六、linux平臺centOS7 安裝 mosquitto
推薦一種安裝mosquitto 最爲簡單的方式:通過EPEL 軟件庫安裝
-
添加EPEL軟件庫
yum install https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
-
查看EPEL軟件庫結果(肯能會耗費些時間,可以跳過):
yum repolist all | grep enabled
-
查看 mosquitto軟件包列表(可以跳過)
yum list all | grep mosquitto
-
可以查看mosquitto 相關信息(可以跳過):
yum info mosquitto
-
安裝 mosquitto 軟件包:
yum install mosquitto
全部yes 安裝完成 !
-
查看安裝結果,可以看到版本號:
yum list installed | grep mosquitto
-
默認安裝的配置文件存放在
/etc/mosquitto
下
-
在這個目錄下,建立自己的配置文件
conf.d passwd.d acl.d
conf.d
#設置是否可以匿名登錄 allow_anonymous false # MQTT服務的端口 port 1883 # 配置websocket接入的兩行: listener 9001 protocol websockets #設置用戶賬號密碼 password_file /etc/mosquitto/passwd.d #設置用戶的主題權限 acl_file /etc/mosquitto/acl.d
passwd.d
爲空就行,稍後指令生成
acl.d
#設置是否可以匿名登錄 # 設置用戶 chen 有讀取/訂閱 主題 hello/world 的權限 user chen topic read hello/world # 設置用戶 chen 有寫入/發佈 主題 hello/world 的權限 user chen topic write hello/world # 若不加第一行user chen ,直接設置 topic ,就是對所有用戶生效 # topic write hh # topic read hh
-
生成用戶賬號密碼:
mosquitto_passwd ./passwd.d chen
-
啓動mosquitto
mosquitto -c conf.d -v
-c 爲使用 conf.d 配置文件, -v 爲顯示詳細日誌 -d 爲 後臺運行
-d 後臺啓動,結束的話直接 kill -9 1400 [root@pipi mosquitto]# mosquitto -c conf.d -v -d [root@pipi mosquitto]# ps -ef|grep mosquitto mosquit+ 1400 1 0 17:39 ? 00:00:00 mosquitto -c conf.d -v -d root 1402 952 0 17:39 pts/0 00:00:00 grep --color=auto mosquitto [root@pipi mosquitto]# kill -9 1400 [root@pipi mosquitto]#
-
注意打開1883 9001 端口,或者測試時直接關閉防火牆
systemctl stop firewalld.service
-
設置賬號密碼後,連接測試通過。
-
web頁面端測試,websocket連接通過 url頁面地址:
七、關於mosquitto中,內置主題的使用
很簡單 ,相對於正常主題,使用即可:如
訂閱mosquitto服務器狀態各主題,注意放開用戶的相應權限。
MQTT客戶端可以通過訂閱位於$SYS層次下的主題來查看mosquitto服務器的狀態信息。標記爲Static的主題對於每一次訂閱只發布一次。其它所有主題每隔sys_interval(在mosquitto.conf文件或conf.d中配置)秒更新發布。如果sys_interval設置爲0,系統就不發佈更新。
$SYS中各主題說明如下:
$SYS/broker/bytes/received
自服務器啓動以來共接收的字節數
$SYS/broker/bytes/sent
自服務器啓動以來共發送的字節數
$SYS/broker/clients/connected,
$SYS/broker/clients/active (1.4版本已取消)
當前連接的客戶端數量
$SYS/broker/clients/expired
超過有效期被斷開連接的客戶端數量,有效期通過persistent_client_expiration參數設置。
$SYS/broker/clients/disconnected,
$SYS/broker/clients/inactive (1.4版本已取消)
註冊到服務器上的持久連接(clean seesion爲假)但當前斷開的客戶端數量
$SYS/broker/clients/maximum
服務器同一時間連接的最大客戶端數量
$SYS/broker/clients/total
有效和無效連接、註冊到服務器上的總數。
$SYS/broker/connection/#
如果服務器設置了橋接,系統會提供一個主題來標識連接狀態,默認使用$SYS/broker/connection/,
如果主題值爲1表示連接激活,如果爲0表示連接沒有激活。
$SYS/broker/heap/current size
Mosquitto正在使用的堆內存大小。注意這個主題是否可以使用取決於系統編譯時的相關參數設置。
$SYS/broker/heap/maximum size
Mosquitto使用的最大堆內存。這個參數是否有效也取決於系統編譯時的相關參數設置。
$SYS/broker/load/connections/+
不同時間段內服務器接收到的connections包的平均數。最後的“+”可是1min,5min,15min。
分別表示1分鐘,5分鐘,15分鐘的平均數。
$SYS/broker/load/bytes/received/+
不同時間段內服務器接收數據的平均字節數。最後的“+”可是1min,5min,15min。
$SYS/broker/load/bytes/sent/+
不同時間段內服務器發送數據的平均字節數。最後的“+”可是1min,5min,15min。
$SYS/broker/load/messages/received/+
不同時間段內服務器接收到的所有類型消息的平均數。最後的“+”可是1min,5min,15min。
$SYS/broker/load/messages/sent/+
不同時間段內服務器發送的所有類型的消息的平均數。最後的“+”可是1min,5min,15min。
$SYS/broker/load/publish/dropped/+
不同時間段內服務器丟棄的消息的平均數,這表明了那些持久連接但與服務器斷開的客戶端失去消息的速率。
最後的“+”可是1min,5min,15min。
$SYS/broker/load/publish/received/+
不同時間段內服務器接收的發佈消息的平均數。最後的“+”可是1min,5min,15min。
$SYS/broker/load/publish/sent/+
不同時間段內服務器發送的發佈消息的平均數。最後的“+”可是1min,5min,15min。
$SYS/broker/load/sockets/+
不同時間段內服務器打開的socket連接的平均數。最後的“+”可是1min,5min,15min。
$SYS/broker/messages/inflight
等待確認的Qos>0的消息的數量。
$SYS/broker/messages/received
自服務器啓動以來接收的所有類型的消息總數。
$SYS/broker/messages/sent
自服務器啓動以來發送的所有類型的消息總數。
$SYS/broker/messages/stored
服務器存儲的消息的總數,包括保留消息和持久連接客戶端的消息隊列中的消息數。
$SYS/broker/publish/messages/dropped
由於inflight/queuing限制而直接丟棄的消息的總數,
相關設置請查看mosquitto.conf中max_inflight_messages 和max_queued_messages參數。
$SYS/broker/publish/messages/received
自服務器啓動以來接收的發佈消息的總數。
$SYS/broker/publish/messages/sent
自服務器啓動以來發送的發佈消息的總數。
$SYS/broker/retained messages/count
服務器保留的消息總數。
$SYS/broker/subscriptions/count
服務器訂閱主題總數。
$SYS/broker/timestamp
Mosquitto軟件build的詳細時間(Static)。
$SYS/broker/uptime
Mosquitto啓動時長(單位:秒)。
$SYS/broker/version
Mosquitto軟件版本號(Static)。
至此,服務器配置,基本完畢,你也算是MQTT的小高手了
之後就是Java SSM 框架的融合 和 web端適用 mqtt.js 連接的相關搭建。
八、融入SSM框架
1. pom.xml 導入jar包
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-mqtt</artifactId>
<version>4.3.9.RELEASE</version>
</dependency>
<dependency>
<groupId>org.eclipse.paho</groupId>
<artifactId>org.eclipse.paho.client.mqttv3</artifactId>
<version>1.2.2</version>
</dependency>
2.MQTTUtil.class 工具類
主要用來處理髮布方法pub
package com.chen.manage.mqtt_test;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.eclipse.paho.client.mqttv3.MqttTopic;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
/**
* MQTT 基礎工具類 ,主要用來發布消息,pub功能;<br>
* 相關配置文件,可以抽取到配置文件中,由spring導入。
*
* @author chen
*/
public class MQTTUtil {
// tcp://MQTT安裝的服務器地址:MQTT定義的端口號
public static final String HOST = "tcp://192.168.8.19:1883";
// 定義MQTT的ID,可以在MQTT服務配置中指定
private static final String clientid = "myManageMQTTServer";
private MqttClient client;
private MqttTopic mqttTopic;
private String userName = "chen";
private String passWord = "chen";
/**
* 構造函數
*
* @throws MqttException
*/
public MQTTUtil(String topic) throws MqttException {
// MemoryPersistence設置clientid的保存形式,默認爲以內存保存
client = new MqttClient(HOST, clientid, new MemoryPersistence());
connect(topic);
}
/**
* 用來連接服務器
*/
private void connect(String topic) {
MqttConnectOptions options = new MqttConnectOptions();
options.setCleanSession(false);
options.setUserName(userName);
options.setPassword(passWord.toCharArray());
// 設置超時時間
options.setConnectionTimeout(10);
// 設置會話心跳時間
options.setKeepAliveInterval(20);
try {
// 設置回調
client.setCallback(new PushCallback());
client.connect(options);
mqttTopic = client.getTopic(topic);
} catch (Exception e) {
e.printStackTrace();
}
}
// 發送消息並獲取回執
public void publish(MqttMessage message) throws Exception {
MqttDeliveryToken token = mqttTopic.publish(message);
token.waitForCompletion();
System.out.println("message is published completely! " + token.isComplete());
System.out.println("messageId:" + token.getMessageId());
token.getResponse();
if (client.isConnected())
client.disconnect(10000);
System.out.print("Disconnected: delivery token \"" + token.hashCode() );
System.out.println("\" received: " + token.isComplete());
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassWord() {
return passWord;
}
public void setPassWord(String passWord) {
this.passWord = passWord;
}
public MqttTopic getMqttTopic() {
return mqttTopic;
}
public void setMqttTopic(MqttTopic mqttTopic) {
this.mqttTopic = mqttTopic;
}
}
3. MQTTClientService.class
主要當做一個客戶端在SSM中運行,處理回調和返回訂閱消息
package com.chen.manage.mqtt_test;
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.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.chen.manage.pojo.Admin;
import com.chen.manage.service.AdminService;
/**
* 模擬一個客戶端接收消息
* @author chen
*/
@Service
public class MQTTClientService {
public static String str = "";
public static final String HOST = "tcp://192.168.8.19:1883";
// 服務器內置主題,用來監測當前服務器上連接的客戶端數量($SYS/broker/clients/connected)
// public static final String TOPIC1 = "$SYS/broker/clients/connected";
public static final String TOPIC1 = "topic1";
private static final String clientid = "client1";
private MqttClient client;
private MqttConnectOptions options;
private String userName = "chen";
private String passWord = "chen";
@Autowired
private AdminService adminService;
public void start() {
// host爲主機名,clientid即連接MQTT的客戶端ID,一般以唯一標識符表示,
//MemoryPersistence設置clientid的保存形式,默認爲以內存保存
try {
client = new MqttClient(HOST, clientid, new MemoryPersistence());
// MQTT的連接設置
options = new MqttConnectOptions();
// 設置是否清空session,這裏如果設置爲false表示服務器會保留客戶端的連接記錄,
//設置爲true表示每次連接到服務器都以新的身份連接
options.setCleanSession(false);
// 設置連接的用戶名
options.setUserName(userName);
// 設置連接的密碼
options.setPassword(passWord.toCharArray());
// 設置超時時間 單位爲秒
options.setConnectionTimeout(10);
// 設置會話心跳時間 單位爲秒 服務器會每隔1.5*20秒的時間向客戶端發送個消息
//判斷客戶端是否在線,但這個方法並沒有重連的機制
options.setKeepAliveInterval(20);
// 設置回調
client.setCallback(new MqttCallback() {
public void connectionLost(Throwable cause) {
// 連接丟失後,一般在這裏面進行重連,
System.out.println("連接斷開,可以做重連,只是簡單處理:10秒後重連");
try {
Thread.sleep(10 * 1000);
start();
} catch (Exception e) {
e.printStackTrace();
}
}
public void deliveryComplete(IMqttDeliveryToken token) {
System.out.println("deliveryComplete---------" + token.isComplete());
}
public void messageArrived(String topic, MqttMessage message) {
try {
str = message.toString();
System.out.println(" 從服務器收到的消息爲:" + message.toString());
Admin admin = adminService.queryById(Integer.valueOf(str));
if (admin != null) {
//查詢數據庫,如果有用戶數據,則返回用戶的相關屬性,這裏用手機號示例:
System.out.println(admin.getPhone());
//使用MQTT發送主題消息
MQTTUtil mqttUtil = new MQTTUtil("topic11");
MqttMessage message1 = new MqttMessage();
message1.setId(1);
message1.setQos(1);
message1.setPayload(admin.getPhone().getBytes());
mqttUtil.publish(message1);
} else {
System.out.println("admin is null");
}
} catch (Exception e) {
e.printStackTrace();
}
}
});
// MqttTopic topic = client.getTopic(TOPIC1);
// setWill方法,設置最終端口的通知消息:如果項目中需要知道客戶端是否掉線可以調用該方法。
// options.setWill(topic, "close".getBytes(), 2, true); //遺囑
client.connect(options);
// 訂閱消息
int[] Qos = {1};
String[] topic1 = {TOPIC1};
client.subscribe(topic1, Qos);
} catch (MqttException e1) {
e1.printStackTrace();
}
}
}
4. BootService.class 由SSM框架加載完成後,啓動
主要用來啓動mqttClientService.start()
;方法,SSM加載完成後執行此方法。
package com.chen.manage.service;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.chen.manage.mqtt_test.MQTTClientService;
import com.chen.manage.netty2.EchoServer;
import com.chen.manage.nettyudp.NettyUdpServer;
import io.netty.channel.ChannelFuture;
/**
* 系統啓動後執行
*
* @author Fitz
*
*/
@Service
public class BootService implements InitializingBean {
//
// @Autowired
// private NettyTCPServer nettyTCPServer;
@Autowired
private EchoServer echoServer;
@Autowired
private NettyUdpServer nettyUdpServer;
@Autowired
private MQTTClientService mqttClientService;
@Override
public void afterPropertiesSet() throws Exception {
mqttClientService.start();
}
}
5 啓動成功,使用客戶端訂閱發佈測試
運行ok
九、處理web頁面,mqtt.js的使用
1. paho-mqtt.js下載
鏈接:https://pan.baidu.com/s/1R2j1sbOhTL7Fak132b2crA
提取碼:8zuz
2. jquery.min.js下載
鏈接:https://pan.baidu.com/s/1OIoDrBf63cmexOD_xSgMvg
提取碼:w6eg
3. my_good_mqtt_test.jsp 實現調用
鏈接:https://pan.baidu.com/s/1awEe5rAwQNaEgLpPWeqC_Q
提取碼:8fnm
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title></title>
<meta charset="utf-8" />
<script src="/js_mqtt/jquery.min.js"></script>
<script src="/js_mqtt/paho-mqtt.js"></script>
<script type="text/javascript">
//所有主題
var allTopics = [
{ "Topic": "topic1", "Describe": "topic1" },
{ "Topic": "/data/alarm", "Describe": "警示" },
{ "Topic": "/data/message", "Describe": "消息" },
{ "Topic": "/data/notify", "Describe": "通知" }
];
//選中訂閱主題
var selectedTopics = [];
//選中發佈主題
var currentTopic;
//客戶端選項
var option = {
"ServerUri": "192.168.8.19",
"ServerPort": 9001,
"UserName": "chen",
"Password": "chen",
"ClientId": "",
"TimeOut": 5,
"KeepAlive": 100,
"CleanSession": false,
"SSL":false
}
//客戶端
var client;
$(function () {
BindSubTopics(allTopics);
BindPubTopics(allTopics);
//訂閱主題選中事件
$("#subTopics input[type=checkbox]").on("click", function () {
var t = $(this).val();
var topic;
for(var i in allTopics){
var tmp = allTopics[i];
if (tmp.Topic == t) {
topic = tmp;
}
}
if ($(this).is(":checked")) {//選中
selectedTopics.push(topic);
}
else {//取消選擇
if(selectedTopics.length>0){
for(var i in selectedTopics){
var tmp = selectedTopics[i];
if (tmp.Topic == t) {
selectedTopics.splice(i, 1);
}
}
}
}
});
//發佈主題選中事件
$("#pubTopics").on("change", function () {
var d = $("#pubTopics option:selected").text();
var t = $("#pubTopics").val();
currentTopic = { "Topic": t, "Describe": d }
console.log(currentTopic);
});
//連接按鈕點擊事件
$("#btnConnect").on("click", function () {
if ($("#txtIp").val()!="") {
option.ServerUri = $("#txtIp").val();
}
else {
alert("請輸入服務端IP!");
return;
}
if($("#txtPort").val()!=""){
option.ServerPort = Number($("#txtPort").val());
}
else {
alert("請輸入端口號!");
return;
}
option.ClientId = guid();
client = new Paho.Client(option.ServerUri, option.ServerPort, option.ClientId)
client.onConnectionLost = onConnectionLost;
client.onMessageArrived = onMessageArrived;
client.connect({
invocationContext: {
host: option.ServerUri,//IP地址
port: option.ServerPort,//端口號
path: client.path,
clientId: option.ClientId//標識
},
timeout: option.TimeOut,//連接超時時間
keepAliveInterval: option.KeepAlive,//心跳間隔
cleanSession: option.CleanSession,//是否清理Session
useSSL: option.SSL,//是否啓用SSL
userName: option.UserName, //用戶名
password: option.Password, //密碼
onSuccess: onConnect,//連接成功回調事件
onFailure: onError//連接失敗回調事件
});
});
//斷開按鈕點擊事件
$("#btnDisconnect").on("click", function () {
client = null;
enable($("#btnConnect"), true);
enable($("#btnDisconnect"), false);
enable($("#btnPublish"), false);
enable($("#btnSubscribe"), false);
});
//訂閱按鈕點擊事件
$("#btnSubscribe").on("click", function () {
if (!client) {
alert("請連接服務端");
return;
}
if(selectedTopics.length==0){
alert("請選擇要訂閱的主題!");
return;
}
var msg = "";
for(var i in selectedTopics){
var t = selectedTopics[i];
client.subscribe(t.Topic);
msg+=t.Topic+";"
}
WriteToStatus("成功訂閱主題:" + msg);
});
//發佈按鈕點擊事件
$("#btnPublish").on("click", function () {
if(!client){
alert("請連接服務端");
return;
}
if (!currentTopic) {
alert("請選擇要發佈的主題!");
return;
}
if($("#txtContent").val()==""){
alert("請輸入要發佈的內容");
return;
}
var message = new Paho.Message($("#txtContent").val());
message.destinationName = currentTopic.Topic;
client.send(message);
WriteToStatus("發佈了主題爲" + currentTopic.Topic + "的消息:" + $("#txtContent").val())
});
});
//連接成功事件
function onConnect() {
WriteToStatus("連接成功!")
enable($("#btnConnect"), false);
enable($("#btnDisconnect"), true);
enable($("#btnPublish"), true);
enable($("#btnSubscribe"), true);
}
//連接失敗事件
function onError(e) {
WriteToStatus("連接失敗:" + e)
enable($("#btnConnect"), true);
enable($("#btnDisconnect"), false);
enable($("#btnPublish"), false);
enable($("#btnSubscribe"), false);
}
//連接斷開事件
function onConnectionLost(e) {
if (e.errorCode !== 0) {
WriteToStatus("連接異常斷開:" + e.errorMessage);
enable($("#btnConnect"), true);
enable($("#btnDisconnect"), false);
enable($("#btnPublish"), false);
enable($("#btnSubscribe"), false);
}
}
//接收消息事件
function onMessageArrived(data) {
WriteToStatus("收到消息:" + data.payloadString);
}
//綁定訂閱主題
function BindSubTopics(topics) {
var html = "";
for (var i = 0; i < topics.length;i++){
var topic = topics[i];
html += topic.Describe;
html += '<input type="checkbox" value="'+topic.Topic+'"/>';
}
$("#subTopics").html(html);
}
//綁定發佈主題
function BindPubTopics(topics) {
var html = "";
for (var i = 0; i < topics.length; i++) {
var topic = topics[i];
html += '<option value="' + topic.Topic + '">' + topic.Describe + '</option>';
}
$("#pubTopics").html(html);
}
//狀態輸出
function WriteToStatus(data) {
var now = new Date();
var message = '[' + now.toLocaleTimeString() + ']' + data;
console.log(message);
$("#logResult").append('<li>' + message + '</li>');
}
//生成GUID
function guid() {
function S4() {
return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
}
return (S4() + S4() + "-" + S4() + "-" + S4() + "-" + S4() + "-" + S4() + S4() + S4());
}
//切換按鈕狀態
function enable(button,enabled) {
if (enabled) {
button.removeAttr("disabled");
}
else {
button.attr("disabled", "disabled");
}
}
</script>
</head>
<body>
<table>
<tr>
<td></td>
<td><input id="txtIp" type="text" value="192.168.8.19"/></td>
<td><input id="txtPort" type="text" value="9001"/></td>
<td><input id="btnConnect" type="button" value="連接"/></td>
<td><input id="btnDisconnect" type="button" value="斷開" disabled="disabled"/></td>
<td></td>
</tr>
<tr>
<td></td>
<td colspan="3">
<div id="subTopics">
</div>
</td>
<td><input id="btnSubscribe" type="button" value="訂閱" disabled="disabled"/></td>
<td></td>
</tr>
<tr>
<td></td>
<td colspan="4">
<ul id="logResult"></ul>
</td>
<td></td>
</tr>
<tr>
<td></td>
<td>
<select id="pubTopics">
</select>
</td>
<td colspan="2"><input id="txtContent" type="text"/></td>
<td><input id="btnPublish" type="button" value="發佈" disabled="disabled"/></td>
<td></td>
</tr>
</table>
</body>
</html>
4. 測試成功
十、arduino開發 ESP8266 12F 中使用mqtt
1.首選項,加載開發板
http://arduino.esp8266.com/stable/package_esp8266com_index.json
2. 加載開發板庫
3. 選擇開發板WeMos D1R1
4. 加載 mqtt庫,這裏使用 PubSubClient
5. mqtt_esp8266.ino, arduino燒錄硬件,硬件即可完成MQTT通信。
K02_mqtt_esp8266.ino
鏈接:https://pan.baidu.com/s/1WuvgZ7mKqA91Wfd90JpzDw
提取碼:og2n
/*
Basic ESP8266 MQTT example
This sketch demonstrates the capabilities of the pubsub library in combination
with the ESP8266 board/library.
It connects to an MQTT server then:
- publishes "hello world" to the topic "outTopic" every two seconds
- subscribes to the topic "inTopic", printing out any messages
it receives. NB - it assumes the received payloads are strings not binary
- If the first character of the topic "inTopic" is an 1, switch ON the ESP Led,
else switch it off
It will reconnect to the server if the connection is lost using a blocking
reconnect function. See the 'mqtt_reconnect_nonblocking' example for how to
achieve the same result without blocking the main loop.
To install the ESP8266 board, (using Arduino 1.6.4+):
- Add the following 3rd party board manager
- under "File -> Preferences -> Additional Boards Manager URLs":
http://arduino.esp8266.com/stable/package_esp8266com_index.json
- Open the "Tools -> Board -> Board Manager" and click install for the ESP8266"
- Select your ESP8266 in "Tools -> Board"
*/
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
// Update these with values suitable for your network.
const char* ssid = "Iot Lab";
const char* password = "WXshiNNN";
const char* mqtt_server = "192.168.8.14";
WiFiClient espClient;
PubSubClient client(espClient);
long lastMsg = 0;
char msg[50];
int value = 0;
void setup_wifi() {
delay(10);
// We start by connecting to a WiFi network
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
randomSeed(micros());
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
}
void callback(char* topic, byte* payload, unsigned int length) {
Serial.print("Message arrived [");
Serial.print(topic);
Serial.print("] ");
for (int i = 0; i < length; i++) {
Serial.print((char)payload[i]);
}
Serial.println();
// Switch on the LED if an 1 was received as first character
if ((char)payload[0] == '1') {
// Turn the LED on (Note that LOW is the voltage level
digitalWrite(BUILTIN_LED, LOW);
// but actually the LED is on; this is because
// it is active low on the ESP-01)
} else {
// Turn the LED off by making the voltage HIGH
digitalWrite(BUILTIN_LED, HIGH);
}
}
void reconnect() {
// Loop until we're reconnected
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
// Create a random client ID
String clientId = "ESP8266Client-";
clientId += String(random(0xffff), HEX);
// Attempt to connect
if (client.connect(clientId.c_str())) {
Serial.println("connected");
// Once connected, publish an announcement...
client.publish("outTopic", "hello world");
// ... and resubscribe //硬件訂閱這個主題,其他發佈到這個主題,就可以通信
//接收其他程序的消息:
client.subscribe("inTopic");
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
// Wait 5 seconds before retrying
delay(5000);
}
}
}
void setup() {
// Initialize the BUILTIN_LED pin as an output
pinMode(BUILTIN_LED, OUTPUT);
Serial.begin(115200);
setup_wifi();
client.setServer(mqtt_server, 8883);
client.setCallback(callback);
}
void loop() {
if (!client.connected()) {
reconnect();
}
client.loop();
long now = millis();
if (now - lastMsg > 2000) {
lastMsg = now;
++value;
snprintf (msg, 50, "hello world #%ld", value);
Serial.print("Publish message: ");
Serial.println(msg);
//向外發送消息數據
client.publish("outTopic", msg);
}
}
結束 2020-1-3
看見即是有緣,多謝關注,多謝私信交流,多謝推薦技術好文。 在前進的路上,我們永不停息!