从客户端Web浏览器与串行端口进行通信。

在我的Web应用程序(sencha extjs 5)中,我有一个用户需求来读/写数据到客户端PC串口。

我知道客户端浏览器不能访问本地机器硬件,而无需在本地机器上安装一些二进制文件(Native app,Windows Service等)。

我已经看到了几年前在stackoverflow论坛讨论相同的问题。 但是我需要知道今天用现有技术做这件事的最好方法是什么?

那么,一个办法是开发一个Chrome应用程序。 你可以使用chrome.serial API。

https://developer.chrome.com/apps/serial

示例代码,

在你的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"] } } } 

在你的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); 

一旦创build了Chrome应用程序与串行端口进行通信,接下来就是允许您的外部网页使用JavaScript与Chrome应用程序进行通信。

对于你的manifest.json文件添加,

 "externally_connectable": { "matches": ["*://*.example.com/*"] } 

这将允许您的example.com域上的外部网页与您的Chrome应用程序进行通信。

在你的网页上,

  // 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); }); 

在你的Chrome应用程序中,

 chrome.runtime.onMessageExternal.addListener( function (request, sender, sendResponse) { sendResponse("Send serial port data to the web page"); }); 

https://developer.chrome.com/apps/messaging

警告!! Chrome应用将于2018年停止使用(Google再次表明它们的可靠性)