CDMA SMS pdu解码

去年玩过via cdma模组,刚开始对cdma sms pdu真是一脸茫然,意识到我也可能不会长时间做这个,网上这类帖子少之又少,体会初学者的辛苦,重新翻尸体,记录下来。

收到两条短信,现在用AT把它们读取出来。

at+cmgr=5
+CMGR:5,”REC UNREAD”,”15338896020″,”UNKNOWN NUMBER”,”N/A”,176

“0000021002020702c54ce225a8a80601c0089d00031001e801
8e2230018801780193108b09fb087b317b012b6a080162e38c8e6
3b422e07b65980162b942e872e4b3b4246f7a70500162e54bbf9a7
053f67c7e3801729f544c0b108bb423918a75d00163317a70033b0
ae07ce3e00162b943108bb4236b54158a71680162ff5a7283b423
71c33b2b71c29dd80173108b09fb087b317c1a933cb80162b943659
b6a0bb4227122e5c00306081229192611″

at+cmgr=21
+CMGR:21,”REC UNREAD”,”15338896020″,”UNKNOWN NUMBER”,”N/A”,96

“0000021002020702c54ce225a8a806014c084d00031001f8013
e20f00190017801900162dfca7004b1acb1abb4239614c67001629
63b2b12b9827ae310c001729f544c0b108bb423918a75d00163317
a70029f52e07cf0f80306081229192616”

[deli@deli example]$ ./test_pdu_decode
0000021002020702c54ce225a8a80601c0089d00031001e8018e22
30018801780193108b09fb087b317b012b6a080162e38c8e63b422
e07b65980162b942e872e4b3b4246f7a70500162e54bbf9a7053f67
c7e3801729f544c0b108bb423918a75d00163317a70033b0ae07ce3
e00162b943108bb4236b54158a71680162ff5a7283b42371c33b2b7
1c29dd80173108b09fb087b317c1a933cb80162b943659b6a0bb422
7122e5c00306081229192611
sms context == 1/2我愿意是急流,山里的小河,在崎岖的路上,岩石上经过.只要我的爱人,是一条小鱼,在我的浪花中,快乐的游来游去.我愿意是荒林,在河流的两岸
SM_ENCODING == 4
TPA == 15338896020
SCTS == 19:26:11 12/29/08

[deli@deli example]$ ./test_pdu_decode
0000021002020702c54ce225a8a806014c084d00031001f8013e20f
00190017801900162dfca7004b1acb1abb4239614c6700162963b2
b12b9827ae310c001729f544c0b108bb423918a75d00163317a700
29f52e07cf0f80306081229192616
sms context == 2/2,对一阵阵的狂风,勇敢地作战.只要我的爱人,是一只小鸟
SM_ENCODING == 4
TPA == 15338896020
SCTS == 19:26:16 12/29/08

PDU串解析

CDMA的pdu格式与GSM的相差很多,不能直接用肉眼看出来。第一条内容比较长,就拿第二条pdu串来分析吧。
1.首先将PDU串打成PDU包
将PDU串相邻的两个ascii字符拼凑成一个8bit数据

如下:
00 00 02 10 02 02 07 02 c5 4c e2 25 a8 a8 06 01 4c 08 4d 00 03 10 01 f8 01 3e 20 f0 01 90 01 78 01 90 01 62 df ca 70 04 b1 ac b1 ab b4 23 96 14 c6 70 01 62 96 3b 2b 12 b9 82 7a e3 10 c0 01 72 9f 54 4c 0b 10 8b b4 23 91 8a 75 d0 01 63 31 7a 70 02 9f 52 e0 7c f0 f8 03 06 08 12 29 19 26 16

消息传送类型: 0x00 point to point message(表示点对点消息)

下面的内容为短消息的各个字段 每个字段分为三个部分: 字段类型(ID)(8bit)、字段长度(Length)(8bit)和字段内容.

第一个字段: 00 02 10 02
0x00, 表示uTeleserviceID字段
0x02, 字段长度,该长度必须为2,否则为错误的pdu信息

字段内容为:0x1002,十进制是4098,

