Communicate With The Serial Port From Client Web Browser.
Solution 1:
Using Web Serial API. I am using this to ONLY read the data from my Weight Scale with RS232 Serial Interface
<!DOCTYPE html><htmllang="en"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>Web Serial</title></head><body><divclass="serial-scale-div"><buttonclass="btn"id="connect-to-serial">Connect with Serial Device</button></div><buttonid="get-serial-messages">Get serial messages</button><divid="serial-messages-container"><divclass="message"></div></div><script>
"use strict";
classSerialScaleController {
constructor() {
this.encoder = newTextEncoder();
this.decoder = newTextDecoder();
}
asyncinit() {
if ('serial'in navigator) {
try {
const port = await navigator.serial.requestPort();
await port.open({ baudRate: 9600 });
this.reader = port.readable.getReader();
let signals = await port.getSignals();
console.log(signals);
}
catch (err) {
console.error('There was an error opening the serial port:', err);
}
}
else {
console.error('Web serial doesn\'t seem to be enabled in your browser. Try enabling it by visiting:');
console.error('chrome://flags/#enable-experimental-web-platform-features');
console.error('opera://flags/#enable-experimental-web-platform-features');
console.error('edge://flags/#enable-experimental-web-platform-features');
}
}
asyncread() {
try {
const readerData = awaitthis.reader.read();
console.log(readerData)
returnthis.decoder.decode(readerData.value);
}
catch (err) {
const errorMessage = `error reading data: ${err}`;
console.error(errorMessage);
return errorMessage;
}
}
}
const serialScaleController = newSerialScaleController();
const connect = document.getElementById('connect-to-serial');
const getSerialMessages = document.getElementById('get-serial-messages');
connect.addEventListener('pointerdown', () => {
serialScaleController.init();
});
getSerialMessages.addEventListener('pointerdown', async () => {
getSerialMessage();
});
asyncfunctiongetSerialMessage() {
document.querySelector("#serial-messages-container .message").innerText += await serialScaleController.read()
}
</script></body></html>
Checkout this demo and this code for a more descriptive example.
You might need to turn on the Serial API feature on your browser. Following is the quote from References
As you can imagine, this is API is only supported by modern Chromium based desktop browsers right now (April 2020) but hopefully support will improve in the near future. At this moment you need to enable your browser's Experimental Web Platform Features, just copy and paste the right URL:
chrome://flags/#enable-experimental-web-platform-features
opera://flags/#enable-experimental-web-platform-features
edge://flags/#enable-experimental-web-platform-features
References:
https://dev.to/unjavascripter/the-amazing-powers-of-the-web-web-serial-api-3ilc
Solution 2:
Well, One way to do this is develop a chrome app. You can use chrome.serial API.
https://developer.chrome.com/apps/serial
Sample Code,
In your manifest.json,
{
"name": "Serial Sample",
"description": "Read/Write from/to serial port.",
"version": "1.0",
"manifest_version": 2,
"permissions": ["serial"],
"app": {
"background": {
"scripts": ["background.js"]
}
}
}
In your background.js,
const DEVICE_PATH = 'COM1';
const serial = chrome.serial;
var dataRecieved="";
/* Interprets an ArrayBuffer as UTF-8 encoded string data. */var ab2str = function(buf) {
var bufView = new Uint8Array(buf);
var encodedString = String.fromCharCode.apply(null, bufView);
return decodeURIComponent(escape(encodedString));
};
/* Converts a string to UTF-8 encoding in a Uint8Array; returns the array buffer. */var str2ab = function(str) {
var encodedString = unescape(encodeURIComponent(str));
var bytes = new Uint8Array(encodedString.length);
for (var i = 0; i < encodedString.length; ++i) {
bytes[i] = encodedString.charCodeAt(i);
}
return bytes.buffer;
};
var SerialConnection = function() {
this.connectionId = -1;
this.lineBuffer = "";
this.boundOnReceive = this.onReceive.bind(this);
this.boundOnReceiveError = this.onReceiveError.bind(this);
this.onConnect = new chrome.Event();
this.onReadLine = new chrome.Event();
this.onError = new chrome.Event();
};
SerialConnection.prototype.onConnectComplete = function(connectionInfo) {
if (!connectionInfo) {
log("Connection failed.");
return;
}
this.connectionId = connectionInfo.connectionId;
chrome.serial.onReceive.addListener(this.boundOnReceive);
chrome.serial.onReceiveError.addListener(this.boundOnReceiveError);
this.onConnect.dispatch();
};
SerialConnection.prototype.onReceive = function(receiveInfo) {
if (receiveInfo.connectionId !== this.connectionId) {
return;
}
this.lineBuffer += ab2str(receiveInfo.data);
var index;
while ((index = this.lineBuffer.indexOf('\n')) >= 0) {
var line = this.lineBuffer.substr(0, index + 1);
this.onReadLine.dispatch(line);
this.lineBuffer = this.lineBuffer.substr(index + 1);
}
};
SerialConnection.prototype.onReceiveError = function(errorInfo) {
if (errorInfo.connectionId === this.connectionId) {
this.onError.dispatch(errorInfo.error);
}
};
SerialConnection.prototype.connect = function(path) {
serial.connect(path, this.onConnectComplete.bind(this))
};
SerialConnection.prototype.send = function(msg) {
if (this.connectionId < 0) {
throw'Invalid connection';
}
serial.send(this.connectionId, str2ab(msg), function() {});
};
SerialConnection.prototype.disconnect = function() {
if (this.connectionId < 0) {
throw'Invalid connection';
}
serial.disconnect(this.connectionId, function() {});
};
var connection = new SerialConnection();
connection.onConnect.addListener(function() {
//console.log('connected to: ' + DEVICE_PATH);
});
connection.onReadLine.addListener(function (line) {
//Serial port data recieve event.
dataRecieved = dataRecieved +line;
});
connection.connect(DEVICE_PATH);
Once you create the chrome app to communicate with the serial port the next thing is to allow your external web page to communicate with the chrome app using JavaScript.
For this on your manifest.json file add,
"externally_connectable":{"matches":["*://*.example.com/*"]}
This will allow external webpage on your example.com domain communicate with your chrome app.
In your webpage,
// The ID of the extension we want to talk to.var editorExtensionId = "nboladondmajlaalmcdupihoilpcketyl";
// Make a simple request:
chrome.runtime.sendMessage(editorExtensionId,
{ data: "data to pass to the chrome app" },
function (response)
{
alert(response);
});
In your chrome app,
chrome.runtime.onMessageExternal.addListener(
function (request, sender, sendResponse) {
sendResponse("Send serial port data to the web page");
});
Solution 3:
I set up a website and a simple example for running a serial terminal in your browser. You should host it on a https server.
The serial terminal features are now available in chrome 88.
Live demo https://www.SerialTerminal.com Full source. https://github.com/mmiscool/serialTerminal.com/blob/main/index.html
Post a Comment for "Communicate With The Serial Port From Client Web Browser."