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

📄 umain.pas

📁 DSC(Data Service Center)用来接收和处理DTU发送过来的数据;如上图
💻 PAS
📖 第 1 页 / 共 3 页
字号:
unit umain;

interface


uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, Menus, ComCtrls, ToolWin, StdCtrls, ImgList, ExtCtrls, NMUDP,winsock;

const  MAX_RECEIVE_BUF=960; //最大接收缓冲区
const  MAX_SEND_BUF=960;   //最代发送缓冲区
const  NO_DIRECTORY='no_directory';

type
  // 用户注册信息结构
  gprs_user_info=record
	m_userid:array[1..12] of char;	//终端模块号码
	m_sin_addr:cardinal;     	//终端模块进入Internet的代理主机IP地址
	m_sin_port:word;     	        //终端模块进入Internet的代理主机IP端口
	m_local_addr:cardinal;   	//终端模块在移动网内IP地址
	m_local_port:word;   	        //终端模块在移动网内IP端口
	m_logon_date:array[1..20] of char; 	//终端模块登录时间
	m_update_time:array[1..20] of char; //终端模块更新信息时间
	m_status:byte;		        //终端模块状态, 1 在线 0 不在线
     end;

  //用户数据结构
  data_record=record
	m_userid:array[1..12] of char;
	m_recv_date:array[1..20] of char;
	m_data_buf:array[1..MAX_RECEIVE_BUF] of char;
	m_data_len:word;
	m_data_type:byte;
        //m_data_null:array[1..1000] of char;
     end;
  THandle=cardinal;

  
  TForm1 = class(TForm)
    MainMenu1: TMainMenu;
    N1: TMenuItem;
    N2: TMenuItem;
    N3: TMenuItem;
    N4: TMenuItem;
    N5: TMenuItem;
    N6: TMenuItem;
    N7: TMenuItem;
    ListView1: TListView;
    ToolBar1: TToolBar;
    StatusBar1: TStatusBar;
    Label1: TLabel;
    CheckBox2: TCheckBox;
    Memo1: TMemo;
    ImageList1: TImageList;
    ToolButton1: TToolButton;
    ToolButton2: TToolButton;
    ToolButton3: TToolButton;
    ToolButton4: TToolButton;
    ToolButton5: TToolButton;
    ToolButton6: TToolButton;
    S1: TMenuItem;
    IP1: TMenuItem;
    N8: TMenuItem;
    CheckBox3: TCheckBox;
    N9: TMenuItem;
    Timer1: TTimer;
    GroupBox1: TGroupBox;
    N10: TMenuItem;
    N11: TMenuItem;
    T1: TMenuItem;
    Edit1: TEdit;
    Button1: TButton;
    Edit2: TEdit;
    RadioButton2: TRadioButton;
    RadioButton1: TRadioButton;
    Label2: TLabel;
    N12: TMenuItem;
    A1: TMenuItem;
    Panel1: TPanel;
    Panel2: TPanel;
    Shape1: TShape;
    Shape2: TShape;
    Shape3: TShape;
    Shape4: TShape;
    Shape5: TShape;
    Shape6: TShape;
    Shape7: TShape;
    Shape8: TShape;
    Shape9: TShape;
    Shape10: TShape;
    Shape11: TShape;
    Shape12: TShape;
    Shape13: TShape;
    Shape14: TShape;
    Shape15: TShape;
    Shape16: TShape;
    CheckBox1: TCheckBox;
    Timer2: TTimer;
    F1: TMenuItem;
    CheckBox4: TCheckBox;
    I1: TMenuItem;
    ToolButton7: TToolButton;
    N13: TMenuItem;
    R1: TMenuItem;
    NMUDP1: TNMUDP;
    N14: TMenuItem;
    procedure N5Click(Sender: TObject);
    procedure ToolButton1Click(Sender: TObject);
    procedure ToolButton2Click(Sender: TObject);
    procedure IP1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure N8Click(Sender: TObject);
    procedure N9Click(Sender: TObject);
    procedure CheckBox3Click(Sender: TObject);
    procedure ToolButton4Click(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
    {
            定时器函数,每隔2 min执行一次,用于查询当前和服务器连接的
        终端的信息,然后将信息显示在listview中。
            由于用户登录时没有提示,所以只能不停的通过函数Get_user_at
        函数去读取用户信息。
    }
    procedure ListView1Click(Sender: TObject);
    procedure ToolButton3Click(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure T1Click(Sender: TObject);
    procedure N11Click(Sender: TObject);
    procedure A1Click(Sender: TObject);
    procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);

    procedure recvmessage(var mess:Tmessage); message 4567;
    procedure Timer2Timer(Sender: TObject);
    procedure F1Click(Sender: TObject);
    procedure CheckBox4Click(Sender: TObject);
    procedure I1Click(Sender: TObject);
    procedure N13Click(Sender: TObject);
    procedure R1Click(Sender: TObject);
    procedure NMUDP1DataReceived(Sender: TComponent; NumberBytes: Integer;
      FromIP: String; Port: Integer);
    procedure N14Click(Sender: TObject);
    procedure FormShow(Sender: TObject);
   
    //procedure recvcomm(var Mess:Tmessage); message Wm_commnotify;
    {
      响应消息4567,编程时通过服务器启动函数将消息4567传送给服务器,当服务器
      收到数据时,就向此窗口发送消息4567,函数recvmessage响应此消息
    }
  private
    { Private declarations }
  public

     hand:HMODULE;         //指向DLL文件的句柄
     sport:integer;        //服务端口
     msg:cardinal;         //窗口响应的消息
     oncolor,offcolor,errorcolor:tcolor;
                           //指示灯颜色
     baudrate:integer;     //串口波特率
     comnum:integer;       //串口号 1、2等等
     parity:integer;       //校验码
     databit:integer;      //数据位
     stopbit:integer;      //停止位
     flowctl:integer;      //流量控制
     comhand:THandle;      //指向打开的串口的句柄
     comonoff:integer;     //指示串口状态 打开或者关闭
     commstate:array[1..5] of integer;  //窗口中串口各项配置的索引,
                                        //如commstate[3]为3,则Combobox3的itemindex为3

     lognamepath:string;     //保存日志的路径
     logmaxcount:integer;    //日志中最多可存的记录数
     currentfile:string;     //当前的日志文件名
     currentnum:integer;     //已经收到数据报的数量

     lightonoff:integer;     //指示灯开关

     timeinterval:integer;   //用户注册时间间隔

     accountname:array[1..100] of string;    //帐号名称

     registerstyle:integer;   //1-随服务器动 2-手工注册
     SerialNo:Integer;
     serverIP:string;
     serverport:integer;
     ExtendSerialNo:String;

     StartType:Integer;
                                             
     procedure showstate(str:string);
     {
        显示指示灯状态,输入为字符串'xxxx',x为'0'~'9'、'A'~'F'中的一个值,
        函数将这个值转换为一个二进制串,如’123F'转换成’0001001000111111',
        然后将这个值显示在窗口中的16个指示灯中
     }

     procedure showstate2;
     {
        只用于显示有数据到达
     }
     function  is_datetime(str:string):boolean;
     {
        判断字符串是否为datetime型,如果是,返回TRUE,否则返回FALSE
     }
     function  inttoip(ip:cardinal):string;
     {
        将32为整数表示的ip地址转换成字符串'xxx.xxx.xxx.xxx'形式
        返回值为该字符串
     }
     function  strtohex(str:string):string;
     {
        将一个16进制字符串转换成字符串,如:
        '3132'转换成'12'的形式
     }
     function  stoi(ch:char):integer;
     {
         将一个字符转换成整数,如'8'转换成8,'A' 转换成10
     }
     function  legalchar(ch:char):boolean;
     {
         判断字符ch是否在'0'~'9'、'A'~'F'中
     }
     function  userintable(str:string):boolean;
     {
         判断用户是否在窗口列表中
     }

     function strtohexstr(str:string;lenstr:integer):string;
     {
         将一个字符串转换成16进制的字符串
         如:'1234' 转换成 '31 32 33 34'
     }
     procedure writelogfile(data:data_record);
     procedure registerserver(cmd:integer);   //1-login 2-logout
     procedure writeinifile(cmd:integer);     //1-read 2-write
     function  getipaddr(dmname:string):string;
     { Public declarations }

  end;

type
  arr=array[1..256] of char;
  arr2=array[1..1024] of char;
  p_integer=^integer;
  p_char=^char;
  p_byte=^byte;
  p_data_record=^data_record;
  p_user_info=^gprs_user_info;


  //下面定义的时函数类型,用于指向动态库中的函数
  start_gprs_server=function(a:HWND;b:cardinal;c:integer;d:p_char):integer;stdcall;
      //启动服务
  do_read_proc=function(a:p_data_record;b:p_char;c:boolean):integer;stdcall;
      //接收数据
  stop_gprs_server=function(a:p_char):integer;stdcall;
      //停止服务
  do_close_all_user=function(a:p_char):integer;stdcall;
      //关闭全部用户
  do_send_user_data=function(a:p_byte;b:p_byte;c:cardinal;d:p_char):integer;stdcall;
      //发送数据
  get_user_at=function(a:cardinal;b:p_user_info):integer;stdcall;
      //获得用户信息
  get_max_user_amount=function:cardinal;stdcall;
      //得到当前最大用户数量
  do_close_one_user=function(a:p_byte;b:p_char):integer;stdcall;
      //关闭某个用户


var
  Form1: TForm1;

  function_get_max_user_amount:get_max_user_amount;
  function_do_close_one_user:do_close_one_user;
  function_get_user_at:get_user_at;
  function_stop_gprs_server:stop_gprs_server;
  function_do_read_proc:do_read_proc;
  function_start_gprs_server:start_gprs_server;
  function_do_close_all_user:do_close_all_user;
  function_do_send_user_data:do_send_user_data;

  
implementation

uses otherset, myDialogs, Ucomset, uabout, Uaccount, Ulog, Uinterval,
  Uregister, UStart;

procedure TForm1.writelogfile(data:data_record);
var 
    F:TextFile;
    str:string;
    i:integer;   

begin
    try
    if form1.currentnum<form1.logmaxcount then
        begin
         assignfile(F,form1.currentfile);
         Append(F);
         //memo1.Lines.Add('append:'+inttostr(GetLastError()));
        end 
    else
    begin
        str:=datetimetostr(now);

        for i:=1 to length(str) do
          if (str[i]>'9') or (str[i]<'0') then str[i]:='_';

        form1.currentnum:=0;

        if form1.lognamepath<>NO_DIRECTORY then
            str:=form1.lognamepath+'\'+str
        else str:=ExtractFilePath(application.ExeName)+str;    
        str:=str+'.log';
        form1.currentfile:=str;
        //memo1.Lines.Add(form1.lognamepath+':'+str);
        assignfile(F,str);
        //memo1.Lines.Add('assingfile:'+inttostr(GetLastError()));
        rewrite(F);
        //memo1.Lines.Add('rewrite:'+inttostr(GetLastError()));
    end;

    except
        memo1.Lines.Add('无法打开日志文件');
        exit;
    end;

    try

    str:='USERID:'+data.m_userid+'    RECV_TIME:'+data.m_recv_date+'    DATA_LENGTH:'+inttostr(data.m_data_len);
    WriteLn(F,str);
//  memo1.Lines.Add('writeln:'+inttostr(GetLastError())); 
    str:='DATA:'+strtohexstr(data.m_data_buf,data.m_data_len);
    Writeln(F,str);

    except
        memo1.Lines.Add('无法写日志:'+form1.currentfile);
        exit;
    end;

    form1.currentnum:=form1.currentnum+1;
    CloseFile(F);
end;


{$R *.dfm}
procedure TForm1.recvmessage(var mess:Tmessage);
var //func:receive_data;
    rvdata:data_record;
    buf:arr2;
    retval:integer;
    writecount:cardinal;
    showstr:string;
    i:integer;
    //wflag:OVERLAPPED;
begin
   //@func:=GetProcAddress(hand,'do_read_proc');
         //获得动态库中的读数据函数的地址
   if (@function_do_read_proc=nil)  then
      begin
         memo1.lines.Add('无法取到 do_read_proc 函数');
         exit;
      end;
   if checkbox2.Checked then
        retval:=function_do_read_proc(@rvdata,@buf[1],true)
   else retval:=function_do_read_proc(@rvdata,@buf[1],false);
        //调用该函数发送数据

   if rvdata.m_data_len<0 then
      begin
         exit;
      end;

   if rvdata.m_data_len=0 then
      begin
         Form1.Timer1Timer(Timer1);
         exit;
      end;

   if memo1.Lines.Count>=100 then
   begin
        memo1.Lines.Clear;
   end;

   if n13.Checked then
   begin
       showstr:='';

       showstr:=Format('用户ID :%s   接收时间:%s  数据长度:%d',[pchar(@rvdata.m_userid[1]),pchar(@rvdata.m_recv_date[1]),rvdata.m_data_len]);
       memo1.Lines.Add(showstr);

       if not checkbox1.Checked then
           memo1.Lines.Add('接收数据:'+rvdata.m_data_buf)
        else
           memo1.Lines.Add('接收数据:'+strtohexstr(rvdata.m_data_buf,rvdata.m_data_len));
   end;
   if (comonoff=1)  then    //判断是否需要将接收到的数据发送的串口
       begin
           WriteFile(comhand,rvdata.m_data_buf,rvdata.m_data_len,writecount,nil);
           //if writecount<1 then memo1.Lines.Add('服务器端:无法向串口写数据');
           //WriteFile(comhand,'test',4,writecount,nil);
       end;

   if checkbox4.Checked then
       begin
           Form1.writelogfile(rvdata);
       end;

   //将收到的数据前四位用指示灯显示,目前没意义
   if N13.Checked then
   if lightonoff>0 then form1.showstate2
   else
      if rvdata.m_data_len>=4 then
          begin
              showstr:='';

⌨️ 快捷键说明

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