web前端讀取串口數據

來自掃碼槍應用適配的經驗及擴展。

查了好多資料,發現實現思路不外乎以下幾種:

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插件的安全控制,將之都設爲啓用或提示狀態。

以上配置完成,可以用下面的代碼嘗試是否安裝成功

<!DOCTYPE html>
<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">COM1</option>
						<option value="2">COM2</option>
						<option value="7" selected>COM7</option>
						<option value="4">COM4</option>
						<option value="5">COM5</option>
						<option value="9">COM9</option>
					</select>
					<br/>
					<span>波特率:</span>
					<select name="BaudRate" id="BaudRate" style="width:75px">
						<option value="9600">9600</option>
						<option value="57600">57600</option>
						<option value="115200" selected>115200</option>
					</select>
					<br/>
		
					<span>校驗位:</span>
					<select name="CheckBit" id="CheckBit" style="width:75px">
						<option value="N" selected>無NONE</option>
						<option value="O">奇ODD</option>
						<option value="E">偶EVEN</option>
					</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>

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章