MQTT.JS是MQTT協議的客戶端庫,用Node.js和瀏覽器編寫的JavaScript編寫。
MQTT.JS是一個開放的開源項目,請參閱貢獻部分,以了解這意味著什麼。
v5.0.0 (07/2023)
new創建MqttClient實例時。v4.0.0 (發布04/2020)刪除了對所有終止節點版本的支持,現在支持節點V12和V14。它還為調試日誌記錄以及一些功能添加而增加了改進。
當破裂的變化時,默認情況下,MQTT.JS客戶端中內置了錯誤處理程序,因此,如果發出任何錯誤並且用戶未在客戶端上創建事件處理程序以解決錯誤,則客戶端不會因未手動錯誤而破壞。此外,典型的TLS錯誤(例如ECONNREFUSED已將ECONNRESET添加到TLS錯誤列表中,該列表將從MQTT.JS客戶端發出,因此可以作為連接錯誤處理。
v3.0.0增加了對MQTT 5的支持,對節點V10.X的支持以及許多修復以提高可靠性。
注意: MQTT V5支持是實驗性的,因為它尚未由經紀人實施。
v2.0.0刪除了對節點v0.8,v0.10和v0.12的支持,並且發送數據包的速度快3倍。它還刪除了v1.0.0中的所有棄用功能,主要是mqtt.createConnection和mqtt.Server 。從v2.0.0來看,重新連接時恢復訂閱,如果clean: true 。 v1.xx現在在LTS中,只要有v0.8,v0.10和v0.12用戶,它將繼續受到支持。
當破裂的更改時,刪除了舊客戶端中的encoding選項,現在所有內容都是UTF-8,除了連接消息中的password和發布消息中的payload ,這是Buffer 。
另一個打破更改是MQTT.JS現在默認為MQTT v3.1.1,因此要支持舊經紀人,請閱讀客戶端選項文檔。
V1.0.0改進了項目的整體體系結構,該架構現在分為三個組件:MQTT.JS保持客戶端,MQTT-Connection包括用於服務器端使用的Barrebone連接代碼,MQTT-Packet包括協議Parser和Generator。新客戶將性能提高了30%的因素,嵌入了Websocket支持(現在已棄用了MOWS),並且對QoS 1和2的支持更好。先前的API仍得到支持,但不推薦使用,因此在此讀書中沒有記錄下來。
npm install mqtt --save為了簡單起見,讓我們將訂戶和發布者放在同一文件中:
const mqtt = require ( "mqtt" ) ;
const client = mqtt . connect ( "mqtt://test.mosquitto.org" ) ;
client . on ( "connect" , ( ) => {
client . subscribe ( "presence" , ( err ) => {
if ( ! err ) {
client . publish ( "presence" , "Hello mqtt" ) ;
}
} ) ;
} ) ;
client . on ( "message" , ( topic , message ) => {
// message is Buffer
console . log ( message . toString ( ) ) ;
client . end ( ) ;
} ) ;輸出:
Hello mqttMQTT.JS可用於React Native應用程序。要使用它,請參見React本地示例
如果您想運行自己的MQTT經紀人,則可以使用蚊子或艾德斯-CLI並啟動它。
您也可以使用測試實例:test.mosquitto.org。
如果您不想安裝單獨的經紀人,則可以嘗試使用AEDES。
const mqtt = require ( "mqtt" ) // require mqtt
const client = mqtt . connect ( "mqtt://test.mosquitto.org" ) // create a client import mqtt from "mqtt" ; // import namespace "mqtt"
let client = mqtt . connect ( "mqtt://test.mosquitto.org" ) ; // create a client import { connect } from "mqtt" ; // import connect from mqtt
let client = connect ( "mqtt://test.mosquitto.org" ) ; // create a client mqtt.js捆綁了一個命令與經紀人互動。為了使其在路徑上可用,您應該在全球安裝mqtt.js:
npm install mqtt -g然後,在一個終端上
mqtt sub -t ' hello ' -h ' test.mosquitto.org ' -v在另一個
mqtt pub -t ' hello ' -h ' test.mosquitto.org ' -m ' from MQTT.js '有關命令mqtt help <command> 。
mqtt.js使用調試軟件包進行調試目的。要啟用調試日誌,請在運行時添加以下環境變量:
# ( example using PowerShell, the VS Code default )
$env:DEBUG='mqttjs*' 任何WebSocket連接的重要部分是連接下降並且客戶端需要重新連接時該怎麼辦。 MQTT具有內置的重新連接支持,可以配置為以適合應用程序的方式行事。
transformWsUrl簽名URL(僅WebSocket)當MQTT連接下降並且需要重新連接時,通常要求與連接相關的任何身份驗證都與基礎驗證機制保持最新。例如,某些應用程序可能會通過初始連接上的連接選項傳遞一個auth令牌,而其他雲服務可能需要在每個連接時簽名URL。
到重新連接發生在應用程序生命週期中時,原始驗證數據可能已經過期了。
為了解決這個問題,我們可以使用稱為transformWsUrl的鉤子在重新連接時操縱連接URL或客戶端選項。
示例(在每個重新連接上更新客戶端和用戶名):
const transformWsUrl = ( url , options , client ) => {
client . options . username = `token= ${ this . get_current_auth_token ( ) } ` ;
client . options . clientId = ` ${ this . get_updated_clientId ( ) } ` ;
return ` ${ this . get_signed_cloud_url ( url ) } ` ;
}
const connection = await mqtt . connectAsync ( < wss url > , {
... ,
transformWsUrl : transformUrl ,
} );現在,每次打開新的Websocket連接(希望不太頻繁)時,我們將獲得新的簽名URL或新的驗證令牌數據。
注意:當前,此鉤子不支持承諾,這意味著要使用最新的auth代幣,您必須具有一些運行的外部機制來處理應用程序級的身份驗證刷新,以便Websocket Connection可以簡單地抓住最新的有效令牌或已簽名的URL。
createWebsocket自定義Websocket(僅Websocket)當您需要添加自定義的Websocket子協議或標題以通過具有自定義身份驗證的代理打開連接,此回調允許您創建自己的Websocket實例,該實例將在MQTT客戶端中使用。
const createWebsocket = ( url , websocketSubProtocols , options ) => {
const subProtocols = [
websocketSubProtocols [ 0 ] ,
'myCustomSubprotocolOrOAuthToken' ,
]
return new WebSocket ( url , subProtocols )
}
const client = await mqtt . connectAsync ( < wss url > , {
... ,
createWebsocket : createWebsocket ,
} );reconnectPeriod選項重新連接為了確保MQTT客戶端自動嘗試在連接丟棄時重新連接,必須將client option option reconnectPeriod設置為大於0的值。值為0的值將禁用重新連接,然後在下降時終止該值。
默認值為1000 ms,這意味著它將在失去連接後嘗試重新連接1秒。
請注意,這只能在連接超時或成功連接後重新連接。它將(默認情況下)啟用重試的連接,這些連接被服務器積極拒絕Connack錯誤。
為了啟用自動重新連接Connack錯誤,請設置reconnectOnConnackError: true 。
如果客戶端設置了選項autoUseTopicAlias:true ,則MQTT.JS會自動使用現有主題別名。
示例場景:
1. PUBLISH topic: ' t1 ' , ta:1 (register)
2. PUBLISH topic: ' t1 ' - > topic: ' ' , ta:1 (auto use existing map entry)
3. PUBLISH topic: ' t2 ' , ta:1 (register overwrite)
4. PUBLISH topic: ' t2 ' - > topic: ' ' , ta:1 (auto use existing map entry based on the receent map)
5. PUBLISH topic: ' t1 ' (t1 is no longer mapped to ta:1)用戶不需要管理哪個主題映射到哪個主題別名。如果用戶想註冊主題別名,請使用主題別名發布主題。如果用戶想使用主題別名,請在沒有主題別名的情況下發布主題。如果有映射的主題別名,則將其添加為屬性,然後將主題更新為空字符串。
如果客戶端設置了選項autoAssignTopicAlias:true ,則MQTT.JS會自動使用現有主題別名。如果沒有主題別名,則自動分配一個新的空缺主題別名。如果主題別名充分使用,則LRU(最近使用的)主題 - 阿里亞利亞輸入將被覆蓋。
示例場景:
The broker returns CONNACK (TopicAliasMaximum:3)
1. PUBLISH topic: ' t1 ' - > ' t1 ' , ta:1 (auto assign t1:1 and register)
2. PUBLISH topic: ' t1 ' - > ' ' , ta:1 (auto use existing map entry)
3. PUBLISH topic: ' t2 ' - > ' t2 ' , ta:2 (auto assign t1:2 and register. 2 was vacant)
4. PUBLISH topic: ' t3 ' - > ' t3 ' , ta:3 (auto assign t1:3 and register. 3 was vacant)
5. PUBLISH topic: ' t4 ' - > ' t4 ' , ta:1 (LRU entry is overwritten)此外,用戶也可以使用發布主題手動註冊主題 - alias對:'some',ta:x。它可以與自動主題別名分配效果很好。
mqtt.connect()mqtt.connectAsync()mqtt.Client()mqtt.Client#connect()mqtt.Client#publish()mqtt.Client#publishAsync()mqtt.Client#subscribe()mqtt.Client#subscribeAsync()mqtt.Client#unsubscribe()mqtt.Client#unsubscribeAsync()mqtt.Client#end()mqtt.Client#endAsync()mqtt.Client#removeOutgoingMessage()mqtt.Client#reconnect()mqtt.Client#handleMessage()mqtt.Client#connectedmqtt.Client#reconnectingmqtt.Client#getLastMessageId()mqtt.Store()mqtt.Store#put()mqtt.Store#del()mqtt.Store#createStream()mqtt.Store#close()連接到給定URL指定的經紀人和選項,並返回客戶端。
URL可以按以下協議:“ MQTT','MQTTS','TCP','tls','ws','wss','wss','wxs','alis'。如果要連接到UNIX套接字,只需將+unix後綴附加到協議(例如: mqtt+unix )。這將自動設置unixSocket屬性。
URL也可以是URL.parse()返回的對象,在這種情況下,兩個對像已合併,即,您可以將單個對像傳遞給具有URL和Connect選項的單個對象。
您還可以用內容指定servers選項: [{ host: 'localhost', port: 1883 }, ... ] ,在這種情況下,每個連接都迭代數組。
對於所有與MQTT相關的選項,請參見客戶端構造函數。
connect功能周圍的異步包裝器。
當客戶端觸發'connect'或'end'事件時,返回將解析為mqtt.Client實例的Promise ,或者如果觸發了'error' ,則會拒絕錯誤。
請注意, manualConnect選項將導致此功能返回的承諾永遠不會解析或拒絕,因為基礎客戶從未觸發任何事件。
Client類通過任意傳輸方法(TCP,TLS,WebSocket,ECC)將客戶連接與MQTT代理相關聯。 Client是一個擁有自己的活動的eventemitter
Client自動處理以下內容:
論點是:
streamBuilder是返回支持connect事件的Stream類的子類的函數。通常是net.Socket 。options是客戶端連接選項(請參閱:連接數據包)。預設值: wsOptions :是Websocket連接選項。默認值為{} 。這是針對Websocket的。有關可能的選項,請查看:https://github.com/websockets/ws/blob/master/master/doc/ws.md。
keepalive : 60秒,設置為0以禁用
reschedulePings :發送數據包後重新安排ping消息(默認為true )
clientId : 'mqttjs_' + Math.random().toString(16).substr(2, 8)
protocolId : 'MQTT'
protocolVersion : 4
clean : true ,設置為false以接收QoS 1和2郵件,而離線
reconnectPeriod : 1000毫秒,兩個重新連接之間的間隔。通過設置為0 ,禁用自動重新連接。
reconnectOnConnackError : false ,是否還要重新連接是否有錯誤收到Connack。
connectTimeout : 30 * 1000毫秒,時間等待,然後再收到Connack
username :您的經紀人要求的用戶名,如果有的話
password :經紀人要求的密碼,如果有的話
incomingStore :傳入數據包的商店
outgoingStore :外賣包的商店
queueQoSZero :如果連接斷開,排隊發出的QoS零消息(默認為true )
customHandleAcks :MQTT 5自定義處理Puback和PubRec數據包的功能。它的回調:
customHandleAcks: function ( topic , message , packet , done ) { /*some logic with calling done(error, reasonCode)*/ } autoUseTopicAlias :使用功能啟用自動主題別名
autoAssignTopicAlias :啟用自動主題別名分配功能
properties :屬性MQTT 5.0。支持以下屬性的object :
sessionExpiryInterval :以秒number表示會話的到期間隔,receiveMaximum :接收最大值number ,maximumPacketSize :表示客戶端願意接受number最大數據包大小,topicAliasMaximum :表示主題別名最大值表示客戶端將接受為服務器number發送的主題別名,requestResponseInformation :客戶端使用此值來請求服務器在Connack boolean中返迴響應信息,requestProblemInformation :客戶端使用此值來指示在失敗的情況下,字符串或用戶屬性是否發送的boolean ,userProperties :允許用戶屬性多次出現以表示多個名稱,值對object ,authenticationMethod :用於擴展身份驗證string身份驗證方法的名稱,authenticationData :包含身份驗證數據binary數據authPacket :auth分組object的設置
will :當客戶端斷開連接時,經紀人將自動發送的消息。格式是:
topic :發表的主題payload :發布的消息qos :QoSretain :保留旗properties :MQTT 5.0的意志屬性:willDelayInterval :表示將以秒數number Will延遲間隔,payloadFormatIndicator :WILL消息是UTF-8編碼字符數據或不是boolean ,messageExpiryInterval :值是WILL消息的壽命秒內,當服務器發布Will Message number ,contentType :描述意志消息string的內容,responseTopic :字符串用作響應消息string的主題名稱,correlationData :請求消息的發件人使用了相關數據,以識別響應消息是在收到binary何時響應消息的情況下,userProperties :允許用戶屬性多次出現以表示多個名稱,值對object transformWsUrl :僅適用於WS/WSS協議的可選(url, options, client) => url函數。可用於實現簽名URL,重新連接後可能已過期。
createWebsocket :可選的url, websocketSubProtocols, options) => Websocket函數僅適用於WS/WSS協議。可用於實現自定義的Websock子協議或實現。
resubscribe :如果連接斷開並重新連接,則再次自動訂閱訂閱的主題(默認為true )
messageIdProvider :自定義MessageID提供商。當設置new UniqueMessageIdProvider()時,則提供非衝突消息ID。
log :自定義日誌功能。默認使用調試軟件包。
manualConnect :防止要調用connect構造函數。在這種情況下,在稱為mqtt.connect之後,您應該手動調用client.connect 。
timerVariant :默認為auto ,它試圖確定哪個計時器最適合您的環境,如果您有檢測問題,則可以將其設置為worker或native 。如果不適合您,則可以通過設置和清除屬性傳遞計時器對象:
timerVariant: {
set : ( func , timer ) => setInterval ( func , timer ) ,
clear : ( id ) => clearInterval ( id )
} forceNativeWebSocket :如果您有檢測問題(即ws does not work in the browser ),則將其設置為True,以強制使用本機Weberocket。重要的是要注意,如果為創建的第一個客戶端設置為true,則所有客戶端將使用本機WebSocket。相反,如果未設置或設置為false,所有這些都將使用檢測結果。
unixSocket :如果要連接到Unix插座,請將其設置為true
如果需要MQTTS(TLS上的MQTT),則options對象將通過tls.connect()傳遞。如果使用自簽名的證書,請設置rejectUnauthorized: false 。但是,要謹慎,因為這會使您在中間攻擊中暴露於潛在的人中,並且不建議進行生產。
對於那些支持單個端口上多個TLS協議的人,例如WSS上的MQTT和MQTT,請使用ALPNProtocols選項。這使您可以定義應用程序層協議協議(ALPN)協議。您可以根據設置將ALPNProtocols設置為字符串陣列,緩衝區或UINT8ARRAY。
如果您要連接到僅支持MQTT 3.1(不符合3.1.1)的經紀人,則應通過以下其他選項:
{
protocolId : 'MQIsdp' ,
protocolVersion : 3
}這在RabbitMQ 3.2.4和蚊子<1.3上得到了證實。蚊子1.3和1.4版本沒有這些。
'connect' function (connack) {}
在成功的(RE)連接(即Connack RC = 0)上排放。
connack收到了Connack包。當clean連接選項為false且服務器具有以前的clientId連接選項會話時,則connack.sessionPresent標誌為true 。在這種情況下,您可以依靠存儲的會話,並且不願意為客戶端發送訂閱命令。 'reconnect' function () {}
重新連接開始時發出。
'close' function () {}
斷開後發出。
'disconnect' function (packet) {}
從經紀人收到斷開數據包後發出。 MQTT 5.0功能。
'offline' function () {}
客戶離線時發出。
'error' function (error) {}
當客戶端無法連接時發射(即Connack RC!= 0)或發生解析錯誤時。
以下TLS錯誤將作為一個error事件發出:
ECONNREFUSEDECONNRESETEADDRINUSEENOTFOUND'end' function () {}
當調用mqtt.Client#end()時發出。如果將回調傳遞給mqtt.Client#end() ,則一旦回調返回,就會發出此事件。
'message' function (topic, message, packet) {}
客戶收到發布數據包時發出
topic主題message有效載荷packet ,如MQTT Packet所定義'packetsend' function (packet) {}
客戶發送任何數據包時發出。這包括.publishiped()數據包以及MQTT用於管理訂閱和連接的數據包
packet ,如MQTT Packet所定義'packetreceive' function (packet) {}
客戶收到任何數據包時發出。這包括來自訂閱主題的數據包以及MQTT用於管理訂閱和連接的數據包
packet ,如MQTT Packet所定義默認情況下,client在調用構造函數時連接。為了防止這種情況,您可以將manualConnect選項設置為true ,並手動調用client.connect() 。
將消息發佈到主題
topic是要發佈到String主題message是要發布, Buffer或String消息options是要發布的選項,包括:qos QoS級別, Number ,默認值0retain標誌, Boolean ,默認為falsedup標記為重複標誌, Boolean ,默認錯誤falseproperties :MQTT 5.0屬性objectpayloadFormatIndicator :有效載荷是UTF-8編碼字符數據或不是boolean ,messageExpiryInterval :以秒number應用程序消息的壽命,topicAlias :用於識別主題而不是使用主題名稱number值,responseTopic :字符串用作響應消息string的主題名稱,correlationData :請求消息的發件人使用以識別響應消息是在接收到binary何時的請求,userProperties :允許用戶屬性多次出現以表示多個名稱,值對object ,subscriptionIdentifier :代表訂閱number的標識符,contentType :描述應用程序消息的內容string的字符串cbStorePut function () ,如果QoS為1或2 ,則將消息輸入outgoingStore時發射。callback - function (err, packet) ,QoS處理完成時或在QoS 0時在下一個tick上觸發。如果客戶端斷開連接,則會發生錯誤。異步publish 。返回Promise<Packet | undefined> 。
messageId屬性的任何內容。訂閱主題或主題
topic是要訂閱的String主題或要訂閱的Array主題。它也可以是一個對象,它作為對象鍵作為主題名稱,並作為QoS值,例如{'test1': {qos: 0}, 'test2': {qos: 1}} 。支持MQTT topic通配符字符(單級+ #對於多級別)options是要訂閱的選項,包括:qos QoS訂閱級別,默認為0nl沒有本地MQTT 5.0標誌(如果值為真,則不得將應用程序消息轉發到與clientID等於發布連接的客戶端的連接)rap保留為已發布的MQTT 5.0標誌(如果為true,則使用此訂閱轉發的應用程序消息保持其發布的保留標誌。如果是錯誤的,則使用此訂閱轉發的應用程序消息將rearain標誌設置為0。)rh保留處理MQTT 5.0(此選項指定在建立訂閱時是否發送保留消息。)properties : objectsubscriptionIdentifier :代表訂閱number的標識符,userProperties :允許用戶屬性多次出現以表示多個名稱,值對objectcallback - function (err, granted)在Suback上觸發的回調:err訂閱錯誤或客戶斷開連接時發生的錯誤granted是{topic, qos}的數組:topic是對主題的訂閱qos是理所當然的QoS級別異步subscribe 。返回Promise<ISubscriptionGrant[]> 。
退訂主題或主題
topic是一個String主題或一系列主題,要取消訂閱options :取消訂閱的選項。properties : objectuserProperties :允許用戶屬性多次出現以表示多個名稱,值對objectcallback - function (err) ,在Unsubak上發射。如果客戶端斷開連接,則會發生錯誤。異步unsubscribe 。返回Promise<void> 。
關閉客戶,接受以下選項:
force :將其傳遞給真實將立即關閉客戶,而無需等待飛行中的消息。此參數是可選的。options :斷開連接的選項。reasonCode :斷開原因代碼numberproperties : objectsessionExpiryInterval :以秒number表示會話的到期間隔,reasonString :表示斷開string的原因,userProperties :允許用戶屬性多次出現以表示多個名稱,值對object ,serverReference :客戶端可以使用的字符串來識別另一台服務器以使用stringcallback :客戶關閉時將被調用。此參數是可選的。異步end 。返回Promise<void> 。
從外向店中刪除消息。如果刪除該消息,將會通過錯誤(“刪除消息”)調用回調。
調用此函數後,釋放消息ID並將重複使用。
mId :外向店裡的消息的消息。使用與Connect()相同的選項再次連接
帶有背壓支持的消息,一次。隨意覆蓋,但始終致電callback ,否則客戶將懸掛。
布爾值:如果客戶端連接,則設置為true 。否則為false 。
號碼:獲取最後一條消息ID。這僅用於發送消息。
布爾值:如果客戶端試圖重新連接到服務器,則設置為true 。否則為false 。
消息存儲的內存實現。
options是商店選項:clean :調用關閉時的true ,乾淨的機上消息(默認為true ) mqtt.Store的其他實現:
將數據包添加到商店中,一個數據包是具有messageId屬性的任何內容。存儲數據包時調用回調。
在商店中使用所有數據包創建流。
從商店中刪除數據包,一個數據包是具有messageId屬性的任何內容。刪除數據包後,調用回調。
關閉商店。
重要的
瀏覽器中支持的唯一協議是Websocket上的MQTT,因此您必須使用ws://或wss://協議。
當WS模塊在NodeJS中使用時,Websocket用於瀏覽器中。這對用戶完全透明,除了以下內容:
瀏覽器不支持wsOption 。
出於安全原因,瀏覽器不允許捕獲許多WebSocket錯誤,例如:
訪問此信息可以允許惡意網頁獲取有關您的網絡的信息,因此他們需要瀏覽器以無法區分的方式報告所有連接時間錯誤。
因此,聆聽client.on('error')可能不會捕獲您在nodejs env中會遇到的所有錯誤。
MQTT.JS使用Esbuild捆綁。經過測試,與WebPack,Vite和React等所有捆綁包一起工作。
您可以在dist文件夾中找到所有MQTT捆綁版本:
mqtt.js iife格式,未更新mqtt.min.js iife格式,縮小mqtt.esm.js ESM格式縮小從MQTT.JS> 5.2.0開始,您可以在代碼中導入MQTT:
import mqtt from 'mqtt'這將由您的捆綁器自動處理。
否則,您可以選擇使用特定的捆綁包:
import * as mqtt from 'mqtt/dist/mqtt'
import * as mqtt from 'mqtt/dist/mqtt.min'
import mqtt from 'mqtt/dist/mqtt.esm'MQTT.JS捆綁包可通過http://unpkg.com獲得,特別是在https://unpkg.com/mqtt/dist/mqtt.min.js上獲得。有關版本範圍的完整文檔,請參見http://unpkg.com。
這是QoS的工作方式:
關於數據消耗,顯然是QoS 2> QoS 1> QoS 0,如果您關注的話。
從V5開始,此項目以打字稿編寫,類型定義包含在軟件包中。
例子:
import { connect } from "mqtt"
const client = connect ( 'mqtt://test.mosquitto.org' ) 支持微信迷你計劃。使用wxs協議。請參閱微信文檔。
import 'abortcontroller-polyfill/dist/abortcontroller-polyfill-only' // import before mqtt.
import 'esbuild-plugin-polyfill-node/polyfills/navigator'
const mqtt = require ( "mqtt" ) ;
const client = mqtt . connect ( "wxs://test.mosquitto.org" , {
timerVariant : 'native' // more info ref issue: #1797
} ) ;支持Ali Mini計劃。使用alis協議。請參閱“支付寶”文檔。
const mqtt = require ( "mqtt" ) ;
const client = mqtt . connect ( "alis://test.mosquitto.org" ) ; MQTT.JS是一個開放的開源項目。這意味著:
做出巨大貢獻的個人可以使該項目獲得合適的貢獻。該項目更像是一個開放的Wiki,而不是標準的護衛開源項目。
有關更多詳細信息,請參見貢獻。
僅由於以下貢獻者的出色工作,MQTT.JS才有可能:
| 姓名 | github | 嘰嘰喳喳 |
|---|---|---|
| 亞當·陸克文(Adam Rudd) | github/adamvr | Twitter/@adam_vr |
| Matteo Collina | Github/Mcollina | Twitter/@matteocollina |
| Maxime Agor | Github/4rzael | Twitter/@4rzael |
| Siarhei Buntsevich | Github/Scarry1992 | |
| 丹尼爾·蘭多(Daniel Lando) | Github/Robertslando |
如果您想支持MQTT.JS,請考慮贊助作者和主動維護者:
麻省理工學院