iT邦幫忙

2022 iThome 鐵人賽

0
Modern Web

從新開始學習p5.js畫出一片天系列 第 33

D33_網路通訊資料傳送的操作(WebSocket, OSC, MQTT)

  • 分享至 

  • xImage
  •  

網路通訊資料傳送的操作(WebSocket, OSC, MQTT)

今天來整理一下在網路通訊資料傳送中常見的3種通訊方式,WebSocket, OSC, MQTT

一般網路通訊會分Client及Server,在設置的時候要先確認Server要設置在哪裡,有時Server是在不用的程式軟體,有時是在不同的主機上,有時是在雲端的主機上。
在設定時,要先想好Server的IP address及通訊埠 port number,有時還要提供path路徑或是分類目錄,甚至是需要提供帳號密碼,要看使用的是什麼通訊方式。

WebSocket

先來看一下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的物件
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已斷線

OSC

有關p5.js與OSC的狀況,目前主要的解決方案是,透過WebSocket,轉送訊息給OSC Server,再發送給其他OSC Client,尚未有直接的OSC的方案,因此,可以利用Processing來實作 WebSocket_OSC Server當作中介Server。不過在傳送格式上,要符合OSC的規範。

WebSocket_OSC Server

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

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
MqttClient

查看一下MQTT物件的 options 項目
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


上一篇
D32_網路讀取資料的操作(JS AJAX, CORS)
下一篇
D34_資料記錄與儲存的操作
系列文
從新開始學習p5.js畫出一片天40
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言