1.MQTT 入門介紹
MQTT(Message Queuing Telemetry Transport,消息隊列遙測傳輸協議),是一種基於發佈/訂閱(publish/subscribe)模式的"輕量級"通訊協議,該協議構建於TCP/IP協議上,由IBM在1999年發佈。MQTT最大優點在於,可以以極少的代碼和有限的帶寬,爲連接遠程設備提供實時可靠的消息服務。作爲一種低開銷、低帶寬佔用的即時通訊協議,使其在物聯網、小型設備、移動應用等方面有較廣泛的應用。
MQTT只是一個網絡協議,需要一個消息中間件,目前比較有名的有Mosquitto,Apollo,RabbitMQ,Emqx等,本篇使用Mosquitto,使用的是docker eclipse-mosquitto 鏡像
2.安裝MQTT
用Centos7 + docker部署 MQTT服務,使用下載和關注次數較多的 eclipse-mosquitto 鏡像,https://hub.docker.com/_/eclipse-mosquitto
1.創建目錄和文件
mkdir -p /mosquitto/config
mkdir -p /mosquitto/data
mkdir -p /mosquitto/log
touch /mosquitto/config/mosquitto.conf
touch /mosquitto/log/mosquitto.log
2.初始化配置文件
vi /mosquitto/config/mosquitto.conf,內容如下
persistence true
persistence_location /mosquitto/data
log_dest file /mosquitto/log/mosquitto.log
3.目錄授權
chmod -R 755 /mosquitto
4.運行docker鏡像啓動mqtt
docker run -it --name=mosquitto -p 1883:1883 -p 9001:9001 -v /mosquitto/config/mosquitto.conf:/mosquitto/config/mosquitto.conf -v /mosquitto/data -v /mosquitto/log eclipse-mosquitto
5.添加配置
vi /mosquitto/config/mosquitto.conf
# 關閉匿名模式
allow_anonymous false
# 指定密碼文件
password_file /mosquitto/config/pwfile.conf
6.進入啓動的容器shell命令行:docker exec -it mosquitto sh
7.在容器shell命令行中,利用mosquitto命令設置密碼,才能訪問MQTT
touch /mosquitto/config/pwfile.conf
chmod -R 755 /mosquitto/config/pwfile.conf
# 使用mosquitto_passwd命令創建用戶,第一個lxy是用戶名,第二個lxy是密碼
mosquitto_passwd -b /mosquitto/config/pwfile.conf test test_123
8.重啓mqtt容器:docker restart mosquitto
9.利用MQTT.fx進行連接,下載地址:http://mqttfx.bceapp.com/
安裝MQTT.fx後,設置好連接地址,端口(默認1883),訂閱一個主題,再向此主題Publish
10.mosquitto.conf完整內容如下:
persistence true
persistence_location /mosquitto/data
log_dest file /mosquitto/log/mosquitto.log
allow_anonymous false
password_file /mosquitto/config/pwfile.conf
#如果要讓 js 通過websocket連接,則需要設置protocol爲websockets
#protocol websockets
3.使用MQTT.fx連接
對照上面的第9點,下載mqtt.fx 的windows64位版本,然後安裝,打開軟件,點擊Extras-Edit Connection…
輸入MQTT服務地址,端口,點擊Generate生成一個ClientID,在User Credentials中輸入用戶名和密碼
在Subscribe(訂閱)中輸入一個Topic名稱爲 test,在Publish(發佈)中選中test,輸入內容點擊publish,能在Subscribe的右下角看到發佈的內容
pis:訂閱一個主題,向此主題發佈內容,那麼訂閱者就能收到信息
4.JavaScript使用WebSocket連接 MQTT
想要使用websocket連接mqtt,需要mqtt服務支持websocket協議,
需要在配置文件中添加:protocol websockets
然後重啓docker服務:docker restart mosquitto
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>websocket連接mqtt</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/paho-mqtt/1.0.1/mqttws31.min.js" type="text/javascript"></script>
<script>
var hostname = '192.168.68.134', //'192.168.1.2',
port = 1883,
clientId = 'client-test',
timeout = 10,
keepAlive = 100,
cleanSession = false,
ssl = false,
userName = 'test',
password = 'test_123',
topic = '/test';
client = new Paho.MQTT.Client(hostname, port, clientId);
//建立客戶端實例
var options = {
invocationContext: {
host: hostname,
port: port,
path: client.path,
clientId: clientId
},
timeout: timeout,
keepAliveInterval: keepAlive,
cleanSession: cleanSession,
useSSL: ssl,
userName : 'test',
password : 'test_123',
onSuccess: onConnect,
onFailure: function (e) {
console.log(e);
s = "{time:" + new Date().Format("yyyy-MM-dd hh:mm:ss") + ", onFailure()}";
console.log(s);
}
};
client.connect(options);
//連接服務器並註冊連接成功處理事件
function onConnect() {
console.log("onConnected");
s = "{time:" + new Date().Format("yyyy-MM-dd hh:mm:ss") + ", onConnected()}";
console.log(s);
client.subscribe(topic);
}
client.onConnectionLost = onConnectionLost;
//註冊連接斷開處理事件
client.onMessageArrived = onMessageArrived;
//註冊消息接收處理事件
function onConnectionLost(responseObject) {
console.log(responseObject);
s = "{time:" + new Date().Format("yyyy-MM-dd hh:mm:ss") + ", onConnectionLost()}";
console.log(s);
if (responseObject.errorCode !== 0) {
console.log("onConnectionLost:" + responseObject.errorMessage);
console.log("連接已斷開");
}
}
function onMessageArrived(message) {
s = "{time:" + new Date().Format("yyyy-MM-dd hh:mm:ss") + ", onMessageArrived()}";
console.log(s);
console.log("收到消息:" + message.payloadString);
}
function send() {
var s = document.getElementById("msg").value;
if (s) {
s = "{time:" + new Date().Format("yyyy-MM-dd hh:mm:ss") + ", content:" + (s) + ", from: web console}";
message = new Paho.MQTT.Message(s);
message.destinationName = topic;
client.send(message);
document.getElementById("msg").value = "";
}
}
var count = 0;
function start() {
window.tester = window.setInterval(function () {
if (client.isConnected) {
var s = "{time:" + new Date().Format("yyyy-MM-dd hh:mm:ss") + ", content:" + (count++) +
", from: web console}";
message = new Paho.MQTT.Message(s);
message.destinationName = topic;
client.send(message);
}
}, 1000);
}
function stop() {
window.clearInterval(window.tester);
}
Date.prototype.Format = function (fmt) { //author: meizz
var o = {
"M+": this.getMonth() + 1, //月份
"d+": this.getDate(), //日
"h+": this.getHours(), //小時
"m+": this.getMinutes(), //分
"s+": this.getSeconds(), //秒
"q+": Math.floor((this.getMonth() + 3) / 3), //季度
"S": this.getMilliseconds() //毫秒
};
if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length));
for (var k in o)
if (new RegExp("(" + k + ")").test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[
k]) : (("00" + o[k]).substr(("" + o[k]).length)));
return fmt;
}
</script>
</head>
<body>
<input type="text" id="msg" />
<input type="button" value="Send" onclick="send()" />
<input type="button" value="Start" onclick="start()" />
<input type="button" value="Stop" onclick="stop()" />
</body>
</html>
效果如下,首先會提示連接成功,然後輸入 hello world ,點擊 send ,控制檯會監測輸出發送的信息
不過此版本的MQTT有點問題,要只能tcp連接,要麼只能websocket連接,而且測試發現 移動智能設備無法連接上,因此又找了一個開源 MQTT 服務器 EMQ X,請看下一節