使用Ruby在windows下通过串口自动测试AT

原文http://deli.xmu.me/?p=7,放在Wayhome mm给我提供的空间,现在已经无法访问。

手机芯片厂家常常会更新模组软件版本,在发给客户之前,一般先对AT进行一次测试。手机设计公司收到新的软件版本,烧入Flash, 也要对模组的AT进行一次测试,验证是否正常,比较与上个版本是否有差别。手工一个个验证,乏味,容易对工作失去兴趣。

从http://rubyinstaller.rubyforge.org 可以下载 Ruby One-Click,现在最新版本安装软件为ruby186-27_rc2.exe。安装过程中,把RubyGems也勾上。在windows上用ruby访问串口,可以用win32ole模块,也可以用ruby-serialport,后者是跨平台的。安装ruby-serialport前要做一些准备工作,确认有装Microsoft’s Visual C++ 或Borland’s C++编译器,这里以VC6.0为例。
(1)设置环境变量:

PATH=C:\Program Files\Microsoft Visual Studio\VC98\Bin
INCLUDE=C:\Program Files\Microsoft Visual Studio\VC98\Include
LIB=C:\Program Files\Microsoft Visual Studio\VC98\Lib

(2)安装ruby-serialport:
开始 -> 程序 -> Ruby-186-27 -> RubyGems -> RubyGems Package Manager,输入:
gem install ruby-serialport
如果提示找不到mspdb60.dll, 请到http://www.dll-files.com 找,把它放到
C:\Program Files\Microsoft Visual Studio\VC98\Bin
接下来,就可以写一个测试脚本了。

# filename: test.rb
require 'rubygems'
require 'serialport'

# 0 is mapped to "COM1" on Windows, and 5 is COM6, 115200 is baud rate
sp = SerialPort.new(5, 115200)
sp.write "AT\r\n"
sleep(0.2)
puts sp.read   # hopefully "OK" ;-) 

注意:如果没有sleep,可能会收不到”OK”响应。

如果你弄了老半天,ruby-serialport也没装得上,那就用用win32ole,美其名曰:Windows Automation。win32ole是Masaki Suketa编写的Ruby扩展,是标准ruby发行版本的一部分。
现在写一个mscomm.rb文件

#! /usr/bin/env ruby
#
# filename: mscomm.rb
# @date 2009.5.16
#

require 'win32ole'

class MSCOMM
  def initialize(port)
    @serial = WIN32OLE.new("MSCOMMLib.MSComm")

    @serial.CommPort = port
    @serial.Settings = "115200,N,8,1"
    @serial.InputLen = 0
    @serial.PortOpen = true
  end
  def write(str)
    @serial.Output = str
  end
  def read
    str = @serial.Input
    str
  end
  def close
    @serial.PortOpen = false
  end
  def serial
    @serial
  end
end

再写一个简单的测试用例test_comm.rb:

#! /usr/bin/env ruby
#
# filename: test_comm.rb
# @date 2009.5.16
#

require 'mscomm.rb

comm  = MSCOMM.new(6)
comm.write("AT\r\n")
sleep(0.2)
puts comm.read
comm.close

和上面的test.rb用法一样,没什么神秘感,是不是很简单呢 :-)

再加个查询信号的AT,在test_comm.rb倒数第二行加上
comm.write(“AT+CSQ?\r\n”)
sleep(0.2)
puts comm.read
要是很多很多…想想,还是写个函数吧.

def exec_cmd(comm, cmd)
  comm.write("#{cmd}\r\n")
  sleep(0.2)

  begin
    result = comm.read
    result = "Command not support\n" if result.include?("ERROR\n")
  rescue
    result = "Writing serial port error\n"
  end

  puts result
end

于是,test_comm.rb中间部分的可以可以写成:
exec_cmd(comm, “AT”)
exec_cmd(comm, “AT+CSQ?”)

