Delphi下的手机短信投票平台(下)

这一篇主要讲一下短信的接受部分。
短信被手机接受后可以有好几种处理方法,我只说三种:
  1. AT+CNMI=0,0,0,0,0
    短信到来后不告知主机,需要要主机定时使用AT+CMGL轮讯新消息,这种方式显然是不可取的,效率太低,实时性也不好。
  2. AT+CNMI=2,1,0,0,0
    短信到来后使用+CMTI告知主机新短信的存储位置以及序号,等待主机使用AT+CMGR读取该消息。由于短信投票会在短时间内收到大量数据,如果每一条短信都被存储在手机中再读出分析,这势必会影响处理的速度。
  3. AT+CNMI=2,2,0,0,0
    短信到来后,直接用+CMT把PDU串发送给主机,手机不做任何保存操作,这种方法效率是最高的,但是要求主机要能准确无误的收到所有的数据包,否则就会丢包了。
初始化手机的代码如下:

  ComMobile.WriteStr('AT+CNMI=2,2,0,0,0'+#13);
  Sleep(2000);
  ComMobile.ReadStr(buff, 22);
  if Copy(buff, 21, 2) <> 'OK' then
  begin
    ShowMessage('初始化错误!');
    Exit;
  end;
  ComMobileData.StopString := #13#10;
  ComMobileData.ComPort := ComMobile;

这里使用了一个TComDataPacket控件ComMobileData用于处理接到的所有数据(使用#13#10进行自动包分割)。其处理代码如下
procedure TFormMain.ComMobileDataPacket(Sender: TObject; const Str: string);
begin
  if Length(Str) = 0 then Exit;
  lstLog.Items.Append(Str);
  lstLog.ItemIndex := lstLog.Items.Count-1;
  if Copy(Str, 1, 1) = '>' then Exit;
  if Copy(Str, 1, 2) = 'OK' then Exit;
  if Copy(Str, 1, 1) = '+' then Exit;
  if Copy(Str, 1, 2) = 'AT' then Exit;
  if Copy(Str, 1, 5) = 'ERROR' then
  begin
    ShowMessage('错误!');
    Exit;
  end;
  PhraseSMS(Str);
end;

PhraseSMS是用于解码PDU包的,有如下注意事项:
英文短信的编码是0x00,使用压缩7bit方法编码,如要编码“hellohello”,方法如下:

hellohello
104101108108111104101108108111
1101000110010111011001101100110111111010001100101110110011011001101111
1101000
1100101
1101100
1101100
1101111
1101000
1100101

1101100
1101100
1101111


11101000
00110010
10011011
11111101
01000110
10010111
11011001


11101100


110111
E8329BFD4697D9


EC37

这一部分我是用内嵌汇编实现的,好好体会一下就明白怎么实现的了。
至于中文的UCS2编码,只是做了简单的拼装,注意高低字节千万不要弄反了。

procedure TFormMain.PhraseSMS(msg: string);
var
  num: string;
  str: WideString;
  wchar: WideChar;
  t: TDateTime;
  i, j, k: Integer;
  b1, b2, r: Byte;
begin
  i := StrToInt('0x'+Copy(msg, 1, 2));
  Delete(msg, 1, 2*(i+2));
  i := StrToInt('0x'+Copy(msg, 1, 2));
  Delete(msg, 1, 4);
  num := '';
  for j := 1 to ((i+1) div 2) do
  begin
    num := num+msg[2];
    if (j < ((i+1) div 2)) or ((i mod 2) = 0) then num := num+msg[1];
    Delete(msg, 1, 2);
  end;
  Delete(msg, 1, 2);
  k := StrToInt('0x'+Copy(msg, 1, 2));
  Delete(msg, 1, 2);
  t := StrToDateTime('20'+msg[2]+msg[1]+'-'
                       +msg[4]+msg[3]+'-'
                       +msg[6]+msg[5]+'-'
                       +msg[8]+msg[7]+':'
                       +msg[10]+msg[9]+':'
                       +msg[12]+msg[11]);
  Delete(msg, 1, 14);
  i := StrToInt('0x'+Copy(msg, 1, 2));
  Delete(msg, 1, 2);
  str := '';
  if k = 0 then
  begin
    j := 0;
    b2 := 0;
    r := 0;
    while j < i do
    begin
      Inc(j);
      Inc(b2);
      b1 := StrToInt('0x'+Copy(msg, 1, 2));
      asm
        MOV AL,b1
        MOV AH,0
        MOV CL,b2
        SHL AX,CL
        SHR AL,1
        OR  AL,r
        MOV r,AH
        MOV b1,AL
      end;
      str := str+Chr(b1);
      if (j+1) mod 8 = 0 then
      begin
        Inc(j);
        str := str+Chr(r);
        r := 0;
        b2 := 0;
      end;
      Delete(msg, 1, 2);
    end;
  end;
  if k = 8 then
  begin
    for j := 1 to (i div 2) do
    begin
      b1 := StrToInt('0x'+Copy(msg, 1, 2));
      b2 := StrToInt('0x'+Copy(msg, 3, 2));
      Delete(msg, 1, 4);
      asm
        MOV AH,b1
        MOV AL,b2
        MOV wchar,AX
      end;
      str := str+wchar;
    end;
  end;
  Vote(num, str, t);
end;

后面就是做一些简单的投票处理了,都是简单的数据库操作,比如查看时候有重复投票等等……这里就不罗嗦了,也没什么技术含量,呵呵
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值