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

时间:2022-09-17 19:07:50
这个投票平台是原理性的,使用的是普通的Nokia 6100作为接收端设备,没有经过严格的测试,在大量信息同时接受时可能出现短信拥塞、延时。

预备资料:
  1. Delphi下的ComPort控件
  2. Nokia AT Command Set
  3. SMS PDU Format

这里只说一下短信发送、接受的处理方法,至于收到短信后如何识别序号和更新数据,不是本文的重点。
在主窗体新建一个TComPort控件,名为ComMobile用于读写串口。将FlowControl中的DTR、RTS控制选项开启(Enable),否则无法与Nokia手机通讯。

首先使用AT+CMGS指令实现短信的发送。查阅PDU包格式进行编码。
注意以下几点:
  1. 最开始的“00”是指此PDU包不含有短消息中心信息,使用手机默认的短消息中心。
    注意:这个“00”不算在PDU长度里面,所以AT+CMGS命令所带的长度参数是从“11”开始计算起的,PDU包字节数(2个16进制编码一个字节)。
  2. 对小灵通的号码做了特殊处理,其号码类型为0xA1,即国内电话号码没有加号。
  3. 接受方号码为半字节拼装存储,一定要注意顺序,先低四位后高四位,不足的补1111。
  4. 直接使用UCS2编码,没有考虑到英文短信的问题。而且WideString本身就是UCS2编码的,所以直接转成16进制即可。
  5. 使用#13,不要使用#10!!#26是Ctrl+Z 。
  6. 这段代码没有考虑手机的应答,无法处理一些特殊错误~~~比如,手机没钱了,发不出短信 :-p

procedure TFormMain.SendSMS(num: string; text: WideString);
var
  sms: string;
  i, j, k: Integer;
  wchar: WideChar;
begin
  sms := ' 001100'+IntToHex(Length(num), 2);
  if Copy(num, 1 ,3) = '106' then
    sms := sms+'A1'
  else
    sms := sms+'91';
  for i := 1 to ((Length(num)+1) div 2) do
  begin
    if (i < ((Length(num)+1) div 2)) or (Length(num) mod 2 = 0) then
      sms := sms+num[2*i]+num[2*i-1]
    else
      sms := sms+'F'+num[2*i-1];
  end;
  sms := sms+'0008A7';
  sms := sms+IntToHex(Length(text)*2, 2);
  for i := 1 to Length(text) do
  begin
    wchar := text[i];
    sms := sms+IntToHex(Integer(wchar), 4);
  end;
  ComMobile.WriteStr('AT+CMGS='+IntToStr (Length(sms) div 2-1)+#13);
  ComMobile.WriteStr(sms+#26#13);
end;