📄 umain.pas
字号:
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 + -