715 lines
21 KiB
ObjectPascal
715 lines
21 KiB
ObjectPascal
unit uTCPDevice;
|
|
|
|
interface
|
|
|
|
uses System.Win.ScktComp,uSafeLog,uErrorInfo,System.SysUtils,FMX.Types,
|
|
System.StrUtils,System.Classes,WinSock,WinSock2,Winapi.Windows;
|
|
|
|
Const
|
|
IOC_IN = $80000000;
|
|
IOC_VENDOR = $18000000;
|
|
IOC_out = $40000000;
|
|
SIO_KEEPALIVE_VALS = IOC_IN or IOC_VENDOR or 4;
|
|
DATA_BUFSIZE = 8192;
|
|
|
|
type
|
|
TTCP_KEEPALIVE = packed record
|
|
onoff: integer;
|
|
keepalivetime: integer;
|
|
keepaliveinterval: integer;
|
|
end;
|
|
|
|
TWorkEvent = procedure(sValue:string) of object;
|
|
T2DWorkEvent = procedure(Sender: TObject;sValue:string) of object;
|
|
|
|
TThreadX<T> = class(TThread)
|
|
private
|
|
FProc: TProc<T>;
|
|
AValue:T;
|
|
protected
|
|
procedure Execute; override;
|
|
public
|
|
constructor Create(const AProc: TProc<T>;ProcPar:T);
|
|
end;
|
|
|
|
TThreadHelper= class helper for TThread
|
|
public
|
|
class function CreateThreadX<T>(const ThreadProc: TProc<T>;proPar:T): TThread; static;
|
|
end;
|
|
|
|
TRfid=class //RFID
|
|
private
|
|
bIsDestory:boolean;
|
|
FOnWork:TWorkEvent;
|
|
FOnShowState:TWorkEvent;
|
|
FTimer: TTimer;
|
|
FPreValue:string; //保存前一个标签值
|
|
FSocket:TClientSocket;
|
|
procedure TimerTimer(Sender: TObject); //判断连接状态,断开的话,自动重连
|
|
procedure SocketRead(Sender: TObject; Socket: TCustomWinSocket); //读缓存数据
|
|
procedure SocketError(Sender: TObject; Socket: TCustomWinSocket; //出错代码处理
|
|
ErrorEvent: TErrorEvent; var ErrorCode: Integer);
|
|
procedure SocketConnect(Sender: TObject; Socket: TCustomWinSocket);
|
|
procedure SocketDisConnect(Sender: TObject; Socket: TCustomWinSocket);
|
|
procedure SocketConnecting(Sender: TObject; Socket: TCustomWinSocket);
|
|
procedure SendBtye(sValue: String);
|
|
|
|
public
|
|
constructor Create(sIp:string;iPort:integer);
|
|
destructor Destroy; override;
|
|
procedure Close();
|
|
procedure Connect();
|
|
property OnWork: TWorkEvent read FOnWork write FOnWork;//业务处理事件
|
|
property OnShowState:TWorkEvent read FOnShowState write FOnShowState;//显示连接断开提示
|
|
procedure SendStr(sValue:String); //
|
|
procedure ReadData;
|
|
end;
|
|
|
|
TNumEnce=class //采集器
|
|
private
|
|
bIsDestory:boolean;
|
|
FOnWork:TWorkEvent;
|
|
FOnShowState:TWorkEvent;
|
|
FTimer: TTimer;
|
|
FPreValue:string; //保存前一个值
|
|
FSocket:TClientSocket;
|
|
FCount:Integer;
|
|
procedure TimerTimer(Sender: TObject); //判断连接状态,断开的话,自动重连
|
|
procedure SocketRead(Sender: TObject; Socket: TCustomWinSocket); //读缓存数据
|
|
procedure SocketError(Sender: TObject; Socket: TCustomWinSocket; //出错代码处理
|
|
ErrorEvent: TErrorEvent; var ErrorCode: Integer);
|
|
procedure SocketConnect(Sender: TObject; Socket: TCustomWinSocket);
|
|
procedure SocketDisConnect(Sender: TObject; Socket: TCustomWinSocket);
|
|
procedure SocketConnecting(Sender: TObject; Socket: TCustomWinSocket);
|
|
public
|
|
|
|
constructor Create(sIp:string;iPort:integer);
|
|
destructor Destroy; override;
|
|
procedure Close();
|
|
procedure Connect();
|
|
property OnWork: TWorkEvent read FOnWork write FOnWork;//业务处理事件
|
|
property OnShowState:TWorkEvent read FOnShowState write FOnShowState;//显示连接断开提示
|
|
property Count: Integer read FCount write FCount;
|
|
Function Check(sValue:string;iPos:Integer):boolean; //判断返回字符串具体位为1还是0,返回真为1
|
|
procedure SendStr(sValue:String);
|
|
procedure SendStr8(sValue:String);
|
|
end;
|
|
|
|
T2DCode=class //2D读头
|
|
private
|
|
bIsDestory:boolean;
|
|
FTimer: TTimer;
|
|
FOnWork:T2DWorkEvent;
|
|
FOnShowState:TWorkEvent;
|
|
FSocket:TClientSocket;
|
|
FNum:Integer; //编号
|
|
procedure SetKeepAlive(Socket: TCustomWinSocket);
|
|
procedure TimerTimer(Sender: TObject); //判断连接状态,断开的话,自动重连
|
|
procedure SocketRead(Sender: TObject; Socket: TCustomWinSocket); //读缓存数据
|
|
procedure SocketError(Sender: TObject; Socket: TCustomWinSocket; //出错代码处理
|
|
ErrorEvent: TErrorEvent; var ErrorCode: Integer);
|
|
procedure SocketConnect(Sender: TObject; Socket: TCustomWinSocket);
|
|
procedure SocketDisConnect(Sender: TObject; Socket: TCustomWinSocket);
|
|
procedure SocketConnecting(Sender: TObject; Socket: TCustomWinSocket);
|
|
public
|
|
property Num:Integer read FNum write FNum;
|
|
constructor Create(sIp:string;iPort:integer);
|
|
destructor Destroy; override;
|
|
procedure Close();
|
|
procedure Connect();
|
|
procedure DisConnect();
|
|
property OnWork: T2DWorkEvent read FOnWork write FOnWork;//业务处理事件
|
|
property OnShowState:TWorkEvent read FOnShowState write FOnShowState;//显示连接断开提示
|
|
procedure Open;
|
|
end;
|
|
|
|
|
|
implementation
|
|
|
|
|
|
|
|
constructor TThreadX<T>.Create(const AProc: TProc<T>;ProcPar:T);
|
|
begin
|
|
inherited Create(True);
|
|
FreeOnTerminate := True;
|
|
FProc := AProc;
|
|
Avalue:=ProcPar;
|
|
end;
|
|
|
|
procedure TThreadX<T>.Execute;
|
|
begin
|
|
inherited;
|
|
FProc(Avalue);
|
|
end;
|
|
|
|
class function TThreadHelper.CreateThreadX<T>(const ThreadProc: TProc<T>; proPar: T): TThread;
|
|
begin
|
|
Result := TThreadX<T>.Create(ThreadProc,proPar);
|
|
end;
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
constructor TRfid.Create(sIp:string;iPort:integer); //参数固定
|
|
begin
|
|
inherited Create;
|
|
bIsDestory:=false;
|
|
WorkLog.Debug('创建RFID读卡器');
|
|
FSocket:=TClientSocket.Create(nil);
|
|
FSocket.OnRead:=SocketRead;
|
|
FSocket.OnError:=SocketError;
|
|
FSocket.OnConnect:=SocketConnect;
|
|
FSocket.OnDisconnect:=SocketDisConnect;
|
|
FSocket.OnConnecting:=SocketConnecting;
|
|
FSocket.Address:=sIp;
|
|
FSocket.Port:=iPort;
|
|
FTimer:=TTimer.Create(nil);
|
|
FTimer.OnTimer:=TimerTimer;
|
|
FTimer.Enabled:=true;
|
|
WorkLog.Debug('连接RFID读卡器:%s,%d',[sIp,iPort]);
|
|
FPreValue:='';
|
|
end;
|
|
|
|
procedure TRfid.Connect();
|
|
var
|
|
tmp:string;
|
|
begin
|
|
tmp:=Format('连接RFID读卡器:%s,%d',[FSocket.Address,FSocket.Port]);
|
|
WorkLog.Debug(tmp);
|
|
if Assigned(FOnShowState) then FOnShowState(tmp);
|
|
FSocket.Active:=true;
|
|
end;
|
|
|
|
procedure TRfid.SocketConnecting(Sender: TObject; Socket: TCustomWinSocket);
|
|
begin
|
|
WorkLog.Debug('RFID读卡器连接中...');
|
|
if Assigned(FOnShowState) then FOnShowState('RFID读卡器连接中...');
|
|
end;
|
|
|
|
procedure TRfid.Close();
|
|
begin
|
|
FTimer.Enabled:=false;
|
|
FSocket.Close;
|
|
end;
|
|
|
|
destructor TRfid.Destroy;
|
|
begin
|
|
bIsDestory:=true;
|
|
FSocket.Close;
|
|
FTimer.Enabled:=false;
|
|
WorkLog.Debug('销毁RFID读卡器');
|
|
FSocket.Free;
|
|
FTimer.Free;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TRfid.SocketDisConnect(Sender: TObject; Socket: TCustomWinSocket);
|
|
begin
|
|
WorkLog.Debug('RFID读卡器连接断开');
|
|
if Assigned(FOnShowState) then FOnShowState('RFID读卡器连接断开');
|
|
end;
|
|
|
|
procedure TRfid.TimerTimer(Sender: TObject);
|
|
begin
|
|
if FTimer.Enabled then
|
|
begin
|
|
FTimer.Enabled:=false;
|
|
FSocket.Close;
|
|
FSocket.Open;
|
|
end;
|
|
end;
|
|
|
|
procedure TRfid.SocketRead(Sender: TObject; Socket: TCustomWinSocket);
|
|
var
|
|
buf:array[0..1024] of byte;
|
|
sHexString:string;
|
|
i:Integer;
|
|
sData:string; //标签数据
|
|
function ByteToString(const Value:PByte;iLen:Integer): String;
|
|
var
|
|
I: integer;
|
|
S : String;
|
|
begin
|
|
S := '';
|
|
for I := 0 to iLen-1 do
|
|
begin
|
|
S := S+Chr(Value[I]);
|
|
end;
|
|
Result := S;
|
|
end;
|
|
begin
|
|
if bIsDestory then Exit;
|
|
|
|
sHexString:='';
|
|
for i:= 0 to Socket.ReceiveBuf(buf,1024) do
|
|
begin
|
|
sHexString:=sHexString+buf[i].ToHexString;
|
|
end;
|
|
WorkLog.Debug('RFID读到数据:%s',[sHexString]);
|
|
|
|
//1B3501FF1F0012BE3800413346564646473246413033300000413346564646473246413033A41B3501FF03000100000100
|
|
//数据包的第7位,代表包数据长度
|
|
if (buf[0]=$1B) and ((buf[1]=$35) or (buf[1]=$39)) then // 1B 39 包头 (buf[1]=$39) and (buf[6]<20) and (buf[6]>8)
|
|
begin
|
|
sData:=ByteToString(@buf[10],buf[6]-3);
|
|
if sData<>FPreValue then //判断重复
|
|
begin
|
|
if sData.Length>8 then//保证数据有效
|
|
FPreValue:=sData;
|
|
|
|
//开启连接数据库线程
|
|
if Assigned(FOnWork) then
|
|
TThread.CreateThreadX<string>(FOnWork,sData).Start;
|
|
WorkLog.Debug('RFID数据:%s',[sData]);
|
|
end
|
|
else
|
|
WorkLog.Debug('RFID数据重复:%s',[sData]);
|
|
end;
|
|
end;
|
|
|
|
procedure TRfid.SocketError(Sender: TObject; Socket: TCustomWinSocket;
|
|
ErrorEvent: TErrorEvent; var ErrorCode: Integer);
|
|
var
|
|
tmpError:string;
|
|
begin
|
|
if (ErrorCode=10060) OR (ErrorCode=10065) then
|
|
begin
|
|
tmpError:=Format('RFID连接出错(%d):%s',[ErrorCode,SysErrorMessage(ErrorCode)]);
|
|
if Assigned(FOnShowState) then FOnShowState('RFID连接失败,重新连接');
|
|
end
|
|
else
|
|
begin
|
|
tmpError:=Format('RFID连接出错(%d):%s',[ErrorCode,SysErrorMessage(ErrorCode)]);
|
|
if Assigned(FOnShowState) then FOnShowState('RFID连接出错:'+SysErrorMessage(ErrorCode));
|
|
end;
|
|
workLog.Error('Rfid.SocketError:'+tmpError);
|
|
ErrorCode:=0;
|
|
FTimer.Enabled:=true;
|
|
end;
|
|
|
|
procedure TRfid.SocketConnect(Sender: TObject; Socket: TCustomWinSocket);
|
|
begin
|
|
WorkLog.Debug('RFID连接成功');
|
|
if Assigned(FOnShowState) then FOnShowState('RFID连接成功');
|
|
end;
|
|
|
|
procedure TRfid.SendStr(sValue:String); //Send 1b 35 00 00 08 00 01 02 06 00 00 00 00 00 05
|
|
VAR
|
|
bBtye:array[0..6] of byte;
|
|
i:integer;
|
|
begin
|
|
if bIsDestory or (Length(sValue)>7) then Exit;
|
|
WorkLog.Debug(Format('下发指令Rfid:%s',[sValue]));
|
|
|
|
for I := 0 to Length(sValue)-1 do
|
|
bBtye[i]:=Ord(sValue[i+1]);
|
|
// bBtye[0]:=Ord(sValue[1]);bBtye[1]:=Ord(sValue[1]);bBtye[2]:=$31;
|
|
// bBtye[3]:=$31;bBtye[4]:=$31;bBtye[5]:=$30;
|
|
// bBtye[6]:=$30;
|
|
FSocket.Socket.SendText(sValue);
|
|
// FSocket.Socket.SendBuf(bBtye[0],Length(bBtye));
|
|
// FSocket.Socket.SendText('#011300');
|
|
|
|
end;
|
|
|
|
procedure TRfid.SendBtye(sValue:String); //Send 1b 35 00 00 08 00 01 02 06 00 00 00 00 00 05
|
|
VAR
|
|
bBtye:array of byte;
|
|
i,ilenNo:integer;
|
|
begin
|
|
if bIsDestory then Exit;
|
|
WorkLog.Debug(Format('下发指令Rfid:%s',[sValue]));
|
|
SetLength(bBtye,Length(sValue) div 2);
|
|
ilenNo:= 0;
|
|
for I := 1 to Length(sValue) do
|
|
if i mod 2 =0 then
|
|
begin
|
|
bBtye[ilenNo]:=StrToInt('$'+sValue[i-1]+sValue[i]);
|
|
inc(ilenNo);
|
|
end;
|
|
// bBtye[0]:=Ord(sValue[1]);bBtye[1]:=Ord(sValue[1]);bBtye[2]:=$31;
|
|
// bBtye[3]:=$31;bBtye[4]:=$31;bBtye[5]:=$30;
|
|
// bBtye[6]:=$30;
|
|
// FSocket.Socket.SendText(sValue);
|
|
FSocket.Socket.SendBuf(bBtye[0],Length(bBtye));
|
|
// FSocket.Socket.SendText('#011300');
|
|
|
|
end;
|
|
|
|
procedure TRfid.ReadData();
|
|
begin
|
|
SendBtye('1b 35 00 00 08 00 01 02 06 00 00 00 00 00 05'.Replace(' ',''));
|
|
end;
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
constructor TNumEnce.Create(sIp:string;iPort:integer); //参数固定
|
|
begin
|
|
inherited Create;
|
|
bIsDestory:=false;
|
|
WorkLog.Debug('创建采集器');
|
|
FSocket:=TClientSocket.Create(nil);
|
|
FSocket.OnRead:=SocketRead;
|
|
FSocket.OnError:=SocketError;
|
|
FSocket.OnConnect:=SocketConnect;
|
|
FSocket.OnDisconnect:=SocketDisConnect;
|
|
FSocket.OnConnecting:=SocketConnecting;
|
|
FSocket.Address:=sIp;
|
|
FSocket.Port:=iPort;
|
|
FTimer:=TTimer.Create(nil);
|
|
FTimer.OnTimer:=TimerTimer;
|
|
FTimer.Enabled:=true;
|
|
WorkLog.Debug('连接采集器:%s,%d',[sIp,iPort]);
|
|
FPreValue:='';
|
|
FCount:=0;
|
|
end;
|
|
|
|
procedure TNumEnce.Close();
|
|
begin
|
|
FTimer.Enabled:=false;
|
|
FSocket.Close;
|
|
end;
|
|
|
|
procedure TNumEnce.Connect();
|
|
var
|
|
tmp:string;
|
|
begin
|
|
tmp:=Format('连接采集器:%s,%d',[FSocket.Address,FSocket.Port]);
|
|
WorkLog.Debug(tmp);
|
|
if Assigned(FOnShowState) then FOnShowState(tmp);
|
|
try
|
|
FSocket.Active:=true;
|
|
except
|
|
WorkLog.error('NumEnce.Connect:'+'Connect()');
|
|
end;
|
|
end;
|
|
|
|
procedure TNumEnce.SocketConnecting(Sender: TObject; Socket: TCustomWinSocket);
|
|
begin
|
|
WorkLog.Debug('采集器连接中...');
|
|
if Assigned(FOnShowState) then FOnShowState('采集器连接中...');
|
|
end;
|
|
|
|
destructor TNumEnce.Destroy;
|
|
begin
|
|
bIsDestory:=true;
|
|
FSocket.Close;
|
|
FTimer.Enabled:=false;
|
|
WorkLog.Debug('销毁采集器');
|
|
FSocket.Free;
|
|
FTimer.Free;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TNumEnce.SocketDisConnect(Sender: TObject; Socket: TCustomWinSocket);
|
|
begin
|
|
WorkLog.Debug('采集器连接断开');
|
|
if Assigned(FOnShowState) then FOnShowState('采集器连接断开');
|
|
end;
|
|
|
|
procedure TNumEnce.TimerTimer(Sender: TObject);
|
|
begin
|
|
if FTimer.Enabled then
|
|
begin
|
|
FTimer.Enabled:=false;
|
|
FSocket.Close;
|
|
FSocket.Open;
|
|
end;
|
|
end;
|
|
|
|
procedure TNumEnce.SocketRead(Sender: TObject; Socket: TCustomWinSocket);
|
|
var
|
|
buf:array[0..1024] of byte;
|
|
sHexString:string;
|
|
i:Integer;
|
|
sData:string;
|
|
function ByteToString(const Value:PByte;iLen:Integer): String;
|
|
var
|
|
I: integer;
|
|
S : String;
|
|
begin
|
|
S := '';
|
|
for I := 0 to iLen-1 do
|
|
begin
|
|
if Value[i]=$0D then break;
|
|
S := S+Chr(Value[I]);
|
|
end;
|
|
Result := S;
|
|
end;
|
|
begin
|
|
if bIsDestory then Exit;
|
|
|
|
sHexString:='';
|
|
for i:= 0 to Socket.ReceiveBuf(buf,1024) do
|
|
begin
|
|
sHexString:=sHexString+buf[i].ToHexString;
|
|
end;
|
|
|
|
|
|
if (buf[0]=$3E) then // 3E 包头
|
|
begin
|
|
sData:=ByteToString(@buf[0],Length(sHexString) div 2-2); //18位
|
|
if sData<>FPreValue then //判断重复
|
|
begin
|
|
FPreValue:= sData;
|
|
WorkLog.Debug('采集器读到数据:%s',[sHexString]);
|
|
if Assigned(FOnWork) then FOnWork(sData);
|
|
//WorkLog.Debug('采集器数据:%s,计数:%d',[sData,FCount]);
|
|
end;
|
|
//else
|
|
// WorkLog.Debug('RFID采集卡数据重复:%s',[sData]);
|
|
end;
|
|
end;
|
|
|
|
procedure TNumEnce.SocketError(Sender: TObject; Socket: TCustomWinSocket;
|
|
ErrorEvent: TErrorEvent; var ErrorCode: Integer);
|
|
var
|
|
tmpError:string;
|
|
begin
|
|
if (ErrorCode=10060) OR (ErrorCode=10065) then
|
|
begin
|
|
tmpError:=Format('采集器连接出错(%d):%s',[ErrorCode,SysErrorMessage(ErrorCode)]);
|
|
if Assigned(FOnShowState) then FOnShowState('采集器连接失败,重新连接');
|
|
end
|
|
else
|
|
begin
|
|
tmpError:=Format('采集器连接出错(%d):%s',[ErrorCode,SysErrorMessage(ErrorCode)]);
|
|
if Assigned(FOnShowState) then FOnShowState('采集器连接出错:'+SysErrorMessage(ErrorCode));
|
|
end;
|
|
workLog.Error('SocketError'+tmpError);
|
|
ErrorCode:=0;
|
|
FTimer.Enabled:=true;
|
|
end;
|
|
|
|
procedure TNumEnce.SocketConnect(Sender: TObject; Socket: TCustomWinSocket);
|
|
begin
|
|
WorkLog.Debug('采集器连接成功');
|
|
if Assigned(FOnShowState) then FOnShowState('采集器连接成功');
|
|
end;
|
|
|
|
Function TNumEnce.Check(sValue:string;iPos:Integer):boolean;
|
|
BEGIN
|
|
if length(sValue)=18 then //判断返回位数为18位
|
|
Result:=MidStr(sValue,(19-iPos),1)='1'
|
|
else
|
|
WorkLog.Error('采集器返回的数据异常');
|
|
END;
|
|
|
|
procedure TNumEnce.SendStr8(sValue:String); //Send #011300
|
|
VAR
|
|
bBtye:array[0..7] of byte;
|
|
i:integer;
|
|
begin
|
|
if bIsDestory or (Length(sValue)<8) then
|
|
begin
|
|
WorkLog.Error(Format('下发指令采集器错误:%s,%s,%s',[bIsDestory.ToString,Length(sValue).ToString,sValue]));
|
|
Exit;
|
|
end;
|
|
for I := 0 to Length(sValue)-1 do
|
|
bBtye[i]:=Ord(sValue[i+1]);
|
|
// bBtye[0]:=Ord(sValue[1]);bBtye[1]:=Ord(sValue[1]);bBtye[2]:=$31;
|
|
// bBtye[3]:=$31;bBtye[4]:=$31;bBtye[5]:=$30;
|
|
// bBtye[6]:=$30;
|
|
FSocket.Socket.SendText(sValue);
|
|
// FSocket.Socket.SendBuf(bBtye[0],Length(bBtye));
|
|
// FSocket.Socket.SendText('#011300');
|
|
WorkLog.Debug(Format('下发指令采集器:%s',[sValue]));
|
|
end;
|
|
|
|
procedure TNumEnce.SendStr(sValue:String); //Send #011300
|
|
VAR
|
|
bBtye:array[0..6] of byte;
|
|
i:integer;
|
|
begin
|
|
if bIsDestory or (Length(sValue)<7) then
|
|
begin
|
|
WorkLog.Error(Format('下发指令采集器错误:%s,%s,%s',[bIsDestory.ToString,Length(sValue).ToString,sValue]));
|
|
Exit;
|
|
end;
|
|
for I := 0 to Length(sValue)-1 do
|
|
bBtye[i]:=Ord(sValue[i+1]);
|
|
// bBtye[0]:=Ord(sValue[1]);bBtye[1]:=Ord(sValue[1]);bBtye[2]:=$31;
|
|
// bBtye[3]:=$31;bBtye[4]:=$31;bBtye[5]:=$30;
|
|
// bBtye[6]:=$30;
|
|
FSocket.Socket.SendText(sValue);
|
|
// FSocket.Socket.SendBuf(bBtye[0],Length(bBtye));
|
|
// FSocket.Socket.SendText('#011300');
|
|
WorkLog.Debug(Format('下发指令采集器:%s',[sValue]));
|
|
end;
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
constructor T2DCode.Create(sIp:string;iPort:integer); //参数固定
|
|
begin
|
|
inherited Create;
|
|
bIsDestory:=false;
|
|
FNum:=1;
|
|
WorkLog.Debug('创建2D读头'+sIp+','+IntToStr(iPort));
|
|
FSocket:=TClientSocket.Create(nil);
|
|
FSocket.OnRead:=SocketRead;
|
|
FSocket.OnError:=SocketError;
|
|
FSocket.OnConnect:=SocketConnect;
|
|
FSocket.OnDisconnect:=SocketDisConnect;
|
|
FSocket.OnConnecting:=SocketConnecting;
|
|
FSocket.Address:=sIp;
|
|
FSocket.Port:=iPort;
|
|
FTimer:=TTimer.Create(nil);
|
|
FTimer.OnTimer:=TimerTimer;
|
|
FTimer.Enabled:=false;
|
|
end;
|
|
|
|
procedure T2DCode.Connect();
|
|
var
|
|
tmp:string;
|
|
begin
|
|
tmp:=Format('连接2D读头%d:%s,%d',[FNum,FSocket.Address,FSocket.Port]);
|
|
WorkLog.Debug(tmp);
|
|
if Assigned(FOnShowState) then FOnShowState(tmp);
|
|
FSocket.Active:=true;
|
|
end;
|
|
|
|
procedure T2DCode.DisConnect();
|
|
begin
|
|
FSocket.Close;
|
|
FTimer.Enabled:=false;
|
|
end;
|
|
|
|
procedure T2DCode.SocketConnecting(Sender: TObject; Socket: TCustomWinSocket);
|
|
begin
|
|
WorkLog.Debug(Format('2D读头%d连接中...',[FNum]));
|
|
if Assigned(FOnShowState) then FOnShowState(Format('2D读头%d连接中...',[FNum]));
|
|
end;
|
|
|
|
destructor T2DCode.Destroy;
|
|
begin
|
|
bIsDestory:=true;
|
|
FSocket.Close;
|
|
FTimer.Enabled:=false;
|
|
WorkLog.Debug('销毁2D读头');
|
|
FSocket.Free;
|
|
FTimer.Free;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure T2DCode.SocketDisConnect(Sender: TObject; Socket: TCustomWinSocket);
|
|
begin
|
|
WorkLog.Debug(Format('2D读头%d连接断开',[FNum]));
|
|
if Assigned(FOnShowState) then FOnShowState(Format('2D读头%d连接断开',[FNum]));
|
|
end;
|
|
|
|
procedure T2DCode.SetKeepAlive(Socket: TCustomWinSocket);
|
|
var
|
|
opt:DWORD;
|
|
klive, outKlive: TTCP_KEEPALIVE;
|
|
i,j:integer;
|
|
// OptVal: DWORD;
|
|
begin
|
|
opt := 1;
|
|
if setsockopt(Socket.SocketHandle,SOL_SOCKET, SO_KEEPALIVE, PAnsiChar(@opt), SizeOf(opt)) = SOCKET_ERROR then
|
|
begin
|
|
//showInfo(Format('WinSock Error %d', [WSAGetLastError()]));
|
|
end;
|
|
klive.onoff := 1;
|
|
klive.keepalivetime := 5000;
|
|
klive.keepaliveinterval := 1;
|
|
|
|
if WSAIoctl(Socket.SocketHandle, SIO_KEEPALIVE_VALS, PAnsiChar(@klive),
|
|
SizeOf(TTCP_KEEPALIVE), PAnsiChar(@outKlive),
|
|
SizeOf(TTCP_KEEPALIVE), opt,0,nil) = SOCKET_ERROR then
|
|
begin
|
|
//showInfo(Format('WinSock Error %d', [WSAGetLastError()]));
|
|
end;
|
|
|
|
end;
|
|
|
|
procedure T2DCode.TimerTimer(Sender: TObject);
|
|
begin
|
|
if FTimer.Enabled then
|
|
begin
|
|
FTimer.Enabled:=false;
|
|
FSocket.Close;
|
|
FSocket.Open;
|
|
end;
|
|
end;
|
|
|
|
procedure T2DCode.SocketRead(Sender: TObject; Socket: TCustomWinSocket);
|
|
var
|
|
buf:array[0..1024] of byte;
|
|
sHexString:string;
|
|
i:Integer;
|
|
sData:string;
|
|
function ByteToString(const Value:PByte;iLen:Integer): String;
|
|
var
|
|
I: integer;
|
|
S : String;
|
|
begin
|
|
S := '';
|
|
for I := 0 to iLen-1 do
|
|
begin
|
|
if Value[i]=$0D then break;
|
|
S := S+Chr(Value[I]);
|
|
end;
|
|
Result := S;
|
|
end;
|
|
begin
|
|
if bIsDestory then Exit;
|
|
|
|
sHexString:='';
|
|
for i:= 0 to Socket.ReceiveBuf(buf,1024) do
|
|
begin
|
|
sHexString:=sHexString+buf[i].ToHexString;
|
|
end;
|
|
WorkLog.Debug('2D读头%d读到数据:%s',[FNum,sHexString]);
|
|
|
|
sData:=ByteToString(@buf[0],Length(sHexString) div 2);
|
|
if Assigned(FOnWork) then FOnWork(self,sData);
|
|
end;
|
|
|
|
procedure T2DCode.SocketError(Sender: TObject; Socket: TCustomWinSocket;
|
|
ErrorEvent: TErrorEvent; var ErrorCode: Integer);
|
|
var
|
|
tmpError:string;
|
|
begin
|
|
if (ErrorCode=10060) OR (ErrorCode=10065) then
|
|
begin
|
|
tmpError:=Format('2D读头%d连接出错(%d):%s',[FNum,ErrorCode,SysErrorMessage(ErrorCode)]);
|
|
if Assigned(FOnShowState) then FOnShowState(Format('2D读头%d连接失败,重新连接',[FNum]));
|
|
end
|
|
else
|
|
begin
|
|
tmpError:=Format('2D读头%d连接出错(%d):%s',[FNum,ErrorCode,SysErrorMessage(ErrorCode)]);
|
|
if Assigned(FOnShowState) then FOnShowState('2D读头连接出错:'+SysErrorMessage(ErrorCode));
|
|
end;
|
|
workLog.Error('2DCode.SocketError:'+tmpError);
|
|
ErrorCode:=0;
|
|
if bIsDestory then Exit;
|
|
FTimer.Enabled:=true;
|
|
end;
|
|
|
|
procedure T2DCode.SocketConnect(Sender: TObject; Socket: TCustomWinSocket);
|
|
begin
|
|
WorkLog.Debug(Format('2D读头%d连接成功',[FNum]));
|
|
if Assigned(FOnShowState) then FOnShowState(Format('2D读头%d连接成功',[FNum]));
|
|
end;
|
|
|
|
procedure T2DCode.Close; //4C4F46460D
|
|
VAR
|
|
bBtye:array[0..4] of byte;
|
|
begin
|
|
if bIsDestory then Exit;
|
|
bBtye[0]:=$4C;bBtye[1]:=$4F;bBtye[2]:=$46;
|
|
bBtye[3]:=$46;bBtye[4]:=$0D;
|
|
fSocket.Socket.SendBuf(bBtye[0],5);
|
|
WorkLog.Debug(Format('2D读头%d关闭',[FNum]));
|
|
end;
|
|
|
|
procedure T2DCode.Open; //4C4F4E0d
|
|
VAR
|
|
bBtye:array[0..4] of byte;
|
|
begin
|
|
if bIsDestory then Exit;
|
|
bBtye[0]:=$4C;bBtye[1]:=$4F;bBtye[2]:=$4E;
|
|
bBtye[3]:=$0D;
|
|
fSocket.Socket.SendBuf(bBtye[0],4);
|
|
WorkLog.Debug(Format('2D读头%d打开',[FNum]));
|
|
end;
|
|
|
|
end.
|