第二个字段: 02 07 02 c5 4c e2 25 a8 a8
0x02, SMS_TL_ORIG_ADDR 表示 (短信发送地址)
0x07, 字段长度为7
字段内容: 02 c5 4c e2 25 a8 a8
只看前面几个 02 c5 4c e2的:
0000 0010 1100 0101 0100 1100 1110 0010 0010
取第一个bit 0 表示 RIL_CDMA_SMS_DIGIT_MODE_4_BIT 是4bit压缩
第二个bit 0 表示 RIL_CDMA_SMS_NUMBER_MODE_NOT_DATA_NETWORK
下来8个bit 是 00 0010 11 = 11,表示号码长度 为11
由于是4bit压缩 ,后面44个bit(4*11)表示号码,解析出来是
15338896020

第三个字段: 06 01 4c
表示SMS_TL_BEARER_RPLY_OPT

第四个字段:08 4d 00 03 10 01 f8 01 3e 20 f0 01 90 01 78 01 90 01 62 df ca 70 04 b1 ac b1 ab b4 23 96 14 c6 70 01 62 96 3b 2b 12 b9 82 7a e3 10 c0 01 72 9f 54 4c 0b 10 8b b4 23 91 8a 75 d0 01 63 31 7a 70 02 9f 52 e0 7c f0 f8 03 06 08 12 29 19 26 16

0x08, 表示SMS_TL_BEARER_DATA字段(短信内容)
0x4d,字段长度为77

这个字段也分成各个子字段:

第一子字段: 00 03 10 01 f8
0x00
Mesage Id
0x03 内容长度
10 01 f8  === 0001 0000 0000 0001 1111 1000
0001 表示 DELIVER 短信
0000 0000 0001 1111表示 message id.
紧接后面的 1, 表示HEADER_IND

第二个子字段:01 3e 20 f0 01 90 01 78 01 90 01 62 df ca 70 04 b1 ac b1 ab b4 23 96 14 c6 70 01 62 96 3b 2b 12 b9 82 7a e3 10 c0 01 72 9f 54 4c 0b 10 8b b4 23 91 8a 75 d0 01 63 31 7a 70 02 9f 52 e0 7c f0 f8
0x01, 字段类型
0x3e(62),字段长度
20 f0 01 === 0010 0000 1111 0000 0000 0001
0x20 的前5个bit为00100, 为0x04, 表示短信编码方式为RIL_CDMA_SMS_ENCODING_UNICODE (UNICODE)
0x20 的后3个bit, 0xf0的前5个bit,为 000 1111 0, 即0x1e (30),表示有30个UNICODE 字符。0xf0的后3个bit,0x01的8个bit,再加上0x90的前5个bit,

0000 0000 0011 0010 拼成一个16位数是 0x0032 表示字符 :2,在vim下了解一个字符的16进制码很简单,光标在该字符,按ga,底端显示结果如下:

<2>  50,  Hex 32,  Octal 062                                  2,1           All

依次下去,内容就是上面运行./test_pdu_decode 的结果: 2/2,对一阵阵的狂风,勇敢地作战.只要我的爱人,是一只小鸟

第三个子字段: 03 06 08 12 29 19 26 16

这是一个时间戳字段: 08年12月29号19时26分16秒(短消息发送时间)

字符串分析结束。当然,还有很多可选项在这条短信没有加上,更完整的SMS格式,请参考CDMA SMS standard on 3GPP2 website.

实际编码时,一个while循环遍历,再加上switch简单的状态机即可。

长短信何在?

用的这个模组,不支持长短信,厂家回答“作了预处理,把User Data Header去掉了,因为客户一般不愿意自行处理这个User Data Header,他们只要内容、号码等其它信息。所以,模块送出的PDU中不含有User Data Header。”

为实现长短信的拆分和组合功能,终端应支持 IS637C 协议中关于长短消息处理的参数 HEADER_IND,以及在短消息数据中增加对 User Data Subparameter 参数增加用户数据消息头(User Data Header)和短信拆分、组合的处理。HEADER_IND 为消息头标识位,用于指示 User Data Header 是否包含消息头, 若包含消息头则 HEADER_IND 设置为’1’,否则设置为’0’。具体的拆分与组合,请参考IS637C,或 《中国电信CDMA终端需求规范-SMS分册-V1.0》。需要说明的是,对长短信的处理,有的CDMA模组厂家为了让用户省事,帮你处理了用户数据头,正如前面所看到的,自动加上(1/2), (2/2)等,若想自己手动解析,务必跟模组厂家沟通确认好。

