⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 smthread.pas

📁 通过串口发送多条短信的群发软件
💻 PAS
📖 第 1 页 / 共 2 页
字号:
unit smthread;

interface

uses
  Classes,SysUtils,AdPort,ExtCtrls,ComCtrls;

type
  smioThread = class(TThread)
  private
    current_command:String;//当前发送的指令
    current_answer:String;//针对当前指令返回的结果

    current_sm_tel:String;//当前短信的发送地址
    current_sm_content:String;//当前短信的内容

    task_index:integer;//该任务信息在数据库中的索引

    task_id:string;//任务ID
    mobile_tel:string;//要发送短信的手机号
    mobile_tel_account:integer;//要发送短信的手机号数量
    sm_content:string;//短信内容
    not_send_tel:string;//未发送短信的手机号
    not_send_account:integer;//未发送的手机号数量
    send_tel:string;//已正确发送短信的手机号
    send_account:integer;//已正确发送短信的手机号数量
    error_send_tel:string;//发送错误的手机号
    error_send_account:integer;//发送错误的手机号数量

    send_time:string;//计划发送时间
    dest_tel:string;//目的手机号

    task_state:string;//任务状态

    username:string;//目的手机号对应的用户名

    timeout_count:Integer;//超时记数

    procedure get_new_task();//取得新任务的信息
    procedure set_task_state();//设置指定任务的状态
    procedure get_username();//取得手机号对应的用户名

    procedure save_current_task();//保存当前任务的执行结果
    procedure clear_task_info();//清空当前任务信息

    procedure get_service_tel();//取得短信中心号码
    procedure clear_command_answer();//清空当前指令和返回结果
    procedure begin_to_send();//开始发送短信
    procedure send_message();//发送短信内容
    procedure get_rec_unread();//取未读短信
    procedure get_rec_read();//取已读短信
    procedure delete_rec(index:Integer);//删除索引值对应的短信

    procedure add_user_name();//向收件箱添加用户名

    procedure process_open_or_close_comport();//处理打开或关闭端口
    procedure process_received_buffer();//处理接收的数据
    procedure process_send_message();//处理短信发送
    procedure process_get_rec();//处理短信接收
    procedure process_delete_sm();//处理短信删除

    procedure translate_rec(sm_str:String;read_state:Boolean);//转换已读短信

    procedure start_timeoutTimer();//启动超时计数定时器
    procedure stop_timeoutTimer();//停止超时计数定时器
    procedure timeoutTimerOnTimer(Sender: TObject);//定时器的触发器
    { Private declarations }
  protected
    procedure Execute; override;
  public
    constructor Create(CreateSuspended: Boolean);
  end;

implementation

uses main, log, inbox, other;

{ Important: Methods and properties of objects in visual components can only be
  used in a method called using Synchronize, for example,

      Synchronize(UpdateCaption);

  and UpdateCaption could look like,

    procedure smioThread.UpdateCaption;
    begin
      Form1.Caption := 'Updated in a thread';
    end; }

{ smioThread }

constructor smioThread.Create(CreateSuspended: Boolean);
begin
  //初始化
  clear_command_answer;
  current_sm_tel:='';
  current_sm_content:='';
  clear_task_info;
  
  //生成串口对象
  smsApdComPort:=TApdComPort.Create(mainForm);
  smsApdComPort.Parity:=pNone;
  smsApdComPort.DataBits := 8;
  smsApdComPort.StopBits := 1;
  smsApdComPort.AutoOpen:=False;

  //生成超时计数器对象
  timeoutTimer:=TTimer.Create(mainForm);
  timeoutTimer.Enabled:=False;
  timeoutTimer.Interval:=1000;
  timeoutTimer.OnTimer:=timeoutTimerOnTimer;

  FreeOnTerminate := True;
  inherited Create(CreateSuspended);
end;

procedure smioThread.get_new_task();
var
  i:integer;
begin
  //已连接手机
  if serivce_tel<>'' then
    for i:=0 to mainForm.taskListView.Items.Count-1 do
      if mainForm.taskListView.Items.Item[i].SubItems.Strings[0]='发送' then
      begin
        task_index:=i+1;
        taskadoquery.RecNo:=i+1;
        task_id:=taskadoquery.Fields.Fields[0].AsString;
        mobile_tel:=taskadoquery.Fields.Fields[1].AsString;
        send_time:=taskadoquery.Fields.Fields[2].AsString;
        mobile_tel_account:=taskadoquery.Fields.Fields[3].AsInteger;

        send_account:=taskadoquery.Fields.Fields[4].AsInteger;
        error_send_account:=taskadoquery.Fields.Fields[5].AsInteger;
        not_send_account:=taskadoquery.Fields.Fields[6].AsInteger;
        sm_content:=taskadoquery.Fields.Fields[7].AsString;

        send_tel:=taskadoquery.Fields.Fields[8].AsString;
        error_send_tel:=taskadoquery.Fields.Fields[9].AsString;
        not_send_tel:=taskadoquery.Fields.Fields[10].AsString;

        exit;
      end;