可是每添加一个AT… 还是得写一串的exec_cmd(comm… 。Dave Thomas大师说过:”Don’t Repeat Yourself!” ,这是ruby的设计理念。假设所有的AT都放在另外一个文件呢?我们也可以一个个读取出来。不过现在考虑的是暂时放在同个文件,那就定义一个字符串数组:
atcmd = {
‘AT’,
‘AT+CSQ?’,
‘AT+CREG?’
}
也可以这样写:
Atcmd = %w{
AT
AT+CSQ?
AT+CREG?
}

第二种对于添加AT比较方便,但缺点是AT不能出现空格。那么test_comm.rb 现在又可以写为:
atcmd.each {|at| exec_cmd(comm, at) }

可是,有的AT需要花一些时间才有响应。之前都默认是0.2秒,好吧,重新定义:
def exec_cmd(comm, cmd, timeout = 0.2)

sleep(timeout)

end

于是,就可以这样使用
exec_cmd(comm, “AT+CDV=10000”, 3)
exec_cmd(comm, “AT+CLCC?”)
exec_cmd(comm, “AT+CHV”)
exec_cmd(comm, “AT+CPOF”, 2)
exec_cmd(comm, “AT+CPON”, 5)

像这样的一组AT,具有依赖顺序而每个AT的响应时间又不一样,我们只能根据不同的情况对AT做分类,写不同的测试脚本。

再回头看看 test_commm.rb,如果我们想把输入与输出都放在同一个Excel表格,那该如何写呢?原理一样,依旧用win32ole:

#! /usr/bin/env ruby
#
# filename: excel.rb
# @date 2009.5.16
#

require 'win32ole'

class Excel
  def initialize(filename = nil)
@excel = WIN32OLE.new("excel.Application") # create Excel object

    @excel.Visible = TRUE
    if (filename == nil)
      @workbook = @excel.Workbooks.Add() # create new file
    else
      @workbook = @excel.Workbooks.Open(filename) # open exist file
    end
  end

  def setvalue(pos, data)
    @excel.Range(pos).Value = data
  end
  def save
    @excel.Save()
  end
  def close
    @excel.Quit()
  end
  def excelobj
    @excel
  end

end # end of class

我们重新写个test_cdma_at.rb

#! /usr/bin/env ruby
#
# test_cdma_at.rb
# @date 2009.5.16
#

require 'mscomm.rb'
require 'excel.rb'

def exec_cmd(comm, cmd)
  comm.write("#{cmd}\r\n")
  sleep(0.2)

  begin
    result = comm.read
    result = "Command not support\n" if result.include?("ERROR\n")
  rescue
    result = "Writing serial port error\n"
  end

  return result
end

atcmd = %w{
AT
AT+CPIN?
AT+CPINC?
AT+CSQ?
AT+CREG=2
AT+CREG?
AT+VMCC?;+VMNC?
AT+CPBS=?
AT+CPBS?
AT+CPBS="ME"
AT+CPBS?
AT+CPBW=3,13544049382,"violet",0
AT+CPBR=3
AT+CMGS=13544049382,"Hello!"
AT+CMGW=,13544049382,"Hi!"
}

comm  = MSCOMM.new(6)
excel = Excel.new("d:\\Book1.xls")

i = 1

atcmd.each {|at|
  excel.setvalue("a#{i}", at)
  excel.excelobj.Range("b#{i}").Value = exec_cmd(comm, at)
  i += 1
}

comm.close
excel.save
excel.close

代码不难理解,就是把AT输入放在Excel表格某行的A列,响应写入某行的B列,仅如此而已。

脚本测试也不是万能的,AT本身具有随意性,写脚本意在减轻编码工作量,避免重复机械的劳动。

If you enjoyed this post, make sure you subscribe to my RSS feed!

5 thoughts on “使用Ruby在windows下通过串口自动测试AT

Leave a Reply

Your email address will not be published. Required fields are marked *