unit USocketControl;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Controls,
Dialogs, ExtCtrls, ComCtrls, StdCtrls, Buttons, ScktComp,
DB, ADODB,UServer,UHexUtils;
type
//定义一个再抄表得到数据后触发的事件
TSorcketReadData = procedure(_Region ,_Building,_Termial,_Room,_todo,_AmmeterCoding,_AmmeterAddress,_getData,_Multiple,_Data :string) of Object ;
TSocketGetData = procedure(_AmmeterCoding,_getData :string) of Object ;
TPortServer = Class(TComponent)
private
ServerSocket : TServerSocket ;
CodeList ,DataList : TStringList ;
AdoQuery : TAdoQuery ;
_Date : TDateTime ;
//抄到数据后的事件
FSorcketReadData : TSorcketReadData ;
//抄到数据后触发事件返回客户端
FSocketGetData : TSocketGetData ;
procedure iniServerSocket(_Port : integer) ;
procedure iniAdoQuery ;
procedure iniAdoQueryByNoAndType(_No,_Type : string) ;
procedure iniAmmeter;
public
HaveAmmeter : Boolean ;
_sucessCount : integer ;
Port : integer ;
info : string ;
TerminalList : TStringList ;
AmmeterList : TStringList ;
AmmeterErrorList : TStringList ;
constructor Create(AOwner: TComponent;_Port:integer ;theDate : TDateTime);overload;
constructor Create(AOwner: TComponent;_Port:integer ;theDate : TDateTime;_No ,_Type:string);overload ;
destructor destroy ;override ;
function CheckTerminal : Boolean ;
procedure GetItemData(_Ammeter: TAmmeterObj);
procedure refreshAmmeter;
procedure refreshAmmeterByNoType(_No,_Type : string) ;
procedure SaveDatas ;
procedure CloseSocket ;
procedure ServerSocketClientConnect(Sender: TObject; Socket: TCustomWinSocket);
procedure ServerSocketClientError(Sender: TObject; Socket: TCustomWinSocket; ErrorEvent: TErrorEvent; var ErrorCode: Integer);
procedure ServerSocketClientRead(Sender: TObject; Socket: TCustomWinSocket);
property SorcketReadData : TSorcketReadData read FSorcketReadData write FSorcketReadData ;
property SocketGetData : TSocketGetData read FSocketGetData write FSocketGetData ;
end;
implementation
uses UConst;
{ TPortServer }
function TPortServer.CheckTerminal: Boolean;
begin
if self.TerminalList.Count > 0 then
begin
Result := True ;
end
else
begin
self.info := '没有检测到任何终端';
Result := False ;
end;
end;
procedure TPortServer.CloseSocket;
var
i : integer ;
begin
for i := 0 to self.ServerSocket.Socket.ActiveConnections -1 do
begin
self.ServerSocket.Socket.Connections.Close ;
end;
self.ServerSocket.Close ;
end;
constructor TPortServer.Create(AOwner: TComponent;_Port: integer;theDate : TDateTime);
begin
inherited Create(AOwner);
_Date := theDate ;
Port := _Port ;
ServerSocket := TServerSocket.Create(self) ;
ServerSocket.OnClientConnect := self.ServerSocketClientConnect ;
ServerSocket.OnClientError := self.ServerSocketClientError ;
ServerSocket.OnClientRead := self.ServerSocketClientRead ;
TerminalList := TStringList.Create ;
AmmeterList := TStringList.Create ;
AmmeterErrorList := TStringList.Create ;
CodeList := TStringList.Create ;
DataList := TStringList.Create ;
AdoQuery := TAdoQuery.Create(self) ;
self.iniServerSocket(_Port) ;
self.iniAdoQuery ;
self.iniAmmeter ;
end;
constructor TPortServer.Create(AOwner: TComponent; _Port: integer;
theDate: TDateTime; _No, _Type: string);
begin
inherited Create(AOwner);
_Date := theDate ;
Port := _Port ;
ServerSocket := TServerSocket.Create(self) ;
ServerSocket.OnClientConnect := self.ServerSocketClientConnect ;
ServerSocket.OnClientError := self.ServerSocketClientError ;
ServerSocket.OnClientRead := self.ServerSocketClientRead ;
TerminalList := TStringList.Create ;
AmmeterList := TStringList.Create ;
AmmeterErrorList := TStringList.Create ;
CodeList := TStringList.Create ;
DataList := TStringList.Create ;
AdoQuery := TAdoQuery.Create(self) ;
self.iniServerSocket(_Port) ;
self.iniAdoQueryByNoAndType(_No,_Type) ;
self.iniAmmeter ;
end;
destructor TPortServer.destroy;
begin
self.ServerSocket.Active := False ;
self.ServerSocket.Free ;
self.TerminalList.Free ;
self.AmmeterList.Free ;
self.AmmeterErrorList.Free ;
self.DataList.Free ;
self.CodeList.Free ;
self.AdoQuery.Free ;
inherited;
end;
procedure TPortServer.GetItemData(_Ammeter: TAmmeterObj);
var
i : integer ;
begin
if self.TerminalList.Count > 0 then
begin
Info := '正采集终端'''+_Ammeter.RemoteAddress +'''下电表'''+_Ammeter.AmmeterAddress +'''';
if self.TerminalList.IndexOf(_Ammeter.RemoteAddress)<> -1 then
begin
for i := 0 to self.ServerSocket.Socket.ActiveConnections -1 do
begin
if self.ServerSocket.Socket.Connections.RemoteAddress = _Ammeter.RemoteAddress then
begin
self.ServerSocket.Socket.Connections.SendText(getAmeterCmdByCode(_Ammeter.AmmeterAddress)) ;
//_sleep(800);
//self.ServerSocket.Socket.Connections.SendText(getAmeterCmdByCode(_Ammeter.AmmeterAddress)) ;
Break ;
end;
end;
end ;
end
else
begin
Info := '没有检测到任何终端';
end;
end;
procedure TPortServer.iniAdoQuery;
begin
with self.AdoQuery do
begin
Connection := frm_Server.ADOConnection ;
SQL.Clear ;
SQL.Text := 'Select D.* from '+
'(select B.CommunicationAddress as TerminalAddress, '+
'B.CommunicationPort as TerminalPort,'+
'C.MultipleNo,C.isSucess,E.Multiple,'+
'c.AmmeterCoding,C.CommunicationAddress as AmmeterAddress from TerminalAmmeter as A '+
'left join TerminalAssets as B on A.TerminalCoding=B.TerminalCoding '+
'left join AmmeterAssets as C on A.AmmeterCoding=C.AmmeterCoding '+
'left join Multiple as E on C.MultipleNo=E.MultipleNo '+
') as D where D.isSucess = 1 and D.TerminalPort='+inttostr(Port);
Open ;
self.HaveAmmeter := (RecordCount > 0);
end;
end;
procedure TPortServer.iniAdoQueryByNoAndType(_No, _Type: string);
var
i : integer ;
Info,_Str : string ;
tmpList : TStringList ;
begin
with self.AdoQuery do
begin
Connection := frm_Server.ADOConnection ;
SQL.Clear ;
//江南大学
if _Type = _Root then
begin
SQL.Text := 'select * from view_All '+
' where TerminalPort='+inttostr(Port) ;
Info := '江南大学' ;
end
else
//校区
if _Type = _Region then
begin
SQL.Text := 'select * from view_All '+
' where RegionNo='''+_No+''' and TerminalPort='+inttostr(Port) ;
Info := '校区编号:'+_No ;
end
else
//建筑物
if _Type = _Building then
begin
SQL.Text := 'select * from view_All '+
' where BuildingNo='''+_No+''' and TerminalPort='+inttostr(Port) ;
Info := '建筑物编号:'+_No ;
end
else
//终端
if _Type = _Terminal then
begin
SQL.Text := 'select * from view_All '+
' where TerminalCoding='''+_No+''' and TerminalPort='+inttostr(Port) ;
Info := '终端:'+_No ;
end
{
else
//总表
if _Type = _Ammeter_Sum then
begin
SQL.Text := 'select * from view_All '+
' where ParentAmmeter='''+_No+''' and TerminalPort='+inttostr(Port) ;
end
}
else
//房间
if _Type = _Room then
begin
tmpList := TStringList.Create ;
try
tmpList.CommaText := _No ;
SQL.Text := 'select * from view_All '+
' where BuildingNo='''+tmpList.Strings[0]+
''' and Room='''+tmpList.Strings[1]+''' and TerminalPort='+inttostr(Port) ;
Info := '建筑物编号:'+tmpList.Strings[0] +' 房间:'+tmpList.Strings[1] ;
finally
tmpList.Free ;
end;
end
else
//电表
if _Type = _Ammeter then
begin
SQL.Text := 'select * from view_All '+
' where AmmeterCoding='''+_No+''' and TerminalPort='+inttostr(Port) ;
Info := '电表:'+_No ;
end
else
//部门(某些)
if _Type = _Academe then
begin
tmpList := TStringList.Create ;
try
tmpList.CommaText := _No ;
for i := 0 to tmpList.Count -1 do
begin
if i=0 then
_Str := ''''+tmpList.Strings+''''
else
_Str := _Str + ','''+tmpList.Strings+'''';
end;
finally
tmpList.Free ;
end;
SQL.Text := 'select * from view_All where AcademeNo in ('+ _Str +') and TerminalPort='+inttostr(Port);
Info := '部门:'+_Str ;
end
else
//子部门
if _Type = _Branch then
begin
SQL.Text := 'select * from view_All where BranchNo = '''+ _No +''' and TerminalPort='+inttostr(Port);
Info := '子部门:'+_No ;
end
else
//校区2
if _Type = _Region_2 then
begin
tmpList := TStringList.Create ;
try
tmpList.CommaText := _No ;
SQL.Text := 'select * from view_All where BranchNo = '''+ tmpList.Strings[0] +
''' and RegionNo ='''+ tmpList.Strings[1] +''' and TerminalPort='+inttostr(Port);
Info := '子部门:'+ tmpList.Strings[0] +' 校区:'+ tmpList.Strings[1] ;
finally
tmpList.Free ;
end;
end
else
//建筑物2
if _Type = _Building_2 then
begin
tmpList := TStringList.Create ;
try
tmpList.CommaText := _No ;
SQL.Text := 'select * from view_All where BranchNo = '''+ tmpList.Strings[0] +
''' and BuildingNo ='''+ tmpList.Strings[1] +''' and TerminalPort='+inttostr(Port);
Info := '子部门:'+ tmpList.Strings[0] +' 建筑物:'+ tmpList.Strings[1] ;
finally
tmpList.Free ;
end;
end ;
Open ;
self.HaveAmmeter := (RecordCount > 0);
//显示客户端需要抄表的数量
frm_Server.StatusBar1.Panels[0].Text := Info+ ' 抄表数量:'+inttostr(self.AdoQuery.RecordCount );
frm_Server.Update ;
end;
end;
procedure TPortServer.iniAmmeter;
var
i : integer ;
_Ammeter : TAmmeterObj ;
begin
self.AmmeterList.Clear ;
self.AdoQuery.First ;
for i := 0 to self.AdoQuery.RecordCount -1 do
begin
_Ammeter := TAmmeterObj.Create ;
_Ammeter.RemoteAddress := self.AdoQuery.fieldByName('TerminalAddress').AsString ;
_Ammeter.AmmeterAddress := self.AdoQuery.fieldByName('AmmeterAddress').AsString ;
self.AmmeterList.AddObject(_Ammeter.AmmeterAddress ,_Ammeter) ;
self.AdoQuery.Next ;
end;
end;
procedure TPortServer.iniServerSocket(_Port: integer);
begin
try
self.ServerSocket.Active := False ;
self.ServerSocket.Port := _Port ;
//度线程的抄
self.ServerSocket.ThreadCacheSize := 200 ;
//self.ServerSocket.ServerType := stThreadBlocking ;
self.ServerSocket.Active := True ;
self.info := '端口:'+inttostr(_Port)+'已经打开,开始连接终端';
except
showMessage('端口:'+inttostr(_Port)+'已经打开,不能同时打开2次!');
Abort ;
end;
end;
procedure TPortServer.refreshAmmeter;
var
_tmpString :string;
_Ammeter : TAmmeterObj ;
i : integer ;
begin
for i := 0 to self.CodeList.Count -1 do
begin
if i <> self.CodeList.Count -1 then
begin
_tmpString := _tmpString+''''+ self.CodeList.Strings+''','
end
else
begin
_tmpString := _tmpString+''''+ self.CodeList.Strings+''''
end;
end;
with self.AdoQuery do
begin
Connection := frm_Server.ADOConnection ;
SQL.Clear ;
SQL.Text := 'Select D.* from '+
'(select B.CommunicationAddress as TerminalAddress, '+
'B.CommunicationPort as TerminalPort,'+
'C.MultipleNo,E.Multiple,'+
'c.AmmeterCoding,C.CommunicationAddress as AmmeterAddress from TerminalAmmeter as A '+
'left join TerminalAssets as B on A.TerminalCoding=B.TerminalCoding '+
'left join AmmeterAssets as C on A.AmmeterCoding=C.AmmeterCoding '+
'left join Multiple as E on C.MultipleNo=E.MultipleNo '+
') as D where D.TerminalPort='+inttostr(Port);
if _tmpString <> '' then
SQL.Text := SQL.Text +' and D.AmmeterCoding not in('+_tmpString +')' ;
Open ;
first ;
self.AmmeterErrorList.Clear ;
for i := 0 to recordCount -1 do
begin
_Ammeter := TAmmeterObj.Create ;
_Ammeter.RemoteAddress := self.AdoQuery.fieldByName('TerminalAddress').AsString ;
_Ammeter.AmmeterAddress := self.AdoQuery.fieldByName('AmmeterAddress').AsString ;
self.AmmeterErrorList.AddObject(_Ammeter.AmmeterAddress ,_Ammeter) ;
Next ;
end;
end;
end;
procedure TPortServer.refreshAmmeterByNoType(_No,_Type : string) ;
var
i : integer ;
_tmpString :string;
theAmmeter : TAmmeterObj ;
Info,_Str : string ;
tmpList : TStringList ;
begin
//得到正确的电表地址列表
for i := 0 to self.CodeList.Count -1 do
begin
if i <> self.CodeList.Count -1 then
begin
_tmpString := _tmpString+''''+ self.CodeList.Strings+''','
end
else
begin
_tmpString := _tmpString+''''+ self.CodeList.Strings+''''
end;
end;
with self.AdoQuery do
begin
Connection := frm_Server.ADOConnection ;
SQL.Clear ;
//江南大学
if _Type = _Root then
begin
SQL.Text := 'select * from view_All '+
' where TerminalPort='+inttostr(Port) ;
Info := '江南大学' ;
end
else
//校区
if _Type = _Region then
begin
SQL.Text := 'select * from view_All '+
' where RegionNo='''+_No+''' and TerminalPort='+inttostr(Port) ;
Info := '校区编号:'+_No ;
end
else
//建筑物
if _Type = _Building then
begin
SQL.Text := 'select * from view_All '+
' where BuildingNo='''+_No+''' and TerminalPort='+inttostr(Port) ;
Info := '建筑物编号:'+_No ;
end
else
//终端
if _Type = _Terminal then
begin
SQL.Text := 'select * from view_All '+
' where TerminalCoding='''+_No+''' and TerminalPort='+inttostr(Port) ;
Info := '终端:'+_No ;
end
{
else
//总表
if _Type = _Ammeter_Sum then
begin
SQL.Text := 'select * from view_All '+
' where ParentAmmeter='''+_No+''' and TerminalPort='+inttostr(Port) ;
end
}
else
//房间
if _Type = _Room then
begin
tmpList := TStringList.Create ;
try
tmpList.CommaText := _No ;
SQL.Text := 'select * from view_All '+
' where BuildingNo='''+tmpList.Strings[0]+
''' and Room='''+tmpList.Strings[1]+''' and TerminalPort='+inttostr(Port) ;
Info := '建筑物编号:'+tmpList.Strings[0] +' 房间:'+tmpList.Strings[1] ;
finally
tmpList.Free ;
end;
end
else
//电表
if _Type = _Ammeter then
begin
SQL.Text := 'select * from view_All '+
' where AmmeterCoding='''+_No+''' and TerminalPort='+inttostr(Port) ;
Info := '电表:'+_No ;
end
else
//部门(某些)
if _Type = _Academe then
begin
tmpList := TStringList.Create ;
try
tmpList.CommaText := _No ;
for i := 0 to tmpList.Count -1 do
begin
if i=0 then
_Str := ''''+tmpList.Strings+''''
else
_Str := _Str + ','''+tmpList.Strings+'''';
end;
finally
tmpList.Free ;
end;
SQL.Text := 'select * from view_All where AcademeNo in ('+ _Str +') and TerminalPort='+inttostr(Port);
Info := '部门:'+_Str ;
end
else
//子部门
if _Type = _Branch then
begin
SQL.Text := 'select * from view_All where BranchNo = '''+ _No +''' and TerminalPort='+inttostr(Port);
Info := '子部门:'+_No ;
end
else
//校区2
if _Type = _Region_2 then
begin
tmpList := TStringList.Create ;
try
tmpList.CommaText := _No ;
SQL.Text := 'select * from view_All where BranchNo = '''+ tmpList.Strings[0] +
''' and RegionNo ='''+ tmpList.Strings[1] +''' and TerminalPort='+inttostr(Port);
Info := '子部门:'+ tmpList.Strings[0] +' 校区:'+ tmpList.Strings[1] ;
finally
tmpList.Free ;
end;
end
else
//建筑物2
if _Type = _Building_2 then
begin
tmpList := TStringList.Create ;
try
tmpList.CommaText := _No ;
SQL.Text := 'select * from view_All where BranchNo = '''+ tmpList.Strings[0] +
''' and BuildingNo ='''+ tmpList.Strings[1] +''' and TerminalPort='+inttostr(Port);
Info := '子部门:'+ tmpList.Strings[0] +' 建筑物:'+ tmpList.Strings[1] ;
finally
tmpList.Free ;
end;
end ;
if _tmpString <> '' then
SQL.Text := SQL.Text +' and AmmeterCoding not in('+_tmpString +')' ;
Open ;
first ;
self.AmmeterErrorList.Clear ;
for i := 0 to recordCount -1 do
begin
theAmmeter := TAmmeterObj.Create ;
theAmmeter.RemoteAddress := self.AdoQuery.fieldByName('TerminalAddress').AsString ;
theAmmeter.AmmeterAddress := self.AdoQuery.fieldByName('AmmeterAddress').AsString ;
self.AmmeterErrorList.AddObject(theAmmeter.AmmeterAddress ,theAmmeter) ;
Next ;
end;
//显示客户端需要抄表的数量
frm_Server.StatusBar1.Panels[0].Text := Info+ ' 错误表数量:'+inttostr(self.AdoQuery.RecordCount );
frm_Server.Update ;
end;
end;
procedure TPortServer.SaveDatas;
var
i : integer ;
begin
inherited;
with AdoQuery do
begin
Close ;
SQL.Clear ;
SQL.Text := 'Select * from AmmeterDataRecord where 1=2';
Open ;
for i := 0 to self.CodeList.Count - 1 do
begin
Append ;
FieldByName('Operator').AsString := 'Server' ;
FieldByName('ReadingDate').AsDateTime := _Date ;
FieldByName('AmmeterCoding').AsString := self.CodeList.Strings ;
FieldByName('TotalEnergyReading').AsString := self.DataList.Strings ;
Post ;
end;
end;
end;
procedure TPortServer.ServerSocketClientConnect(Sender: TObject;
Socket: TCustomWinSocket);
begin
self.TerminalList.Add( Socket.RemoteAddress ) ;
self.info := '已经连接上'+inttostr(self.TerminalList.Count)+'个终端';
end;
procedure TPortServer.ServerSocketClientError(Sender: TObject;
Socket: TCustomWinSocket; ErrorEvent: TErrorEvent;
var ErrorCode: Integer);
begin
Socket.Close ;
ErrorCode := 0 ;
end;
procedure TPortServer.ServerSocketClientRead(Sender: TObject;
Socket: TCustomWinSocket);
var
AmmeterAddr : string ;
RecStr : string ;
Datas , Multiple : real ;
begin
inherited;
RecStr := Socket.ReceiveText ;
AmmeterAddr := getAmeterCodeByBackByt(RecStr);
Datas := getAmmeterData(RecStr) ;
if Datas <> -1 then
begin
if self.AdoQuery.Locate('AmmeterAddress',AmmeterAddr,[]) then
begin
inc(_sucessCount);
Multiple := self.AdoQuery.fieldByName('Multiple').AsFloat ;
self.CodeList.Add(self.AdoQuery.fieldByName('AmmeterCoding').AsString) ;
self.DataList.Add(FormatFloat('0.00',Datas*Multiple)) ;
if Assigned(FSorcketReadData) then
begin
FSorcketReadData(self.AdoQuery.fieldByName('RegionName').AsString ,
self.AdoQuery.fieldByName('BuildingName').AsString ,
self.AdoQuery.fieldByName('TerminalAddress').AsString ,
self.AdoQuery.fieldByName('Room').AsString ,
self.AdoQuery.fieldByName('todo').AsString ,
self.AdoQuery.fieldByName('AmmeterCoding').AsString ,
self.AdoQuery.fieldByName('AmmeterAddress').AsString ,
FormatFloat('0.00',Datas),
FormatFloat('0.00',Multiple),
FormatFloat('0.00',Datas*Multiple));
end;
if Assigned(FSocketGetData) then
begin
FSocketGetData(self.AdoQuery.fieldByName('AmmeterAddress').AsString,
FormatFloat('0.00',Datas));
end ;
end;
end;
end;
end.