Bean(WebSocket)通訊
# FastWeb Bean(WebSocket)通訊
Bean之間的通訊依賴於WebSocket通訊,當Bean啟動並運行時,會向FastWeb伺服器發起WebSocket連線,直至頁面被關閉前,均會保持連線的狀態。
接下來將介紹FastWeb中的WebSocket通訊方式,以及如何在Bean,Smart、PinToo,第三方客戶端中實現WebSocket通訊。
# 1. WebSocket概述
在說明Bean的通訊方式前,我們要了解WebSocket是什麼,為什麼使用WebSocket,以及WebSocket的連線特性。
# 1.1. 什麼是WebSocket?
在介紹WebSocket之前,我們要先了解一下HTTP。
HTTP連線是由客戶端發起,伺服器在接收到客戶端的請求後向客戶端發送響應資訊。HTTP的協議存在一個缺陷,就是通訊只能由客戶端發起,伺服器不能主動向客戶端推送資訊。如果伺服器有連續狀態變化時,客戶端想要獲知會變得很麻煩,只能使用輪詢等查詢方式向服務端發送請求來獲取資訊,這種方式不僅不能及時獲知伺服器狀態,還嚴重影響伺服器的運行效率。
WebSocket 協議在2008年誕生,2011年成為國際標準。它的最大特點就是,伺服器可以主動向客戶端推送資訊,客戶端也可以主動向伺服器發送資訊,是真正的雙向平等對話。
# 1.2. FastWeb 上的WebSocket通訊
FastWeb內建了WebSocket伺服器,使用者使用瀏覽器打開FastWeb時,FastWeb瀏覽器的客戶端會與服務端發起WebSocket連線,連線會一直保持直至使用者關閉瀏覽器。
# 2. 配置WebSocket伺服器
WebSocket伺服器的配置位於 配置中心 。在配置中心界面,點選 WebSocket
選項卡,設定WebSocket伺服器的資訊。 請注意,FastWeb預設未開啟,請在 FastWebClient WebSocket 中勾選 開啟
選項。
設定完成後,點選 [儲存]
按鈕,切換至 普通伺服器
選項卡,點選下方 [重啟]
按鈕重新啟動FastWeb。
在上述示例中產生的WebSocket地址為 ws://127.0.0.1:8805/message
,SSL WebSocket地址為 wss://127.0.0.1:8806/message
。接下來測試連線的連通性。使用 WebSocket線上測試工具 (opens new window) 進行測試,輸入地址后,點選 [連線]
按鈕,如出現連線成功的字樣,表示連線成功。
如使用了身份驗證,則應使用以下地址進行身份認證連線。其中的 {USERNAME}
與 {PASSWORD}
處請修改爲配置中心中定義的使用者名稱與密碼。
ws://localhost:8805/sgc/auth/url/{USERNAME}/{PASSWORD}
wss://localhost:8806/sgc/auth/url/{USERNAME}/{PASSWORD}
# 3. Bean通訊方式
在FastWeb中,WebSocket是Bean的重要通訊工具,Bean模組之間的通訊互動以WebSocket為基礎。愛招飛的開發平臺 Smart 與 PinToo、開發板(Arduino、ESP8266、ESP32等)、FastWeb平臺均支援WebSocket通訊,通過WebSocket連線可實現Bean的互聯互通。接下來將介紹在不同協議與FastWeb的WebSocket通訊的方法。
# 3.1. Bean
以下內容對包含瀏覽器功能的 Smart 與 PinToo 同樣適用。
FastWeb平臺內建兩個自定函式 SendWsMsgBySId 、SendWsMsg 用於Bean模組之間的訊息傳送。下面將以 Bean-demo1
、Bean-demo2
兩個帶有圖形的模組為例進行說明。
Bean之間訊息傳輸流程如下。
- 發送資訊
Bean-demo1
模組通過呼叫 SendWsMsgBySId 或 SendWsMsg ,向伺服器發送WebSocket資訊。
- 解析並傳送訊息
FastWeb的WebSocket伺服器接收到來自 Bean-demo1
模組發送的WebSocket資訊,解析後讀取json資訊,根據傳送的目標使用者或者目標會話的資訊,從已連線的Bean列表中查詢匹配的使用者或者會話。如果找到匹配的使用者會話,就會向目標使用者會話 (如 Bean-demo2
) 發送WebSocket 資訊。
- 接收並解析,觸發動作
Bean-demo2
接收到來自FastWeb的訊息后,解析並觸發模組窗體的 OnAjaxEvent
事件,事件的名稱 eventname
以及 數據 data
均由json定義。在 OnAjaxEvent
事件中可使用 params.Values["paramname"]
來讀取鍵值對的數據資訊。示例程式碼如下。
//JScript
function UgWebRunFrameOnAjaxEvent(sender,eventname,params)
{
if (SameText(eventname,"update")) //解讀接收到的eventname ,此處的eventname要與發送端的callbackeventname 或者
{
var user = params.Values["user"];
var msg = params.Values["message"];
ugmemo01.Lines.Add(user+" "+ formatdatetime("c",now()) + ":");
ugmemo01.Lines.Add(msg);
ugmemo01.Lines.Add("");
}
}
2
3
4
5
6
7
8
9
10
11
12
//PasScript
procedure UgWebRunFrameOnAjaxEvent(sender:tobject;eventname,params:string);
var
user,msg: string;
begin
if (SameText(eventname,'update')) then
begin
user := params.Values['user'];
msg := params.Values['message'];
ugmemo01.Lines.Add(user+' '+ formatdatetime('c',now()) + ':');
ugmemo01.Lines.Add(msg);
ugmemo01.Lines.Add('');
end;
end;
2
3
4
5
6
7
8
9
10
11
12
13
14
// Make sure to add code blocks to your code group
# 3.2. WebSocket
Bean通訊可使用傳統的WebSocket協議來進行。支援WebSocket客戶端通訊的有 Smart 與 PinToo、開發板(Arduino、ESP8266、ESP32等)。
通訊的流程如下。
- 登錄並註冊會話
WebSocket客戶端在連線至FastWeb的WebSocket伺服器后,需註冊會話才可進行後續的資訊傳輸。註冊會話json格式如下。
{"action":"login","sid":"wstest"}
通過以上註冊,WebSocket獲得了一個名為 wstest
的會話ID,可進行數據互動的傳輸。
- 發送WebSocket訊息
WebSocket傳輸的是一串格式化的json字串,示例如下。
{
"username": "demo", //WebSocket訊息發送的目標使用者
"action": "callback", //WebSocket訊息告知Bean執行的動作
"tag": "0", //URL參數定義的標識組,可用於區分同一個IsoBean的不同場景的實體
"data": {
"callbackcomponent": "wb-vis-0008_chatroom", //執行動作的目標Bean模組的名稱
"callbackeventname": "update", //執行觸發OnAjaxEvent事件的 eventname(事件名稱)
"callbackparams": [ //傳輸的鍵值,可以有一對或者多對
{
"paramname": "user", //WS參數1名稱
"paramvalue": "demo" //WS參數1取值
},
{
"paramname": "message", //WS參數2名稱
"paramvalue": "212" //WS參數2取值
}
]
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
- 解析並傳送訊息
FastWeb的WebSocket伺服器接收到WebSocket資訊,解析後讀取json資訊,根據傳送的目標使用者資訊,從已連線的Bean列表中查詢匹配的使用者。如果找到匹配的使用者,就會向目標使用者發送WebSocket 資訊。
- 接收並解析,觸發動作
Bean模組接收到來自FastWeb的訊息后,解析並觸發模組窗體的 OnAjaxEvent
事件,事件的名稱 eventname
以及 數據鍵值對 paramname=paramvalue
均由json定義。在 OnAjaxEvent
事件中可使用 params.Values["paramname"]
來讀取鍵值對的數據資訊。示例程式碼請參考 FastWeb 部分 接收並解析,觸發動作
的程式碼。
- 向WebSocket客戶端發送資訊
Bean可使用 SendWsMsgBySId 來向WebSocket客戶端發送資訊。向WebSocket客戶端發送資訊只需要指定 sid
,參數 msg
可任意填寫。呼叫此函式發送時,Bean 向FastWeb 的 WebSocket 伺服器發送資訊。
- 解析並傳送訊息
FastWeb的WebSocket伺服器接收到WebSocket資訊,根據傳送的目標會話ID,從已連線列表中查詢匹配的會話ID。如果找到匹配的會話ID,就會向目標會話ID發送WebSocket 資訊。
- WebSocket客戶端接收處理資訊
WebSocket客戶端從服務端接收到 msg
訊息,可自行設計相關的事件來處理接收的訊息,實現Bean遠端控制的目的。
如果是非FastWeb的WebSocket客戶端需要通過WebSocket伺服器向其他非FastWeb客戶端發送訊息的,可在經過步驟1註冊會話的動作后,通過WebSocket發送以下內容格式的json來實現。
{
"action":"msg", //動作型別
"sid":"smart", //發送的目標會話ID
"text":"Hello Smart Client" //發送的資訊
}
2
3
4
5
上述訊息發送后,在目標的WebSocket客戶端(Smart、PinToo、FastERP或者ESP32開發板等)可接收到 Hello Smart Client
的訊息。
# 3.3. RestAPI
Bean支援通過RestAPI來接收資訊,並將其轉換為 WebSocket 訊息發送給目標使用者的Bean模組。
- 發送資訊
RestAPI的請求Url示例如下。
POST
http://localhost:8888/?restapi=sendwsmsg
2
POST的請求體中包含以下內容。
{
"username": "demo", //WebSocket訊息發送的目標使用者
"action": "callback", //WebSocket訊息告知Bean執行的動作
"tag": "0", //URL參數定義的標識組,可用於區分同一個IsoBean的不同場景的實體
"data": {
"callbackcomponent": "wb-vis-0008_chatroom", //執行動作的目標Bean模組的名稱
"callbackeventname": "update", //執行觸發OnAjaxEvent事件的 eventname(事件名稱)
"callbackparams": [ //傳輸的鍵值,可以有一對或者多對
{
"paramname": "user", //WS參數1名稱
"paramvalue": "demo" //WS參數1取值
},
{
"paramname": "message", //WS參數2名稱
"paramvalue": "212" //WS參數2取值
}
]
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
發送以上請求后,觀察反饋的結果,如果結果為以下內容,則資訊已成功提交。
{
"status": "ok",
"message": "successfully"
}
2
3
4
- 解析並傳送訊息
FastWeb的RestAPI接收到此資訊後進行解析,根據傳送的目標使用者資訊,從已連線的Bean列表中查詢匹配的使用者。如果找到匹配的使用者,就會向目標使用者發送WebSocket 資訊。
- 接收並解析,觸發動作
Bean模組接收到來自FastWeb的訊息后,解析並觸發模組窗體的 OnAjaxEvent
事件,事件的名稱 eventname
以及 數據鍵值對 paramname=paramvalue
均由json定義。在 OnAjaxEvent
事件中可使用 params.Values["paramname"]
來讀取鍵值對的數據資訊。示例程式碼請參考 FastWeb 部分 接收並解析,觸發動作
的程式碼。
# 4. 執行資料庫查詢(SQL)
在 FastWeb 中設定了資料庫連線與預設 SQL 后,可利用 FastWeb 來執行 SQL 查詢。發送的格式內容如下:
直接發送 SQL 語句:在 WebSocket 訊息中可直接發送 SQL 語句來執行查詢。示例如下(包含參數用法):
{
"action": "execsql",
"db_name": "demo",
"sql": "Insert Into Table_Test(FCode,FName) values(:F1,:F2)",
"params": [
{
"name": "F1",
"value": "003"
},
{
"name": "F2",
"value": "f37"
}
]
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
使用預設 SQL 執行查詢:如在 預設 SQL 中設定了查詢資訊,可發送需查詢的預設 SQL 來執行查詢。建立一個名稱為 SQL001
的預設 SQL,查詢語句示例如下(包含參數用法):
Insert Into Table_Test(FCode,FName) values(:F1,:F2)
呼叫 WebSocket 執行資料庫查詢的文字示例如下:
{
"action": "execsql",
"db_name": "demo",
"sql_command_id": "SQL001",
"params": [
{
"name": "F1",
"value": "043"
},
{
"name": "F2",
"value": "d23"
}
]
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15