今天來整理一下在網路通訊資料傳送中常見的3種通訊方式,WebSocket, OSC, MQTT
一般網路通訊會分Client及Server,在設置的時候要先確認Server要設置在哪裡,有時Server是在不用的程式軟體,有時是在不同的主機上,有時是在雲端的主機上。
在設定時,要先想好Server的IP address及通訊埠 port number,有時還要提供path路徑或是分類目錄,甚至是需要提供帳號密碼,要看使用的是什麼通訊方式。
先來看一下WebSocket的網頁上的操作
WebSocket的server設置在processing的程式上
processing
import websockets.*;
WebsocketServer ws;
void setup(){
size(200,200);
ws = new WebsocketServer(this,8025,"/p5js");
}
void draw(){
if(mousePressed){
ws.sendMessage(mouseX+", "+mouseY);
ellipse(mouseX, mouseY, 10, 10);
}
}
void webSocketServerEvent(String msg){
println(msg);
}
JS
let host = 'localhost:8025/p5js';
let socket;
function setup() {
socket = new WebSocket('ws://' + host); //-- 建立 WebSocket 物件
socket.onopen = sendMessage("START");
socket.onmessage = readMessage;
console.log(socket);
}
function sendMessage(data) {
console.log(data);
//socket.send(data);
}
function readMessage(event) {
console.log(event.data);
//console.log(event);
}
先來查看一下WebSocket的物件
在Server端按下滑鼠移動時,會傳送座標數值到client端
接著是client向server傳送資料
let host = 'localhost:8025/p5js';
let socket;
let can;
let clientID = 0;
function setup() {
can = createCanvas(200, 200);
background("lightyellow");
clientID = int(random(1, 10));
socket = new WebSocket('ws://' + host);
socket.onopen = sendMessage("clientID:"+clientID);
socket.onmessage = readMessage;
console.log(socket);
}
function draw(){
if(mouseIsPressed){
sendMessage(clientID+": "+mouseX+", "+mouseY);
//-- clientID 作為Server辨識是哪一個client傳送過來的資訊
ellipse(mouseX, mouseY, 10, 10);
}
}
function sendMessage(data) {
console.log(data);
console.log(socket.readyState);
if(socket.readyState==3){ //-- 如果socket斷線的話,重新執行socket連線
socket = new WebSocket('ws://' + host);
socket.onopen = sendMessage("clientID:"+clientID);
socket.onmessage = readMessage;
}
if(socket.readyState==1){ //-- 確認socket是在ready狀態才傳送資料
console.log(data);
socket.send(data);
}
}
function readMessage(event) {
console.log(event.data);
//console.log(event);
}
這個是socket的readyState狀態代號
代號 | 狀態 | 說明 |
---|---|---|
0 | CONNECTING | Socket建立連線中 |
1 | OPEN | Socket完成連線,可傳輸溝通 |
2 | CLOSING | Socket斷線中 |
3 | CLOSED | Socket已斷線 |
有關p5.js與OSC的狀況,目前主要的解決方案是,透過WebSocket,轉送訊息給OSC Server,再發送給其他OSC Client,尚未有直接的OSC的方案,因此,可以利用Processing來實作 WebSocket_OSC Server當作中介Server。不過在傳送格式上,要符合OSC的規範。
JS
let host = 'localhost:8025/p5js';
let socket;
let can;
let clientID = 0;
function setup() {
can = createCanvas(200, 200);
background("lightyellow");
clientID = int(random(1, 10));
socket = new WebSocket('ws://' + host);
socket.onopen = sendMessage("clientID:"+clientID);
socket.onmessage = readMessage;
console.log(socket);
}
function draw(){
if(mouseIsPressed){
sendMessage(clientID+": "+mouseX+", "+mouseY);
//-- clientID 作為Server辨識是哪一個client傳送過來的資訊
ellipse(mouseX, mouseY, 10, 10);
}
}
function sendMessage(data) {
console.log(data);
console.log(socket.readyState);
if(socket.readyState==3){ //-- 如果socket斷線的話,重新執行socket連線
socket = new WebSocket('ws://' + host);
socket.onopen = sendMessage("clientID:"+clientID);
socket.onmessage = readMessage;
}
if(socket.readyState==1){ //-- 確認socket是在ready狀態才傳送資料
console.log(data);
socket.send(data);
}
}
function readMessage(event) {
console.log(event.data);
//console.log(event);
}
Processing (websocket_osc)
import oscP5.*;
import netP5.*;
import websockets.*;
WebsocketServer ws;
OscP5 oscP5;
NetAddress myRemoteLocation;
void setup() {
size(400,400);
ws = new WebsocketServer(this,8025,"/p5js");
oscP5 = new OscP5(this,12000); //-- server
myRemoteLocation = new NetAddress("localhost", 12001); //-- client
}
void draw() {
if(mousePressed){
ws.sendMessage(mouseX+", "+mouseY);
ellipse(mouseX, mouseY, 10, 10);
}
}
void webSocketServerEvent(String msg){
println(msg);
oscSend(msg);
}
void oscSend(String msg) {
OscMessage myMessage = new OscMessage("/p5js");
myMessage.add(msg);
oscP5.send(myMessage, myRemoteLocation);
}
void oscEvent(OscMessage theOscMessage) {
println(theOscMessage);
println(theOscMessage.addrPattern());
if(theOscMessage.checkAddrPattern("/p5js")==true) {
String msg = theOscMessage.get(0).stringValue();
println(msg);
ws.sendMessage(msg);
return;
}
}
Processing (osc_client)
import oscP5.*;
import netP5.*;
OscP5 oscP5;
NetAddress myRemoteLocation;
void setup() {
size(400,400);
oscP5 = new OscP5(this,12001); //--- server
myRemoteLocation = new NetAddress("127.0.0.1",12000); //-- client
}
void draw() {
background(0);
}
void mousePressed() {
OscMessage myMessage = new OscMessage("/p5js");
myMessage.add("some text");
oscP5.send(myMessage, myRemoteLocation);
}
void oscEvent(OscMessage theOscMessage) {
println(theOscMessage);
println(theOscMessage.addrPattern());
println(theOscMessage.typetag());
if(theOscMessage.checkAddrPattern("/p5js")==true) {
String msg = theOscMessage.get(0).stringValue();
println(msg);
return;
}
}
MQTT是在IOT的場合中,很常用的通訊方式
一般來說,MQTT的Server常常使用 外部的網站當作是中介Server。
HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/mqtt/4.3.7/mqtt.js"></script>
JS
let client;
function setup() {
//-- 連結 mqtt server
client = mqtt.connect("wss://public:public@public.cloud.shiftr.io");
client.options.clientId = "A123";
console.log(client);
console.log(client.options);
client.on("connect", mqtt_connect);
client.on("message", mqtt_message);
}
function draw(){
if(mouseIsPressed){
client.publish("/p5js", mouseX+", "+mouseY); //-- 發送訊息給 /p5js
}
}
function mqtt_connect() {
client.subscribe("/p5js", function(err) { //-- 註冊 /p5js
if (!err) {
client.publish("/p5js", "mqtt_start");
}
})
}
function mqtt_message(topic, message) {
if (topic == "p5js") {
console.log(message.toString());
}
console.log(topic + " - " + message.toString());
// client.end() // mqtt 斷線
}
查看一下建立的MQTT物件 MqttClient
查看一下MQTT物件的 options 項目
Processing (mqtt_client)
import mqtt.*;
MQTTClient client;
void setup() {
client = new MQTTClient(this);
//-- 連結 mqtt server
//-- client.connect("mqtt://id:password@mqtt_server", "username");
client.connect("mqtt://public:public@public.cloud.shiftr.io", "processing");
}
void draw() {
if(mousePressed){
client.publish("/p5js", mouseX+", "+mouseY); //-- 發送訊息給 /p5js
}
}
void clientConnected() {
println("client connected");
client.subscribe("/p5js"); //-- 註冊 /p5js
}
void messageReceived(String topic, byte[] payload) {
println("new message: " + topic + " - " + new String(payload));
}
void connectionLost() {
println("connection lost");
}
mqtt流程:建立連線,註冊,發送訊息,接收訊息
值得注意的是
在JS端的連結網址是 wss://
wss://public:public@public.cloud.shiftr.io
在Processing端的連結網址是 mqtt://
mqtt://public:public@public.cloud.shiftr.io
由此可知在瀏覽器端支援的是 WebSocket
ws:WebSocket
wss:WebSocket Secure
參考資料
Transmitting OSC data via WebSocket
https://contra.medium.com/transmitting-osc-data-via-websocket-43fcc8bfade7
WebSocket
https://developer.mozilla.org/en-US/docs/Web/API/WebSocket
processing_websockets
https://github.com/alexandrainst/processing_websockets
oscP5
https://sojamo.de/libraries/oscP5/
processing-mqtt
https://github.com/256dpi/processing-mqtt