IE浏览器通过mscomm控件与串口外设通信
场景:
基于JAVA EE的BS应用,前端使用IE浏览器,需要通过串口与pos、地磅、显示屏等外设进行通信。
目前与串口应用基本上都是一个本地应用,用vc、vb、delphi等开发工具开发,使用ie直接与com
通信的案例非常少。
因为项目的软件架构风格不能改变,决定了必须用IE与com通信,这种情况下,采用ActiveX的方式
成为不多的选择之一
1环境
后台就不说了,没有什么关系,下面是前端的环境
操作系统:win7(32、64)、xp
浏览器:IE 8
ACTIVEX:MSCOMM
html控制:javascript
2安装
主要是mscomm控件的安装,
针对32、64位不同的版本,把ocx文件放在system32目录下(其他位置貌似也可以)
以管理员身份运行cmd.exe
运行regsvr32 mscomm.ocx
3应用
html<object>
<object classid="clsid:648A5600-2C6E-101B-82B6-000000000014" id=MSComm1 codebase="MSCOMM32.OCX" type="application/x-oleobject" >
<param name="CommPort" value="4" /> <!-- 端口号 -->
<param name="DTREnable" value="1" />
<param name="Handshaking" value="0" />
<param name="InBufferSize" value="1024" />
<param name="InputLen" value="0" />
<param name="NullDiscard" value="0" />
<param name="OutBufferSize" value="512" />
<param name="ParityReplace" value="?" />
<param name="RThreshold" value="1" /> <!-- -->
<param name="RTSEnable" value="1" />
<param name="SThreshold" value="2" />
<param name="EOFEnable" value="0" />
<param name="InputMode" value="1" /><!-- binary 1,ascii 0 -->
<param name="DataBits" value="8" />
<param name="StopBits" value="1" />
<param name="BaudRate" value="9600" />
<param name="Settings" value="9600,N,8,1" /> <!-- 波特率,校验位等 -->
</object>
4异步通信
串口通信本来就是异步通信,类似于以太网的双工工作,发不影响收的过程。
与前台的交互分成两个过程:
a:发送,只管数据发送成功就可以了
b:接收,接收到数据会触发响应事件,接收到完整报文后触发前台的处理函数。但是这里有一个很重要的问题,一个完整的报文是13个字节,
接收的时候有可能是一次接收到5个, 下一次接收到8个,完成一个完整的报文,需要靠报文的开头、结尾字符去认定一个完整的报文。
5、JS不可见字符的严重问题
正常情况下,控件接收到一个报文会赋值给js的变量(字符串),要发送的时候需要把要发送的数据在JS中转换成字符串,传给控件。
但是,由于JS是弱类型的语言,没有byte的概念,在赋值过程中,部分不可见字符(不仅仅是ascii),入0XEB,就会被转换成0X3F,
丢失该字节的表征意义。
解决办法:
a:修改报文都用可见字符
b:再写一个控件,接收mscomm的数据后进行进行转码,然后赋值给js变量,反之亦然(本系统采用此方法)
主要方法:
$('MSComm1').PortOpen ,可赋值,可取值
if ($('MSComm1').PortOpen == false) {
$('MSComm1').PortOpen = true;
}
$('MSComm1').Output ,发送指定的内容,在js中会把所有内容转变成字符串,发给mscomm
$('MSComm1').Output = $("tb_send").value);
$('MSComm1').Input ,接收到的内容,本意是一个字节数组,赋值给js后会变成一个字符串
var v=$('MSComm1').Input;
$('MSComm1').CommEvent ,mscomm事件,在发送、接收,打开、关闭端口都会触发,是异步控制的源头
switch($('MSComm1').CommEvent){
case 1:{ break;} //发送事件
case 2: { Receive();break;} //接收事件
default: alert("Event Raised!"+$('MSComm1').CommEvent);;
}
发送二进制时的几个有用的js方法
String.fromCharCode(arr[i]):把数字(ascii码)作为unicode编码,转换成一个string类型的字符
str.charCodeAt(i).toString(16):把一个字符转换成unicode,并且用16进制显示
4Q&A
Q:发送0x02怎么办,怎么拼到发送字符串里面
A:str=str + String.fromCharCode(0x02)
Q:如何显示收到的字符串中的特殊字符,如0x02
A:str.charCodeAt(i).toString(16)