YY电视台:QQ 发布一天腾讯内部交流会内幕流出,马化腾主持

文章来源:http://www.androidin.net/bbs/android-75655-1-1.html

时间:2010年3月30日
与会人员:腾讯软件开发中心,客户服务部
主持人:马化腾

马化腾:开发部的同事加班加点终于赶在愚人节前夕发布了QQ.APK,我很满意。大家辛苦了。
开发部经理:(讪笑)没啥,就是安排个实习生用了一天时间把QQmini重新封装为apk而已,呵呵
实习生:(不好意思地)对啊,昨天经理给了我QQmini,然后我找美工小王设计了几张图片披,就编译成apk罢了
客户部经理:(为难地)马总,我这有个情况,才发布一天不到,用户的投诉已经挤爆了,全部是负面的。
开发部经理:是啊,我上各个手机论坛溜达,用户很不满意,在不同程度地批评、诅咒、嘲讽我们。

马化腾:(皱着眉头)你们两个经理,怎么说也和我一起混了十年了,还准备把你们提为副总的,怎么没点悟性?
开发部经理:啊?怎么了?
客户部经理:不明白啊…
实习生:我觉得这个Android的开发方案是公司有意为之,故意造成这种效果的。

马化腾:(颔首微笑)嗯,好,没想到你新来炸到居然有这一层领会。
马化腾:(顿了顿)我给你们讲个案例。有两个卖包子的,包子的水平都很高。其中一个一开张就拿出绝活把包子的看家本事都招呼出来,但顾客增长缓慢,而且他再推出新品种的东西反响不强烈。另一个人开张时做出很差的包子,买的人很少,可是他一周一个新品种,而且每一个新品种都比前一周有明显进步,顾客越来越多,甚至都在盼下一周他能推出什么好东西。
马化腾:(笑着说)IT与传统行业本质完全相同。我们其实就是卖包子的。

开发部经理:哦,您的意思是在开始做得差,用户才有慢慢满意的进步感?
客户部经理:我明白了,这样用户才会感到自己的需求不断被被满足,而QQ软件也一天比一天好,有盼头。
实习生:我想马总最看重的还是下载量,因为对前一个版本有不满之处,因此下一个版本更新,用户会蜂拥而至,卸载旧的,下载新的安装。这样我们腾讯的下载量在数据上就非常好看了,做商业报告书也能风风光光。要是一开始就是完美的,很多人赖着不更新,我们向谁要下载量?怎么维系我们向媒体公布的1亿用户同时在线的数据?

马化腾:(吃惊地)我实在不敢相信你是一个实习生!深知吾意啊!
实习生:马总您过奖了,我其实从手机中悟出的,如果手机太完美,用户就不会想换机,企业咋赚钱?
开发部经理:唉,我终于明白进化论了,产品得有从差到好的过渡过程,没有这个过程,用户是培养不起来的。
客户部经理:明白是明白了,只是我们客户部就要为这个过程不停为用户陪笑脸罢了。

实习生:我已经在开发时为这个做好了未来一两个版本的预设,大家看到软件的设置界面只有三个大图标按钮:“QQ邮箱”,“设置”,“网址收藏”,但其实我早已做好了一批图标是准备放在这个界面的,大家可解压.apk看里面的图片目录,就能看到很多新功能图片已经做好备用的了。功能模块也已经写好了,就等着公司决定发布下一个版本时,我直接把图标放上去,把功能开关打开,不费吹灰之力,一个新版本就做好了。
开发部经理:(不可思议的)你用一天时间就完成了这个?
实习生:不是啊,从我最早看公司下达的APKQQ的开发计划,我就已经大概知道了会怎么发展,为了减轻自己工作量,在开发时能少加班,我就提前准备喽!呵呵
马化腾:后生可畏!你比当年的我有才多了。
实习生:其实我在玩手机时装另一些系统的手机QQ时我就已经知道了呀,嘻嘻,您还不知道吧?在还没有进公司时,我作为一个手机玩家,在论坛上骂QQ不会比其他人少呢,呵呵。