end;

procedure smioThread.process_open_or_close_comport();//处理打开或关闭端口
var
  i:Integer;
begin
  //端口已关闭
  if not smsApdComPort.Open  then
  begin
    //暂停线程
    if not self.Suspended then
    begin
      //显示中断端口连接状态
      mainForm.jlljSpeedButton.Caption:='建立连接';
      mainForm.ljszSpeedButton.Enabled:=True;
      mainForm.jlljSpeedButton.Enabled:=True;
      //显示连接状态
      mainForm.smsStatusBar.Panels.Items[2].Text:='尚未检测到工作手机';
      //清空短信服务中心号码
      serivce_tel:='';

      //清空当前指令和返回的结果
      self.clear_command_answer;
      //清空当前任务的信息
      self.clear_task_info;

      //停止当前所有任务
      for i:=0 to mainForm.taskListView.Items.Count-1 do
      begin
        if mainForm.taskListView.Items.Item[i].SubItems.Strings[0]='发送' then
        begin
          //设置等待图标
          mainForm.tasklistview.Items.Item[i].ImageIndex:=2;
          //改变状态
          mainForm.tasklistview.Items.Item[i].SubItems.Strings[0]:='等待';
        end;
      end;

      //显示和隐藏相关按钮
      if mainForm.tasklistview.ItemIndex>=0 then
      begin
        i:=mainForm.tasklistview.ItemIndex;
        mainForm.tasklistview.ItemIndex:=-1;
        mainForm.tasklistview.ItemIndex:=i;
      end;
      
      //暂停线程
      self.Suspend;
    end;
  end
  //端口已打开
  else
  begin
    //还没取得短信服务中心号码
    if (serivce_tel='') and (current_command='') then
    begin
      //发送短信索取短信服务中心号码
      get_service_tel;
      //启动超时计数定时器
      start_timeoutTimer();
    end;
  end;
end;


procedure smioThread.set_task_state();
begin
  mainForm.taskListView.Items.Item[task_index-1].SubItems.Strings[0]:=task_state;
  if task_state='完成' then
    mainForm.taskListView.Items.Item[task_index-1].ImageIndex:=4;
end;

procedure smioThread.save_current_task();//保存当前任务的执行结果
begin
  //修改数据库中的任务信息
  taskadoquery.RecNo:=task_index;
  taskadoquery.Edit;
  taskadoquery.Fields.Fields[4].AsInteger:=send_account;
  taskadoquery.Fields.Fields[5].AsInteger:=error_send_account;
  taskadoquery.Fields.Fields[6].AsInteger:=not_send_account;
  taskadoquery.Fields.Fields[8].AsString:=send_tel;
  taskadoquery.Fields.Fields[9].AsString:=error_send_tel;
  taskadoquery.Fields.Fields[10].AsString:=not_send_tel;
  taskadoquery.Post;

  //修改任务列表中的信息
  mainForm.taskListView.Items.Item[task_index-1].SubItems.Strings[3]:=inttostr(send_account);
  mainForm.taskListView.Items.Item[task_index-1].SubItems.Strings[4]:=inttostr(error_send_account);
  mainForm.taskListView.Items.Item[task_index-1].SubItems.Strings[5]:=inttostr(not_send_account);
end;

procedure smioThread.get_username();
var
  i:integer;
begin
  for i:=0 to mainForm.userListView.Items.Count-1 do
    if mainForm.userListView.Items.Item[i].SubItems.Strings[1]=dest_tel then
    begin
      username:=mainForm.userListView.Items.Item[i].Caption;
      exit;
    end;
end;

procedure smioThread.begin_to_Send();
begin
  //开始发送短信
  if current_command='' then
  begin
    current_command:='AT+CMGS=1'+#13;
    smsApdComPort.PutString(current_command);

    //启动计时器
    start_timeoutTimer;

    logForm.logMemo.Lines.Add('准备发送短信');
  end;
end;

procedure smioThread.Execute;
begin
  { Place thread code here }

  repeat
    //处理打开或关闭端口
    Synchronize(process_open_or_close_comport);

    //接收和处理数据
    Synchronize(process_received_buffer);

    //处理短信发送
    Synchronize(process_send_message);

    //处理短信接收
    Synchronize(process_get_rec);

    //处理短信删除
    Synchronize(process_delete_sm);
    
  until self.Terminated;

end;

procedure smioThread.process_received_buffer();//处理接收的数据
var
  c:Char;
  current_answer_length:Integer;
  i:Integer;
begin
  while smsApdComPort.Open and smsApdComPort.CharReady do
  begin
    c:=smsApdComPort.GetChar;
    current_answer:=current_answer+c;

