来自扫码枪应用适配的经验及扩展。
查了好多资料,发现实现思路不外乎以下几种:
1.使用服务端开发语言开发一个读取串口数据的本地服务模块,并实现websocket长连接支持,前端开启长连接到该服务,根据推送的数据进行操作。
2.针对IE浏览器,可以采用ActiveX插件读取串口数据,根据插件的API进行开发。
3.对于chrome浏览器,可以使用Chrome.serial实现
这几种方式本质区别不大,只是浏览器兼容方面有区别。第一种方式是兼容性最好的,但增加了一个本地服务模块的开发,所以开发成本较高。第二种ActiveX插件对IE浏览器兼容最好。第三种同样需要自己开发一个chrome app来调用chrome.serial接口。
由于项目要求使用IE浏览器,下面只对IE浏览器下使用ActiveX插件读取串口数据的步骤进行详述。
在这里采用的是微软开发的mscomm32.ocx.
1.下载插件并复制 MSCOMM32.OCX 到 C:\WINDOWS\SysWOW64 (如果是32位系统就是 C:\WINDOWS\SysWOW32 )
2.依次运行下面命令(以管理员身份运行,注意根据系统32位和64位更改命令中的路径):
regsvr32 /u C:\WINDOWS\SysWOW64\MSCOMM32.OCX
regsvr32 /i C:\WINDOWS\SysWOW64\MSCOMM32.OCX
regsvr32 C:\WINDOWS\SysWOW64\MSCOMM32.OCX
Reg add"HKEY_CLASSES_ROOT\Licenses\4250E830-6AC2-11cf-8ADB-00AA00C00905" /v “” /d “kjljvjjjoquqmjjjvpqqkqmqykypoqjquoun” /f
3.设置IE浏览器的ActiveX插件的安全控制,将之都设为启用或提示状态。
以上配置完成,可以用下面的代码尝试是否安装成功
<html>
<head>
<title>JavaScript串口测试title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<script ID=clientEventHandlersJS LANGUAGE=javascript>
function MSComm1_OnComm() {
switch(MSComm1.CommEvent) {
case 1:
{
window.alert("Send OK!");
break;
} //发送事件
case 2:
{
Receive();
break;
} //接收事件
default:
alert("Event Raised!" + MSComm1.CommEvent);;
}
}
script>
<script LANGUAGE=javascript FOR=MSComm1 EVENT=OnComm>
// MSComm1控件每遇到 OnComm 事件就调用 MSComm1_OnComm()函数
MSComm1_OnComm()
script>
<script language="JavaScript" type="text/JavaScript">
String.prototype.Blength = function(){
var arr = this.match(/[^\x00-\xff]/ig);
return arr == null ? this.length : this.length + arr.length;
}
function OperatePort() {
if(MSComm1.PortOpen == true) {
try {
MSComm1.PortOpen = false;
document.getElementById("OperateButton").value = "打开串口";
} catch(ex) {
alert(ex.message);
}
} else {
try {
MSComm1.PortOpen = true;
document.getElementById("OperateButton").value = "关闭串口";
} catch(ex) {
alert(ex.message);
}
}
}
function ConfigPort() {
alert("串口状态:" + MSComm1.PortOpen);
if(MSComm1.PortOpen == false) {
try {
MSComm1.CommPort = document.getElementById("ComName").value;
alert(MSComm1.CommPort)
MSComm1.Settings = document.getElementById("BaudRate").value.toString() + "," +
document.getElementById("CheckBit").value.toString() + "," +
document.getElementById("DataBits").value.toString() + "," +
document.getElementById("StopBits").value.toString();
MSComm1.OutBufferCount = 0; //清空发送缓冲区
MSComm1.InBufferCount = 0; //滑空接收缓冲区
alert("已配置串口COM" + MSComm1.CommPort + "\n 参数:" + MSComm1.Settings);
} catch(ex) {
alert(ex.message);
}
} else {
alert("请先关闭串口后再设置!");
}
}
function Send() {
//alert(document.getElementById("txtSend").value);
var orgstr = document.getElementById("txtSend").value;
var newstr = "";
var hexflag = document.getElementById("isSendHex").checked;
if(hexflag && orgstr != "") {
if(orgstr.substr(0, 2) == "0x" || orgstr.substr(0, 2) == "0X") orgstr = orgstr.substring(2, orgstr.length);
if(orgstr.length % 2 != 0) orgstr = "0" + orgstr;
//alert(str2hex(orgstr));
if((newstr = str2hex(orgstr)) == "") {
alert("错误的16进制数");
return false;
}
}
try {
MSComm1.Output = hexflag ? newstr : orgstr;
//alert(MSComm1.Output)
} catch(ex) {
alert(ex.message);
}
}
function Receive() {
//alert("InBufferCount::" + MSComm1.InBufferCount); // 缓冲区接收的字节
document.getElementById("txtReceive").value += MSComm1.Input; //alert("InBufferCount::"+MSComm1.InBufferCount);
}
function ClearReceived() {
document.getElementById("txtReceive").innerText = "";
}
function str2hex(s) {
var a, b, d;
var hexStr = '';
for(var i = 0; i <
s.length; i++) {
d = s.charCodeAt(i);
a = d % 16;
b = (d - a) / 16;
hexStr += '%' + "0123456789ABCDEF".charAt(b) + "0123456789ABCDEF".charAt(a);
}
//alert(hexStr);
return hexStr;
}
function charCode(v) {
return String.fromCharCode(v);
}
script>
head>
<body>
<form name="form1">
<fieldset style="width:200px;height:250px;text-align:center;">
<legend>配置串口legend>
<div style="float:left;width:200px">
<br/>
<span>串口号:span>
<select name="ComName" id="ComName" style="width:75px">
<option value="1">COM1option>
<option value="2">COM2option>
<option value="7" selected>COM7option>
<option value="4">COM4option>
<option value="5">COM5option>
<option value="9">COM9option>
select>
<br/>
<span>波特率:span>
<select name="BaudRate" id="BaudRate" style="width:75px">
<option value="9600">9600option>
<option value="57600">57600option>
<option value="115200" selected>115200option>
select>
<br/>
<span>校验位:span>
<select name="CheckBit" id="CheckBit" style="width:75px">
<option value="N" selected>无NONEoption>
<option value="O">奇ODDoption>
<option value="E">偶EVENoption>
select>
<br/>
<span>数据位:span>
<input type=text id="DataBits" name="DataBits" value=8 style="width:75px;height:20px">
<br/>
<span>停止位:span>
<input type=text id="StopBits" name="StopBits" value=1 style="width:75px;height:20px">
<br/>
<br/>
<input type="button" id="ConfigButton" style="width:80px;height:30px;font-size:13px" name="ConfigButton" value="配置串口" onClick="ConfigPort()">
<input type="button" id="OperateButton" style="width:80px;height:30px;font-size:13px" name="OperateButton" value="打开串口" onClick="OperatePort()">
div>
fieldset>
<fieldset style="width:200px;height:250px;text-align:center;">
<legend>发送区域legend>
<div style="float:left;">
<textarea id="txtSend" name="txtSend" style="width:200px;height:160px">textarea>
<br/>
<span><input id="isSendHex" name="isSendHex" type="checkbox" />16进制span>
<input type="button" id="SendButton" style="width:100px;height:30px" name="SendButton" value="发送" onClick="Send()">
div>
fieldset>
<fieldset style="width:200px;height:250px;text-align:center;">
<legend>接收区域legend>
<div style="float:left;">
<textarea id="txtReceive" READONLY=TRUE name="txtReceive" style="width:200px;height:160px">textarea>
<br/>
<span><input id="isReceiveHex" name="isReceiveHex" type="checkbox" />16进制span>
<input type="button" id="ClearButton" style="width:100px;height:30px" name="ClearButton" value="清空" onClick="ClearReceived()">
div>
fieldset>
form>
<OBJECT id=MSComm1 CLASSID="clsid:648A5600-2C6E-101B-82B6-000000000014" codebase="MSCOMM32.OCX" type="application/x-oleobject" style="LEFT:54px;TOP:14px">
<PARAM NAME="CommPort" VALUE="3"/>
<PARAM NAME="DataBits" VALUE="8"/>
<PARAM NAME="StopBits" VALUE="1"/>
<PARAM NAME="BaudRate" VALUE="9600"/>
<PARAM NAME="Settings" VALUE="9600,N,8,1"/>
<PARAM NAME="RTSEnable" VALUE="1"/>
<PARAM NAME="DTREnable" VALUE="1"/>
<PARAM NAME="Handshaking" VALUE="0"/>
<PARAM NAME="NullDiscard" VALUE="0"/>
<PARAM NAME="ParityReplace" VALUE="?"/>
<PARAM NAME="EOFEnable" VALUE="0"/>
<PARAM NAME="InputMode" VALUE="0"/>
<PARAM NAME="InBufferSize" VALUE="1024"/>
<PARAM NAME="InputLen" VALUE="0"/>
<PARAM NAME="OutBufferSize" VALUE="512"/>
<PARAM NAME="SThreshold" VALUE="0"/>
<PARAM NAME="RThreshold" VALUE="1"/>
OBJECT>
body>
html>