马化腾:哈哈,好,非常好!
实习生:其实,我在开发第一个版本的QQ.apk时,已经故意设定了一些Bug,比如执行速度比较卡,比较费流量,等等。这样在下一个版本时,除了新添加一些功能模块,我还能把这些BUG给堵住,然后写在软件更新日志里,这样用户就会觉得我们很注重他们的反馈,具有不断锐意进取的企业精神了。

马化腾:(长叹一声)你现在这个职位实在是屈才了。现在我决定,腾讯互联网软件开发中心的执行总经理一职由你担任,年薪80万不含年终奖,配粤迪 A6L 2.0T 一台,网络软件的开发由你全权把控,这个担子我今天就交给你了。
开发部经理:(一脸媚笑)小王。。。啊不,王总,恭喜你呀!不要忘了提携小弟我呀……
实习生:(冷笑一声,附身过去在他耳边说)陈经理,我入职以来帮你做的私单,你吞掉了本应我的那一份18万吧?限你一天内打我帐上,同时以后我有私单你必须无条件支持我,你做的全部私单资料我那里有备份,你要是不识相,哼哼…
开发部经理:(庐山瀑布汗)是是,小的照办。。。

实习生:马总,我已经起草了apk版QQ的发展大纲,Google退出对我们正好是一次不错的炒作机会,我们两找个地方待我详细跟你说说。
马化腾:满意地,好。

客服部经理在临走前叹一口气说:网友个个都说QQ是聊天的工具,其实无知的网友只是被工具了,他们的一切反应均在我们的预料中,所以发财的是我们腾讯,网友只能装着个差强人意的QQ在那里骂骂咧咧。。。。

Broncho网站访问速度优化

前些时候,据网友反应,Broncho论坛访问很慢,开始觉得服务器在美国,慢是正常的,加上其他事情多,也没在意。昨晚在宿舍打开了 bbs.broncho.cn,超过了30秒还没显示,不耐烦。听说eoe android 的网站也搬到了美国,对比测试一下,eoe访问速度比broncho快多了,于是今天计划优化一下。网站流量比较小,就一台主机,没计划做cache,更谈不上CDN了,于是只好做一些小局部优化。