//    logForm.logMemo.Lines.Text:=logForm.logMemo.Lines.Text+c;
  
    //判断是否接收到完整的回复
    current_answer_length:=Length(current_answer);
    //收到换行键
    if (current_answer[current_answer_length]=#10) then
    begin
      //收到 OK
      if (current_answer[current_answer_length-5]=#13) and
      (current_answer[current_answer_length-4]=#10) and
      (current_answer[current_answer_length-3]='O') and
      (current_answer[current_answer_length-2]='K') and
      (current_answer[current_answer_length-1]=#13) and
      (current_answer[current_answer_length]=#10) then
      begin
        // 当前的指令是 'AT+CSCA?'+#13
        if current_command='AT+CSCA?'+#13 then
        begin
          serivce_tel:=Copy(current_answer,Pos('"',current_answer)+2,13);

          mainForm.smsStatusBar.Panels.Items[2].Text:='连接到手机';

          logForm.logMemo.Lines.Add('短信服务中心的号码是:'+serivce_tel);

          //清空当前指令和返回的结果
          clear_command_answer;

          //显示和隐藏相关按钮
          if mainForm.tasklistview.ItemIndex>=0 then
          begin
            i:=mainForm.tasklistview.ItemIndex;
            mainForm.tasklistview.ItemIndex:=-1;
            mainForm.tasklistview.ItemIndex:=i;
          end;

          mainForm.jlljSpeedButton.Caption:='中断连接';
          mainForm.jlljSpeedButton.Enabled:=True;

          //停止超时计时器
          self.stop_timeoutTimer;
        end
        // 当前指令是 'AT+CMGS=1'+#13
        else if current_command='AT+CMGS=1'+#13 then
        begin
          logForm.logMemo.Lines.Add('发送成功! '+current_sm_content+' 到 '+
          current_sm_tel);

          send_account:=send_account+1;
          send_tel:=send_tel+dest_tel+';';
          
          //保存当前任务的执行结果
          save_current_task;

          //清空当前指令和返回的结果
          clear_command_answer;
          //清空手机号和短信内容
          current_sm_tel:='';
          current_sm_content:='';

          mainForm.smsStatusBar.Panels.Items[0].Text:='系统空闲';

          //该任务已完成
          if not_send_account=0 then
          begin
            task_state:='完成';

            //更新状态
            set_task_state;

            //重新初始化
            clear_task_info;

            //显示和隐藏相关按钮
            if mainForm.tasklistview.ItemIndex>=0 then
            begin
              i:=mainForm.tasklistview.ItemIndex;
              mainForm.tasklistview.ItemIndex:=-1;
              mainForm.tasklistview.ItemIndex:=i;
            end;

          end;

          //检查该任务当前状态
          if task_index>=1 then
            if mainForm.taskListView.Items.Item[task_index-1].SubItems.Strings[0]='等待' then
              //重新初始化
              clear_task_info;

          //停止超时计时器
          self.stop_timeoutTimer;
        end
        // 当前指令是 'AT+CMGL=0'+#13
        else if current_command='AT+CMGL=0'+#13 then
        begin
          logForm.logMemo.Lines.Add(self.current_answer);

          //显示未读短信
          self.translate_rec(self.current_answer,False);

          //添加用户名
          self.add_user_name;
          
          //清空当前指令和返回的结果
          clear_command_answer;

          //显示相关按钮
          inboxForm.refleshSpeedButton.Visible:=True;
        end
        // 当前指令是 'AT+CMGL=1'+#13
        else if current_command='AT+CMGL=1'+#13 then
        begin
          logForm.logMemo.Lines.Add(self.current_answer);

          //显示已读短信
          self.translate_rec(self.current_answer,True);

          //清空当前指令和返回的结果
          clear_command_answer;

          //取未读短信
          get_rec_unread;

          logForm.logMemo.Lines.Add('取未读短信');
        end
        //当前指令是 'AT+CMGD='+IntToStr(delete_rec_index)+#13
        else if current_command='AT+CMGD='+IntToStr(delete_rec_index)+#13 then
        begin
          logForm.logMemo.Lines.Add(self.current_answer);

          //删除列表中的短信
          for i:=0 to inboxForm.inboxListView.Items.Count-1 do
            if inboxForm.inboxListView.Items.Item[i].Caption=IntToStr(delete_rec_index) then
            begin
              //删除列表中的短信
              inboxForm.inboxListView.Items.Item[i].Delete;
              //重新初始化
              delete_rec_index:=0;

              break;
            end;  

          //清空当前指令和返回的结果
          clear_command_answer;

          //显示相关按钮
          inboxForm.refleshSpeedButton.Enabled:=True;
          inboxForm.deleteSpeedButton.Enabled:=True;

          //显示选中的短信内容
          i:=inboxForm.inboxListView.ItemIndex;
          inboxForm.inboxListView.ItemIndex:=-1;
          inboxForm.inboxListView.ItemIndex:=i;
        end;
      end
      //收到 ERROR
      else if (current_answer[current_answer_length-8]=#13) and
      (current_answer[current_answer_length-7]=#10) and
      (current_answer[current_answer_length-6]='E') and
      (current_answer[current_answer_length-5]='R') and
      (current_answer[current_answer_length-4]='R') and
      (current_answer[current_answer_length-3]='O') and

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -