Files
dyp/pas/uTCPDevice.pas
T
2026-05-07 20:25:34 +08:00

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.