优化原则,当然是Yahoo的 Best Practices for Speeding Up Your Web Site
Yahoo的做法甚至是有些“变态”了,我还发现有其他更变态的优化 :(
首先,用雅虎的YSlow工具测试一下,看看瓶颈在哪,才好下手。YSlow是一个Firefox插件,这个插件依赖于Firebug插件,web开发人员对后一个大家应该很熟悉了。

1. 服务器端apache使用mod_deflate压缩页面

我们服务器是fedora 8,自带的apache也早装有mod_deflate,在http.conf配置文件添加以下内容即可。

<IfModule mod_deflate.c>
	DeflateCompressionLevel 7
	AddOutputFilterByType DEFLATE text/html text/plain text/xml application/x-httpd-php
	AddOutputFilter DEFLATE css js
</IfModule>

在http://www.whatsmyip.org/http_compression/页面测试,结果如下:

http://bbs.broncho.cn is gzipped

Original Size: 73.51 KB
Gzipped Size: 16.64 KB
Data Savings: 77.36%

效果非常明显。还有一个网站http://www.port80software.com/products/httpzip/compresscheck 它的作用是检测你的网站是否被压缩,以及压缩比率等。 用firefox与chrome分别打开broncho论坛,firefox显得有点慢,chrome哇啦哇啦的页面就显示了,chrome不愧号称速度是最快的浏览器。

2. 配置 Apache Etag
用Apache的mod_expires 模块来设置。

<IfModule mod_expires.c>
        <filesmatch "\.(jpg|gif|png|css|js)$">
                ExpiresActive on
                ExpiresDefault "access plus 2 month"
        </filesmatch>
</IfModule>

加上这个后,broncho.cn首页的Grade由C升到B,Overall performance score由79变为88!,好吉利的数字,我喜欢!

3. 合并压缩 css,javascript文件
在broncho首页,有两个css
<link href="/css/broncho_v1.css" rel="stylesheet" type="text/css" />

<link href="/css/inlay.css" rel="stylesheet" type="text/css" />
于是把他们合并在一起,以减少 http 请求次数。

有一个css在线压缩工具:
http://www.cssdrive.com/index.php/main/csscompressor

压缩后,可以选择把注释去掉,大概是这样:
html{background:#ccc; font-size:13px; margin:0}
body{margin:0; font-family:Arial; color:#333; background:url(/images/android2-bg.gif) center repeat-y}
div.body-wide{background:#fff; width:100%}

就是每个标签的属性,都写在同一行上,有的公司就要求这样。我还是坚持这样的风格:

/* $Id: broncho_v1.css 215 2010-02-01 09:06:21Z deli $ */

html {
	background:#ccc;
	font-size:13px;
	margin:0;
}
body {
	margin:0;
	font-family:Arial;
	color:#333;
	background:url(/images/android2-bg.gif) center repeat-y;
}
div.body-wide {
	background:#fff;
	width:100%;
}

主要考虑维护修改方便,不好之处就是每修改一次,都得重新压缩一次。JavaScript用YUI Compressor压缩。

4. 减小 html页面
用tab键进行代码缩进,以节约代码大小,这个可能比较变态。
用2个空格缩进的index.html:
[deli@athena html]$ ll index.html
-rw-rw-r–. 1 deli deli 5816 2010-06-22 10:40 index.html

替换为tab之后的index.html:
[deli@athena html]$ ll index.html
-rw-rw-r–. 1 deli deli 5342 2010-06-22 11:08 index.html
index.html文件本身就比较小,大约减少0.5K这样,效果不是很显著。

5. phpbb论坛优化
broncho论坛采用 phpbb,前段时间对w3c鬼迷心窍,为了使得firefox右下角 Html Validator大红叉去掉,把一些插件的@import 全部写到了overall_header.html,这样首页都要把这些css,js全部加载,装七七八八的插件都堆在overall_header.html,自然会变慢。作为折衷考虑,只好把这些js,css放在真正需要的页面。

phpbb本身确实没什么大的优化了,模板解析,sql查询,都放在cache里,如果可以优化的话,phpbb的开发人员早就把这个问题搞定。记得之前做过CDN,服务器内存都是4G以上,以空间换时间,把很多文件映射的内存中,所以也试试用tmpfs来存放phpbb的 cache,php session。

#phpbb cache:
mkdir /dev/shm/cache
chmod 1777 /dev/shm/cache/
mount --bind /dev/shm/cache/ /var/www/html/forum/cache/

#php session:
mkdir /dev/shm/session
chmod 1777 /dev/shm/session/
mount --bin /dev/shm/session/ /var/lib/php/session/ 

6. 其他杂项
* img使用 width 和 height 属性来定义图像尺寸,以便图像被更快地显示。
* 网址后加斜杠

参考:
1.《如何提高网站访问速度 从30秒到3秒的改变》,不知道作者是谁,大家可以搜索一下。
2. oasisfeng phpBB论坛优化拾零
3. Apache Cache Last-Modified、Expires和Etag相关工作原理

Protocol Buffers in Android

Protocol Buffers in Android

无意中看到android market调试Log信息:”Lcom/google/common/io/protocol/ProtoBuf;”, 觉得好奇,搜索一下,ProtoBuf其源代码位于 external/protobuf/src/com/google/common/io/protocol,这个可不同于com.google.protobuf 包,后者是Google标准官方实现,com.google.common.io.protocol是Android平台上的,提供的接口,可以在这里查阅 http://www.androidjavadoc.com/m5-rc15/com/google/common/io/protocol/ProtoBuf.html

在 cupcake源代码目录下搜索ProtoBuf,没有找到使用ProtoBuf的相干代码。目前我发现只有android market使用这个库,market的数据交换格式不是什么xml或json,当然采用Google自家发明的Protocol Buffers。

update: 2010/08/19: 下载了 Android 2.2的代码,发现external/protobuf/目录不见了,被整进了 GoogleServicesFramework.apk 这个包,美曰其名: Google 服务框架。

使用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本身具有随意性,写脚本意在减轻编码工作量,避免重复机械的劳动。

Pages: Prev 1 2 3 ... 11 12 13 14 15 16 17 18 19 20 21 Next