Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537
注意以下幾點(diǎn):
示例:
let html = ""; for(var i=0;i<data.length;i++){ html += '<tr>'+ '<td>'+ data[i].appName +'</td>'+ '<td>'+ '<button type="button" onclick="edit('+JSON.stringify(data[i]).replace(/\"/g,"'")+')">按鈕1</button>'+'</td>'+ '<td>'+ "<button type='button' onclick='del("+JSON.stringify(data[i])+")'>按鈕2</button>"+'</td>'+ +'</tr>' }
上述代碼中,使用了兩種不同的引號(hào)嵌套格式。按鈕1外層使用單引號(hào),因此需要將JSON字符串中所有雙引號(hào)轉(zhuǎn)化成單引號(hào),比較繁瑣。從語(yǔ)法角度考慮,JavaScript 字符串與 JSON 字符串的最大區(qū)別在于,JSON 字符串必須使用雙引號(hào)(單引號(hào)會(huì)導(dǎo)致語(yǔ)法錯(cuò)誤),因此不推薦此寫(xiě)法。
推薦第二種寫(xiě)法,直接在外層嵌套雙引號(hào),無(wú)需進(jìn)行額外操作。
Json,全名 JavaScript Object Notation,JSON(JavaScript Object Notation(記號(hào)、標(biāo)記))是一種輕量級(jí)的數(shù)據(jù)交換格式。它基于JavaScript(Standard ECMA-262 3rd Edition - December 1999)的一個(gè)子集。 (文末有驚喜)
JSON采用完全獨(dú)立 于語(yǔ)言的文本格式,但是也使用了類(lèi)似于C語(yǔ)言家族的習(xí)慣(包括C, C++, C#, Java, JavaScript, Perl, Python等)。這些特性使JSON成為理想的數(shù)據(jù)交換語(yǔ)言。JSON易于人閱讀和編寫(xiě),同時(shí)也易于機(jī)器解析和生成。常用于 http 請(qǐng)求中,接口
用Python處理json也很簡(jiǎn)單,Python自帶有json模塊。可以對(duì)python對(duì)象與json字符串進(jìn)行相互轉(zhuǎn)換。
python的常見(jiàn)內(nèi)置數(shù)據(jù)類(lèi)型有dict,tuple等,而在json中,數(shù)據(jù)類(lèi)型有object,array等,在相互轉(zhuǎn)換中,類(lèi)型是一一對(duì)應(yīng)的。在下表中的python數(shù)據(jù)類(lèi)型才可以被轉(zhuǎn)為json,集合set、字節(jié)byte不能轉(zhuǎn)為json。
Python數(shù)據(jù)類(lèi)型 | JSON數(shù)據(jù)類(lèi)型 | 說(shuō)明 |
dict | object | 都用花括號(hào){}表示 |
list,tuple | array | JSON用中括號(hào)[]表示 |
str | string | JSON用雙引號(hào)""表示 |
int,float | number | |
True | true | |
False | false | |
None | null |
json模塊的主要4個(gè)函數(shù)。
方法 | 解釋 |
json.dumps | 解析python對(duì)象為json字符串 |
json.dump | 解析python對(duì)象,輸出到j(luò)son文件 |
json.loads | 解析json字符串為python對(duì)象 |
json.load | 輸入json文件,解析為python對(duì)象 |
json.dumps方法提供了很多好用的參數(shù)可供選擇,比較常用的有sort_keys(對(duì)dict對(duì)象進(jìn)行排序,我們知道默認(rèn)dict是無(wú)序存放的),skipkeys(對(duì)于鍵不是基本類(lèi)型Python字典鍵值對(duì)將被過(guò)濾),indent(格式化輸出用的)等參數(shù)。還是舉個(gè)例子:
>> python_obj2={"key2": [4, 5, 6], "key1": [1, 2, 3]}
>>> json_str2=json.dumps(python_obj2)
>>> json_str2=json.dumps(python_obj2,sort_keys=True,indent=2)
>>> print json_str2
{
"key1": [
>> python_obj2={"key2": [4, 5, 6], "key1": [1, 2, 3]}
>>> json_str2=json.dumps(python_obj2)
>>> json_str2=json.dumps(python_obj2,sort_keys=True,indent=2)
>>> print json_str2
{
"key1": [
1,
2,
3
],
"key2": [
4,
5,
6
]
}
>>> json_str2=json.dumps(python_obj2,sort_keys=False,indent=2)
>>> print json_str2
{
"key2": [
4,
5,
6
],
"key1": [
1,
2,
3
]
}
在python中解析python對(duì)象為json字符串,使用json.dumps方法。其中indent參數(shù)表示縮進(jìn),可以優(yōu)化json輸出格式。
yimport json
# 創(chuàng)建python list對(duì)象
obj = [{'a': 1, 'b': {'aa': 11, 'bb': 22}}, {'b': (False,True,None)}]
# 解析python對(duì)象,設(shè)置縮進(jìn)
print(json.dumps(obj,indent=4))
[
{
"a": 1,
"b": {
"aa": 11,
"bb": 22
}
},
{
"b": [
false,
true,
null
]
}
]
注意點(diǎn):
在實(shí)際的項(xiàng)目開(kāi)發(fā)中,使用到的python對(duì)象可能不止內(nèi)置的對(duì)象,還有可能使用如numpy,pandas,datetime等高頻使用的庫(kù)。如下,將numpy的int32類(lèi)型的1轉(zhuǎn)為json,發(fā)現(xiàn)報(bào)錯(cuò)TypeError: Object of type int32 is not JSON serializable,這種類(lèi)型的報(bào)錯(cuò)在python對(duì)象轉(zhuǎn)json過(guò)程中是非常常見(jiàn)的,報(bào)錯(cuò)解釋是輸入的類(lèi)型不能序列化。
# 解析python對(duì)象,會(huì)報(bào)錯(cuò)
json.dumps(np.int32(1))
Traceback (most recent call last):
File "<input>", line 1, in <module>
File "C:\Anaconda3\lib\json\__init__.py", line 231, in dumps
return _default_encoder.encode(obj)
File "C:\Anaconda3\lib\json\encoder.py", line 199, in encode
chunks = self.iterencode(o, _one_shot=True)
File "C:\Anaconda3\lib\json\encoder.py", line 257, in iterencode
return _iterencode(o, 0)
File "C:\Anaconda3\lib\json\encoder.py", line 179, in default
raise TypeError(f'Object of type {o.__class__.__name__} '
TypeError: Object of type int32 is not JSON serializable
該類(lèi)問(wèn)題的解決辦法有兩種,一是在數(shù)據(jù)源處做類(lèi)型強(qiáng)制轉(zhuǎn)換,如可以用內(nèi)置的int方法把numpy的int32轉(zhuǎn)為int。
# 解析python對(duì)象,強(qiáng)制類(lèi)型轉(zhuǎn)換
json.dumps(int(np.int32(1)))
'1'
另外一種方法更為靈活(推薦),設(shè)置json.dumps參數(shù)cls,cls參數(shù)輸入為類(lèi),可以重寫(xiě)jsoneEncoder類(lèi)中的default方法。
# 自定義類(lèi)
class MyEncoder(json.JSONEncoder):
"""
重寫(xiě)json模塊JSONEncoder類(lèi)中的default方法
"""
def default(self, obj):
# np整數(shù)轉(zhuǎn)為內(nèi)置int
if isinstance(obj, np.integer):
return int(obj)
else:
return super(JetEncoder, self).default(obj)
# 解析python對(duì)象,設(shè)置cls參數(shù)
json.dumps(np.int32(1),cls=MyEncoder)
'1'
第二種方法靈活性更好,可以根據(jù)項(xiàng)目情況自定義需要轉(zhuǎn)換的類(lèi)型,當(dāng)有多個(gè)地方需要轉(zhuǎn)換時(shí),通用性更好。
json.dump用于保存python對(duì)象為json文件。obj.json文件中會(huì)保存解析obj后的json字符串。
# python list對(duì)象
print(obj)
[{'a': 1, 'b': {'aa': 11, 'bb': 22}}, {'b': (False, True, None)}]
# 解析python對(duì)象并輸出到j(luò)son文件
with open('obj.json','w') as f:
json.dump(obj,f)
json.loads用于加載json字符串,然后解析成python對(duì)象。
json_str='{"a":1,"b":{"aa":11,"bb":22}}'
# 解析json字符串為python對(duì)象
json.loads(json_str)
{'a': 1, 'b': {'aa': 11, 'bb': 22}}
json.load用于加載json文件,然后解析成python對(duì)象。
# 解析python對(duì)象,輸出到j(luò)son文件
with open('obj.json','r') as f:
print(json.load(f))
[{'a': 1, 'b': {'aa': 11, 'bb': 22}}, {'b': [False, True, None]}]
私信我還有更多驚喜哦!!!
譯自: https://opensource.com/article/18/6/mqtt
作者: Sean Dague
譯者: Andy Song
從開(kāi)源數(shù)據(jù)到開(kāi)源事件流,了解一下 MQTT 發(fā)布/訂閱(pubsub)線路協(xié)議。
去年 11 月我們購(gòu)買(mǎi)了一輛電動(dòng)汽車(chē),同時(shí)也引發(fā)了有趣的思考:我們應(yīng)該什么時(shí)候?yàn)殡妱?dòng)汽車(chē)充電?對(duì)于電動(dòng)汽車(chē)充電所用的電,我希望能夠?qū)?yīng)最小的二氧化碳排放,歸結(jié)為一個(gè)特定的問(wèn)題:對(duì)于任意給定時(shí)刻,每千瓦時(shí)對(duì)應(yīng)的二氧化碳排放量是多少,一天中什么時(shí)間這個(gè)值最低?
我住在紐約州,大約 80% 的電力消耗可以自給自足,主要來(lái)自天然氣、水壩(大部分來(lái)自于 尼亞加拉(Niagara)大瀑布)、核能發(fā)電,少部分來(lái)自風(fēng)力、太陽(yáng)能和其它化石燃料發(fā)電。非盈利性組織 紐約獨(dú)立電網(wǎng)運(yùn)營(yíng)商(New York Independent System Operator) (NYISO)負(fù)責(zé)整個(gè)系統(tǒng)的運(yùn)作,實(shí)現(xiàn)發(fā)電機(jī)組發(fā)電與用電之間的平衡,同時(shí)也是紐約路燈系統(tǒng)的監(jiān)管部門(mén)。
盡管沒(méi)有為公眾提供公開(kāi) API,NYISO 還是盡責(zé)提供了 不少公開(kāi)數(shù)據(jù) 供公眾使用。每隔 5 分鐘匯報(bào)全州各個(gè)發(fā)電機(jī)組消耗的燃料數(shù)據(jù)。數(shù)據(jù)以 CSV 文件的形式發(fā)布于公開(kāi)的檔案庫(kù)中,全天更新。如果你了解不同燃料對(duì)發(fā)電瓦數(shù)的貢獻(xiàn)比例,你可以比較準(zhǔn)確的估計(jì)任意時(shí)刻的二氧化碳排放情況。
在構(gòu)建收集處理公開(kāi)數(shù)據(jù)的工具時(shí),我們應(yīng)該時(shí)刻避免過(guò)度使用這些資源。相比將這些數(shù)據(jù)打包并發(fā)送給所有人,我們有更好的方案。我們可以創(chuàng)建一個(gè)低開(kāi)銷(xiāo)的 事件流(event stream),人們可以訂閱并第一時(shí)間得到消息。我們可以使用 MQTT 實(shí)現(xiàn)該方案。我的項(xiàng)目( ny-power.org )目標(biāo)是收錄到 Home Assistant 項(xiàng)目中;后者是一個(gè)開(kāi)源的 家庭自動(dòng)化(home automation)平臺(tái),擁有數(shù)十萬(wàn)用戶。如果所有用戶同時(shí)訪問(wèn) CSV 文件服務(wù)器,估計(jì) NYISO 不得不增加訪問(wèn)限制。
MQTT 是一個(gè) 發(fā)布訂閱線路協(xié)議(publish/subscription wire protocol),為小規(guī)模設(shè)備設(shè)計(jì)。發(fā)布訂閱系統(tǒng)工作原理類(lèi)似于消息總線。你將一條消息發(fā)布到一個(gè) 主題(topic)上,那么所有訂閱了該主題的客戶端都可以獲得該消息的一份拷貝。對(duì)于消息發(fā)送者而言,無(wú)需知道哪些人在訂閱消息;你只需將消息發(fā)布到一系列主題,并訂閱一些你感興趣的主題。就像參加了一場(chǎng)聚會(huì),你選取并加入感興趣的對(duì)話。
MQTT 能夠構(gòu)建極為高效的應(yīng)用。客戶端訂閱有限的幾個(gè)主題,也只收到它們感興趣的內(nèi)容。不僅節(jié)省了處理時(shí)間,還降低了網(wǎng)絡(luò)帶寬使用。
作為一個(gè)開(kāi)放標(biāo)準(zhǔn),MQTT 有很多開(kāi)源的客戶端和服務(wù)端實(shí)現(xiàn)。對(duì)于你能想到的每種編程語(yǔ)言,都有對(duì)應(yīng)的客戶端庫(kù);甚至有嵌入到 Arduino 的庫(kù),可以構(gòu)建傳感器網(wǎng)絡(luò)。服務(wù)端可供選擇的也很多,我的選擇是 Eclipse 項(xiàng)目提供的 Mosquitto 服務(wù)端,這是因?yàn)樗w積小、用 C 編寫(xiě),可以承載數(shù)以萬(wàn)計(jì)的訂閱者。
在過(guò)去二十年間,我們?yōu)檐浖?yīng)用設(shè)計(jì)了可靠且準(zhǔn)確的模型,用于解決服務(wù)遇到的問(wèn)題。我還有其它郵件嗎?當(dāng)前的天氣情況如何?我應(yīng)該此刻購(gòu)買(mǎi)這種產(chǎn)品嗎?在絕大多數(shù)情況下,這種 問(wèn)答式(ask/receive)的模型工作良好;但對(duì)于一個(gè)數(shù)據(jù)爆炸的世界,我們需要其它的模型。MQTT 的發(fā)布訂閱模型十分強(qiáng)大,可以將大量數(shù)據(jù)發(fā)送到系統(tǒng)中。客戶可以訂閱數(shù)據(jù)中的一小部分并在訂閱數(shù)據(jù)發(fā)布的第一時(shí)間收到更新。
MQTT 還有一些有趣的特性,其中之一是 遺囑(last-will-and-testament)消息,可以用于區(qū)分兩種不同的靜默,一種是沒(méi)有主題相關(guān)數(shù)據(jù)推送,另一種是你的數(shù)據(jù)接收器出現(xiàn)故障。MQTT 還包括 保留消息(retained message),當(dāng)客戶端初次連接時(shí)會(huì)提供相關(guān)主題的最后一條消息。這對(duì)那些更新緩慢的主題來(lái)說(shuō)很有必要。
我在 Home Assistant 項(xiàng)目開(kāi)發(fā)過(guò)程中,發(fā)現(xiàn)這種消息總線模型對(duì) 異構(gòu)系統(tǒng)(heterogeneous systems)尤為適合。如果你深入 物聯(lián)網(wǎng)(Internet of Things)領(lǐng)域,你會(huì)發(fā)現(xiàn) MQTT 無(wú)處不在。
NYSO 公布的 CSV 文件中有一個(gè)是實(shí)時(shí)的燃料混合使用情況。每 5 分鐘,NYSO 發(fā)布這 5 分鐘內(nèi)發(fā)電使用的燃料類(lèi)型和相應(yīng)的發(fā)電量(以兆瓦為單位)。
這個(gè) CSV 文件看起來(lái)像這樣:
表中唯一令人不解就是燃料類(lèi)別中的混合燃料。紐約的大多數(shù)天然氣工廠也通過(guò)燃燒其它類(lèi)型的化石燃料發(fā)電。在冬季寒潮到來(lái)之際,家庭供暖的優(yōu)先級(jí)高于發(fā)電;但這種情況出現(xiàn)的次數(shù)不多,(在我們計(jì)算中)可以將混合燃料類(lèi)型看作天然氣類(lèi)型。
CSV 文件全天更新。我編寫(xiě)了一個(gè)簡(jiǎn)單的數(shù)據(jù)泵,每隔 1 分鐘檢查是否有數(shù)據(jù)更新,并將新條目發(fā)布到 MQTT 服務(wù)器的一系列主題上,主題名稱基本與 CSV 文件有一定的對(duì)應(yīng)關(guān)系。數(shù)據(jù)內(nèi)容被轉(zhuǎn)換為 JSON 對(duì)象,方便各種編程語(yǔ)言處理。
ny-power/upstream/fuel-mix/Hydro {"units": "MW", "value": 3229, "ts": "05/09/2018 00:05:00"}
ny-power/upstream/fuel-mix/Dual Fuel {"units": "MW", "value": 1400, "ts": "05/09/2018 00:05:00"}
ny-power/upstream/fuel-mix/Natural Gas {"units": "MW", "value": 2144, "ts": "05/09/2018 00:05:00"}
ny-power/upstream/fuel-mix/Other Fossil Fuels {"units": "MW", "value": 4, "ts": "05/09/2018 00:05:00"}
ny-power/upstream/fuel-mix/Wind {"units": "MW", "value": 41, "ts": "05/09/2018 00:05:00"}
ny-power/upstream/fuel-mix/Other Renewables {"units": "MW", "value": 226, "ts": "05/09/2018 00:05:00"}
ny-power/upstream/fuel-mix/Nuclear {"units": "MW", "value": 4114, "ts": "05/09/2018 00:05:00"}
這種直接的轉(zhuǎn)換是種不錯(cuò)的嘗試,可將公開(kāi)數(shù)據(jù)轉(zhuǎn)換為公開(kāi)事件。我們后續(xù)會(huì)繼續(xù)將數(shù)據(jù)轉(zhuǎn)換為二氧化碳排放強(qiáng)度,但這些原始數(shù)據(jù)還可被其它應(yīng)用使用,用于其它計(jì)算用途。
主題和 主題結(jié)構(gòu)(topic structure)是 MQTT 的一個(gè)主要特色。與其它標(biāo)準(zhǔn)的企業(yè)級(jí)消息總線不同,MQTT 的主題無(wú)需事先注冊(cè)。發(fā)送者可以憑空創(chuàng)建主題,唯一的限制是主題的長(zhǎng)度,不超過(guò) 220 字符。其中 / 字符有特殊含義,用于創(chuàng)建主題的層次結(jié)構(gòu)。我們即將看到,你可以訂閱這些層次中的一些分片。
基于開(kāi)箱即用的 Mosquitto,任何一個(gè)客戶端都可以向任何主題發(fā)布消息。在原型設(shè)計(jì)過(guò)程中,這種方式十分便利;但一旦部署到生產(chǎn)環(huán)境,你需要增加 訪問(wèn)控制列表(access control list)(ACL)只允許授權(quán)的應(yīng)用發(fā)布消息。例如,任何人都能以只讀的方式訪問(wèn)我的應(yīng)用的主題層級(jí),但只有那些具有特定 憑證(credentials)的客戶端可以發(fā)布內(nèi)容。
主題中不包含 自動(dòng)樣式(automatic schema),也沒(méi)有方法查找客戶端可以發(fā)布的全部主題。因此,對(duì)于那些從 MQTT 總線消費(fèi)數(shù)據(jù)的應(yīng)用,你需要讓其直接使用已知的主題和消息格式樣式。
那么應(yīng)該如何設(shè)計(jì)主題呢?最佳實(shí)踐包括使用應(yīng)用相關(guān)的根名稱,例如在我的應(yīng)用中使用 ny-power。接著,為提高訂閱效率,構(gòu)建足夠深的層次結(jié)構(gòu)。upstream 層次結(jié)構(gòu)包含了直接從數(shù)據(jù)源獲取的、不經(jīng)處理的原始數(shù)據(jù),而 fuel-mix 層次結(jié)構(gòu)包含特定類(lèi)型的數(shù)據(jù);我們后續(xù)還可以增加其它的層次結(jié)構(gòu)。
在 MQTT 中,訂閱僅僅是簡(jiǎn)單的字符串匹配。為提高處理效率,只允許如下兩種通配符:
為便于理解,下面給出幾個(gè)例子:
ny-power/# - 匹配 ny-power 應(yīng)用發(fā)布的全部主題
ny-power/upstream/# - 匹配全部原始數(shù)據(jù)的主題
ny-power/upstream/fuel-mix/+ - 匹配全部燃料類(lèi)型的主題
ny-power/+/+/Hydro - 匹配全部?jī)纱螌蛹?jí)之后為 Hydro 類(lèi)型的主題(即使不位于 upstream 層次結(jié)構(gòu)下)
類(lèi)似 ny-power/# 的大范圍訂閱適用于 低數(shù)據(jù)量(low-volume)的應(yīng)用,應(yīng)用從網(wǎng)絡(luò)獲取全部數(shù)據(jù)并處理。但對(duì) 高數(shù)據(jù)量(high-volume)應(yīng)用而言則是一個(gè)災(zāi)難,由于絕大多數(shù)消息并不會(huì)被使用,大部分的網(wǎng)絡(luò)帶寬被白白浪費(fèi)了。
在大數(shù)據(jù)量情況下,為確保性能,應(yīng)用需要使用恰當(dāng)?shù)闹黝}篩選(如 ny-power/+/+/Hydro)盡量準(zhǔn)確獲取業(yè)務(wù)所需的數(shù)據(jù)。
接下來(lái),應(yīng)用中的一切都依賴于已有的 MQTT 流并構(gòu)建新流。第一個(gè)額外的數(shù)據(jù)層用于計(jì)算發(fā)電對(duì)應(yīng)的二氧化碳排放。
利用 美國(guó)能源情報(bào)署(U.S. Energy Information Administration) 給出的 2016 年紐約各類(lèi)燃料發(fā)電及排放情況,我們可以給出各類(lèi)燃料的 平均排放率 ,單位為克/兆瓦時(shí)。
上述結(jié)果被封裝到一個(gè)專(zhuān)用的微服務(wù)中。該微服務(wù)訂閱 ny-power/upstream/fuel-mix/+,即數(shù)據(jù)泵中燃料組成情況的原始數(shù)據(jù),接著完成計(jì)算并將結(jié)果(單位為克/千瓦時(shí))發(fā)布到新的主題層次結(jié)構(gòu)上:
ny-power/computed/co2 {"units": "g / kWh", "value": 152.9486, "ts": "05/09/2018 00:05:00"}
接著,另一個(gè)服務(wù)會(huì)訂閱該主題層次結(jié)構(gòu)并將數(shù)據(jù)打包到 InfluxDB 進(jìn)程中;同時(shí),發(fā)布 24 小時(shí)內(nèi)的時(shí)間序列數(shù)據(jù)到 ny-power/archive/co2/24h 主題,這樣可以大大簡(jiǎn)化當(dāng)前變化數(shù)據(jù)的繪制。
這種層次結(jié)構(gòu)的主題模型效果不錯(cuò),可以將上述程序之間的邏輯解耦合。在復(fù)雜系統(tǒng)中,各個(gè)組件可能使用不同的編程語(yǔ)言,但這并不重要,因?yàn)榻粨Q格式都是 MQTT 消息,即主題和 JSON 格式的消息內(nèi)容。
為了更好的了解 MQTT 完成了什么工作,將其綁定到一個(gè)消息總線并查看消息流是個(gè)不錯(cuò)的方法。mosquitto-clients 包中的 mosquitto_sub 可以讓我們輕松實(shí)現(xiàn)該目標(biāo)。
安裝程序后,你需要提供服務(wù)器名稱以及你要訂閱的主題。如果有需要,使用參數(shù) -v 可以讓你看到有新消息發(fā)布的那些主題;否則,你只能看到主題內(nèi)的消息數(shù)據(jù)。
mosquitto_sub -h mqtt.ny-power.org -t ny-power/# -v
只要我編寫(xiě)或調(diào)試 MQTT 應(yīng)用,我總會(huì)在一個(gè)終端中運(yùn)行 mosquitto_sub。
到目前為止,我們已經(jīng)有提供公開(kāi)事件流的應(yīng)用,可以用微服務(wù)或命令行工具訪問(wèn)該應(yīng)用。但考慮到互聯(lián)網(wǎng)仍占據(jù)主導(dǎo)地位,因此讓用戶可以從瀏覽器直接獲取事件流是很重要。
MQTT 的設(shè)計(jì)者已經(jīng)考慮到了這一點(diǎn)。協(xié)議標(biāo)準(zhǔn)支持三種不同的傳輸協(xié)議: TCP 、 UDP 和 WebSockets 。主流瀏覽器都支持 WebSockets,可以維持持久連接,用于實(shí)時(shí)應(yīng)用。
Eclipse 項(xiàng)目提供了 MQTT 的一個(gè) JavaScript 實(shí)現(xiàn),叫做 Paho ,可包含在你的應(yīng)用中。工作模式為與服務(wù)器建立連接、建立一些訂閱,然后根據(jù)接收到的消息進(jìn)行響應(yīng)。
// ny-power web console application
var client = new Paho.MQTT.Client(mqttHost, Number("80"), "client-" + Math.random());
// set callback handlers
client.onMessageArrived = onMessageArrived;
// connect the client
client.reconnect = true;
client.connect({onSuccess: onConnect});
// called when the client connects
function onConnect() {
// Once a connection has been made, make a subscription and send a message.
console.log("onConnect");
client.subscribe("ny-power/computed/co2");
client.subscribe("ny-power/archive/co2/24h");
client.subscribe("ny-power/upstream/fuel-mix/#");
}
// called when a message arrives
function onMessageArrived(message) {
console.log("onMessageArrived:"+message.destinationName + message.payloadString);
if (message.destinationName == "ny-power/computed/co2") {
var data = JSON.parse(message.payloadString);
$("#co2-per-kwh").html(Math.round(data.value));
$("#co2-units").html(data.units);
$("#co2-updated").html(data.ts);
}
if (message.destinationName.startsWith("ny-power/upstream/fuel-mix")) {
fuel_mix_graph(message);
}
if (message.destinationName == "ny-power/archive/co2/24h") {
var data = JSON.parse(message.payloadString);
var plot = [
{
x: data.ts,
y: data.values,
type: 'scatter'
}
];
var layout = {
yaxis: {
title: "g CO2 / kWh",
}
};
Plotly.newPlot('co2_graph', plot, layout);
}
上述應(yīng)用訂閱了不少主題,因?yàn)槲覀儗⒁尸F(xiàn)若干種不同類(lèi)型的數(shù)據(jù);其中 ny-power/computed/co2 主題為我們提供當(dāng)前二氧化碳排放的參考值。一旦收到該主題的新消息,網(wǎng)站上的相應(yīng)內(nèi)容會(huì)被相應(yīng)替換。
ny-power.org 網(wǎng)站提供的 NYISO 二氧化碳排放圖。
ny-power/archive/co2/24h 主題提供了時(shí)間序列數(shù)據(jù),用于為 Plotly 線表提供數(shù)據(jù)。ny-power/upstream/fuel-mix 主題提供當(dāng)前燃料組成情況,為漂亮的柱狀圖提供數(shù)據(jù)。
ny-power.org 網(wǎng)站提供的燃料組成情況。
這是一個(gè)動(dòng)態(tài)網(wǎng)站,數(shù)據(jù)不從服務(wù)器拉取,而是結(jié)合 MQTT 消息總線,監(jiān)聽(tīng)對(duì)外開(kāi)放的 WebSocket。就像數(shù)據(jù)泵和打包器程序那樣,網(wǎng)站頁(yè)面也是一個(gè)發(fā)布訂閱客戶端,只不過(guò)是在你的瀏覽器中執(zhí)行,而不是在公有云的微服務(wù)上。
你可以在 http://ny-power.org 站點(diǎn)點(diǎn)看到動(dòng)態(tài)變更,包括圖像和可以看到消息到達(dá)的實(shí)時(shí) MQTT 終端。
ny-power.org 應(yīng)用的完整內(nèi)容開(kāi)源在 GitHub 中。你也可以查閱 架構(gòu)簡(jiǎn)介 ,學(xué)習(xí)如何使用 Helm 部署一系列 Kubernetes 微服務(wù)構(gòu)建應(yīng)用。另一個(gè)有趣的 MQTT 示例使用 MQTT 和 OpenWhisk 進(jìn)行實(shí)時(shí)文本消息翻譯, 代碼模式(code pattern)參考 鏈接 。
MQTT 被廣泛應(yīng)用于物聯(lián)網(wǎng)領(lǐng)域,更多關(guān)于 MQTT 用途的例子可以在 Home Assistant 項(xiàng)目中找到。
如果你希望深入了解協(xié)議內(nèi)容,可以從 mqtt.org 獲得該公開(kāi)標(biāo)準(zhǔn)的全部細(xì)節(jié)。
想了解更多,可以參加 Sean Dague 在 OSCON 上的演講,主題為 將 MQTT 加入到你的工具箱 ,會(huì)議將于 7 月 16-19 日在奧爾良州波特蘭舉辦。
via: https://opensource.com/article/18/6/mqtt
作者: Sean Dague 選題: lujun9972 譯者: pinewall 校對(duì): wxy
本文由 LCTT 原創(chuàng)編譯, Linux中國(guó) 榮譽(yù)推出
*請(qǐng)認(rèn)真填寫(xiě)需求信息,我們會(huì)在24小時(shí)內(nèi)與您取得聯(lián)系。