SmartFactory_NEOL/SOURCE/NEOL-LS_PLC_Agent02/U_LSPLCAgent.pas
2026-09-04 14:06:10 +09:00

2429 lines
72 KiB
ObjectPascal
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

unit U_LSPLCAgent;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, System.Win.ScktComp,
Vcl.ExtCtrls, cxGraphics, cxControls, cxLookAndFeels, cxLookAndFeelPainters,
cxStyles, cxCustomData, cxFilter, cxData, cxDataStorage, cxEdit, cxNavigator,
dxDateRanges, dxScrollbarAnnotations, cxGridCustomTableView, cxGridTableView,
cxGridLevel, cxClasses, cxGridCustomView, cxGrid, Data.DB, Datasnap.DBClient,
math, IniFiles, FireDAC.Stan.Intf, FireDAC.Stan.Option, FireDAC.Stan.Error,
FireDAC.UI.Intf, FireDAC.Phys.Intf, FireDAC.Stan.Def, FireDAC.Stan.Pool,
FireDAC.Stan.Async, FireDAC.Phys, FireDAC.Stan.Param, FireDAC.DatS,
FireDAC.DApt.Intf, FireDAC.DApt, FireDAC.Phys.PGDef, FireDAC.VCLUI.Wait,
FireDAC.Comp.UI, FireDAC.Phys.PG, FireDAC.Comp.DataSet, FireDAC.Comp.Client,
System.StrUtils, Vcl.ComCtrls, cxTextEdit,
System.Net.URLClient, System.Net.HttpClientComponent, System.Net.HttpClient,
system.DateUtils, system.Hash, System.NetEncoding,
AlarmLog, RegisterClasses_base, empmst, System.JSON, cxCurrencyEdit,
MachineMst;
type
TSMSOptions = record
// ToNumber: string;
ToNumber: TStrings;
FromNumber: string;
Text: string;
end;
type
TF_LSPLCAgent = class(TForm)
ClientSocket1_old: TClientSocket;
Tmr_PLCRead: TTimer;
TrayIcon1: TTrayIcon;
tmrExit: TTimer;
FDConnection1: TFDConnection;
FDQuery1: TFDQuery;
FDPhysPgDriverLink1: TFDPhysPgDriverLink;
FDGUIxWaitCursor1: TFDGUIxWaitCursor;
Tmr_DBInsert: TTimer;
FDQuery2: TFDQuery;
PageControl1: TPageControl;
TabSheet1: TTabSheet;
ALARM: TTabSheet;
GroupBox4: TGroupBox;
Label23: TLabel;
Label24: TLabel;
Label25: TLabel;
Label26: TLabel;
Label30: TLabel;
Edit25: TEdit;
Edit26: TEdit;
Edit27: TEdit;
Edit28: TEdit;
Edit32: TEdit;
GroupBox6: TGroupBox;
Label31: TLabel;
Label32: TLabel;
Label33: TLabel;
Edit30: TEdit;
Button9: TButton;
Memo3: TMemo;
Edit31: TEdit;
Memo4: TMemo;
Memo5: TMemo;
Edit33: TEdit;
RadioButton3: TRadioButton;
RadioButton4: TRadioButton;
RadioGroup1: TRadioGroup;
GroupBox5: TGroupBox;
cxGrid3: TcxGrid;
cxGridTableView3: TcxGridTableView;
cxGridTableView3Column1: TcxGridColumn;
cxGridTableView3Column2: TcxGridColumn;
cxGridTableView3Column3: TcxGridColumn;
cxGridTableView3Column4: TcxGridColumn;
cxGridLevel3: TcxGridLevel;
TabSheet2: TTabSheet;
ListBox1: TListBox;
ListBox2: TListBox;
ListBox3: TListBox;
Panel2: TPanel;
Label17: TLabel;
Label16: TLabel;
Label3: TLabel;
ComboBox5: TComboBox;
Button13: TButton;
Edit10: TEdit;
GridAddressList: TcxGrid;
GridAddressListTV: TcxGridTableView;
GridAddressListTVColumn1: TcxGridColumn;
GridAddressListTVColumn2: TcxGridColumn;
GridAddressListTVColumn3: TcxGridColumn;
GridAddressListTVColumn4: TcxGridColumn;
GridAddressListTVColumn5: TcxGridColumn;
GridAddressListTVColumn6: TcxGridColumn;
GridAddressListLv: TcxGridLevel;
GroupBox1: TGroupBox;
Label14: TLabel;
Label15: TLabel;
Label1: TLabel;
Label2: TLabel;
Edit5: TEdit;
Edit6: TEdit;
Button11: TButton;
Button1: TButton;
Edit1: TEdit;
Button2: TButton;
Button3: TButton;
Button4: TButton;
Button5: TButton;
Edit2: TEdit;
Button6: TButton;
Button7: TButton;
CheckBox1: TCheckBox;
RadioButton1: TRadioButton;
RadioButton2: TRadioButton;
Panel1: TPanel;
Splitter2: TSplitter;
Memo1: TMemo;
Memo2: TMemo;
Splitter1: TSplitter;
GridAddressListTVColumn7: TcxGridColumn;
GroupBox2: TGroupBox;
Label4: TLabel;
Edit3: TEdit;
Button8: TButton;
Button10: TButton;
cb_logview: TCheckBox;
Timer_runningCK: TTimer;
lb_status: TLabel;
procedure Button11Click(Sender: TObject);
procedure ClientSocket1_oldConnecting(Sender: TObject;
Socket: TCustomWinSocket);
procedure ClientSocket1_oldDisconnect(Sender: TObject;
Socket: TCustomWinSocket);
procedure ClientSocket1_oldError(Sender: TObject; Socket: TCustomWinSocket;
ErrorEvent: TErrorEvent; var ErrorCode: Integer);
procedure ClientSocket1_oldRead(Sender: TObject; Socket: TCustomWinSocket);
procedure Button13Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure ClientSocket1_oldConnect(Sender: TObject; Socket: TCustomWinSocket);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
procedure Button4Click(Sender: TObject);
procedure Button5Click(Sender: TObject);
procedure Button6Click(Sender: TObject);
procedure Button7Click(Sender: TObject);
procedure Tmr_PLCReadTimer(Sender: TObject);
procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
procedure TrayIcon1Click(Sender: TObject);
procedure tmrExitTimer(Sender: TObject);
procedure CheckBox1Click(Sender: TObject);
procedure Tmr_DBInsertTimer(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure Button9Click(Sender: TObject);
procedure RadioButton4Click(Sender: TObject);
procedure Button8Click(Sender: TObject);
procedure Button10Click(Sender: TObject);
procedure Timer_runningCKTimer(Sender: TObject);
private
{ Private declarations }
FsmsObj: TSMSOptions;
inifilename : string;
ExitOk : boolean;
close_ck : Boolean;
TxBuf,
RxBuf : array [0..1024-1] of byte;
ClientSocket1: TClientSocket;
procedure BuildReadPacket(type_ck,str:string);
procedure BuildReadPacketMulti(const AddrList: TStrings);
function PLCDataLoad: boolean;
function PLCDataLoadMulti: boolean;
procedure AppEvtMinimize(Sender: TObject);
procedure ParseMultiReadResponse(var RxBuf: array of Byte;
AddrCount: Integer; out Values: TArray<Word>);
procedure insertSQL(status,sql: string);
function DB_MainTableCreate: Boolean;
function DB_MainTableDescriptCreate: Boolean;
function DB_LogTableCreate: Boolean;
procedure Memo1_ADD(msg: string; ck:Integer = 0);
procedure Memo2_ADD(msg: string);
procedure PLC_connect;
function PingHost(const AHost: string): Boolean;
procedure SafeReconnect;
procedure OnConnect(Sender: TObject; Socket: TCustomWinSocket);
procedure OnConnecting(Sender: TObject; Socket: TCustomWinSocket);
procedure OnDisconnect(Sender: TObject; Socket: TCustomWinSocket);
procedure OnRead(Sender: TObject; Socket: TCustomWinSocket);
procedure OnError(Sender: TObject; Socket: TCustomWinSocket; ErrorEvent: TErrorEvent; var ErrorCode: Integer);
procedure ClientSocket_Close;
function My_ExecuteAndWait(const CmdLine: string;
var ExitCode: DWord): Boolean;
procedure log_save(cx, msg: string);
function AlarmSend(devName, alarm_detail, alarm_status : string):Boolean;
procedure EmgAlarmlistrefresh;
function xGenerateHMACSHA256(const Key, Data: string): string;
function xSendSMS(const Options: TSMSOptions; const ServiceId, AccessKey,
SecretKey: string): string;
function qCreateGetUniqueString(clsName: string): string;
procedure PLC_statusUpdate(Plc_status: string);
function Alarm_use_CK: Boolean;
public
{ Public declarations }
dbIP_PG, dbUser_PG, dbPW_PG, dbSchema_PG : string;
dbPort_PG : integer;
function DB_Connect:Boolean;
function DB_Close:Boolean;
procedure DB_Insert;
end;
var
F_LSPLCAgent: TF_LSPLCAgent;
LoadCK : Boolean;
PLCconnectCK : Integer;
Alarm_re : integer;
Alarm_use : Boolean;
lastDBInsert : TDateTime;
const
PLC_NO = 2; // <20>Ұ<EFBFBD><D2B0><EFBFBD> 2ȣ
implementation
uses WinSock;
const
METHOD = 'POST';
CONTENT_TYPE = 'application/json; charset=utf-8';
COUNTRY_CODE = '82';
{$R *.dfm}
function TF_LSPLCAgent.Alarm_use_CK:Boolean;
var
sql : string;
begin
Result := false;
try
if not FDConnection1.Connected then FDConnection1.Connected := True;
if FDConnection1.Connected then
begin
sql := 'SELECT * FROM "MachineMst"';
sql := sql + ' WHERE "Name"=''ALARM'' ';
sql := sql + ' AND "IsValid"=''t'' ';
sql := sql + ' AND "LcStatus"=''ON'' ; ';
FDQuery1.Close;
FDQuery1.SQL.Clear;
FDQuery1.SQL.Text := sql;
FDQuery1.Open;
if FDQuery1.RecordCount> 0 then
begin
result := True;
end;
end;
except
on e : exception do
begin
Memo1_ADD('Database Select Error :: '+e.Message);
end;
end;
end;
procedure TF_LSPLCAgent.SafeReconnect;
begin
try
// ClientSocket1.Active := False;
ClientSocket_Close;
ClientSocket1 := TClientSocket.Create(nil);
ClientSocket1.ClientType := ctNonBlocking;
ClientSocket1.Host := Edit5.Text;
ClientSocket1.Port := StrToIntDef(Edit6.Text, 2004);
ClientSocket1.OnConnect := OnConnect;
ClientSocket1.OnConnecting := OnConnecting;
ClientSocket1.OnDisconnect := OnDisconnect;
ClientSocket1.OnError := OnError;
ClientSocket1.OnRead := OnRead;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
ClientSocket1.Active := True;
except
on E: Exception do
Memo1_ADD('SafeReconnect error: ' + E.Message);
end;
end;
procedure TF_LSPLCAgent.Timer_runningCKTimer(Sender: TObject);
begin
if LoadCK and (not Button6.Enabled) then begin
if IncSecond(lastDBInsert,30) < now then begin
Tmr_DBInsert.Enabled := True;
end;
end;
end;
procedure TF_LSPLCAgent.OnConnect(Sender: TObject; Socket: TCustomWinSocket);
begin
Button11.Caption := 'DisConnect';
Memo1_ADD('['+FormatDateTime('yymmdd hhnnss.zzz',now)+'] PLC <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>!');
PLCconnectCK := 2; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
end;
procedure TF_LSPLCAgent.OnConnecting(Sender: TObject; Socket: TCustomWinSocket);
begin
Memo1_ADD('['+FormatDateTime('yymmdd hhnnss.zzz',now)+'] <20><><EFBFBD><EFBFBD> <20>õ<EFBFBD>.');
end;
procedure TF_LSPLCAgent.OnDisconnect(Sender: TObject; Socket: TCustomWinSocket);
begin
Memo1_ADD('['+FormatDateTime('yymmdd hhnnss.zzz',now)+'] <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>!');
Button11.Caption := 'Connect';
PLCconnectCK := 0; // <20>ʱⰪ : 0 - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
LoadCK := False;
end;
procedure TF_LSPLCAgent.OnRead(Sender: TObject; Socket: TCustomWinSocket);
var
Buf: array[0..1023] of Byte;
i, Len: Integer;
RawData: TBytes;
BufCopy: TBytes;
S: string;
Recv: Integer;
begin
try
Len := Socket.ReceiveBuf(Buf, SizeOf(Buf));
if Len > 0 then begin
SetLength(RawData, Len);
Move(Buf, RawData[0], Len);
// 1. Memo1<6F><31> <20><><EFBFBD><EFBFBD> ǥ<><C7A5>
S := '';
for i := 0 to Len - 1 do S := S + IntToHex(RawData[i], 2) + ' ';
Memo2_ADD('>> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> (HEX) : '+ S);
// Memo2_ADD(S);
end;
except
on E: Exception do begin
Memo1_ADD('Read error: ' + E.Message);
LoadCK := False;
end;
end;
end;
procedure TF_LSPLCAgent.OnError(Sender: TObject; Socket: TCustomWinSocket; ErrorEvent: TErrorEvent; var ErrorCode: Integer);
begin
Memo1_ADD('['+FormatDateTime('yymmdd hhnnss.zzz',now)+'] PLC <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>: ' + IntToStr(ErrorCode));
PLCconnectCK := 0; // <20>ʱⰪ : 0 - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
ErrorCode := 0; // <20><><EFBFBD><EFBFBD> <20>߻<EFBFBD> <20><><EFBFBD><EFBFBD>
LoadCK := False;
end;
procedure TF_LSPLCAgent.log_save(cx, msg:string);
var
f : TextFile;
log: TStringList;
i : integer;
logfile, buf : string;
begin
logfile := '';
logfile := ExtractFilePath(Application.ExeName)+'log\'+formatdatetime('yyyymmddhh',now())+'_'+cx+'.log';
if FileExists(logfile) then
begin
log := TStringList.Create;
AssignFile(f, logfile);
reset(f);
while not eof(f) do
begin
ReadLn(f, buf);
log.Add(buf);
end;
log.add(FormatDateTime('hh:nn:ss.zzz :: ',now)+msg);
CloseFile(F);
AssignFile(f, logfile);
rewrite(f);
for i := 0 to log.Count - 1 do
begin
WriteLn(f, log.strings[i]);
end;
CloseFile(F);
log.Free;
end else
begin
log := TStringList.Create;
log.add(FormatDateTime('hh:nn:ss.zzz :: ',now)+msg);
AssignFile(f, logfile);
rewrite(f);
for i := 0 to log.Count - 1 do
begin
WriteLn(f, log.strings[i]);
end;
CloseFile(F);
log.Free;
end;
end;
procedure TF_LSPLCAgent.Memo1_ADD(msg:string; ck:Integer = 0);
begin
// if cb_logview.Checked then begin
while Memo1.Lines.Count > 50 do begin
Memo1.Lines.Delete(0);
end;
Memo1.Lines.Add(msg);
// end;
log_save('SYS',msg);
end;
procedure TF_LSPLCAgent.Memo2_ADD(msg:string);
begin
if cb_logview.Checked then begin
while Memo2.Lines.Count > 50 do begin
Memo2.Lines.Delete(0);
end;
Memo2.Lines.ADD(msg);
end;
log_save('DATA',msg);
end;
procedure TF_LSPLCAgent.BuildReadPacket(type_ck,str:string);
var
i, varcnt, sum: Integer;
addrStr: string;
begin
FillChar(TxBuf, SizeOf(TxBuf), 0);
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
TxBuf[0] := $4C; // L
TxBuf[1] := $53; // S
TxBuf[2] := $49; // I
TxBuf[3] := $53; // S
TxBuf[4] := $2d; // -
TxBuf[5] := $58; // X
TxBuf[6] := $47; // G
TxBuf[7] := $54; // T
TxBuf[8] := $00; // NULL
TxBuf[9] := $00; // NULL
TxBuf[10] := $00; // Ŭ<><C5AC><EFBFBD>̾<EFBFBD>Ʈ -> <20><><EFBFBD><EFBFBD> (0x00)
TxBuf[11] := $00;
TxBuf[12] := $A0; // XGK 0xA0 , XGB(MK) 0xB0 , XGI 0xA4 , XGB(IEC) 0x11 , XGR 0xA8
TxBuf[13] := $33; // Ŭ<><C5AC><EFBFBD>̾<EFBFBD>Ʈ(HMI) -> <20><><EFBFBD><EFBFBD>(PLC) (0x33) / <20><><EFBFBD><EFBFBD>(PLC) -> Ŭ<><C5AC><EFBFBD>̾<EFBFBD>Ʈ(HMI) (0x11)
TxBuf[14] := $00; // <20><><EFBFBD><EFBFBD><EFBFBD>Ӱ<EFBFBD><D3B0><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϱ<EFBFBD> <20><><EFBFBD><EFBFBD> ID
TxBuf[15] := $00;
// TxBuf[16] := 16; // Length (<28><><EFBFBD>ɿ<EFBFBD><C9BF><EFBFBD> 16<31><36><EFBFBD><EFBFBD>Ʈ) - <20><><EFBFBD>ɾ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>Ʈ ũ<><C5A9>
TxBuf[16] := 18; // Length (<28><><EFBFBD>ɿ<EFBFBD><C9BF><EFBFBD> 16<31><36><EFBFBD><EFBFBD>Ʈ) - <20><><EFBFBD>ɾ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>Ʈ ũ<><C5A9>
TxBuf[17] := $00; // <20>̴<EFBFBD><CCB4><EFBFBD><EFBFBD><EFBFBD>ġ
TxBuf[18] := $00; // <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> (0x00)
// CheckSum <20><><EFBFBD><EFBFBD>
sum := 0;
for i := 0 to 18 do begin
sum := sum + TxBuf[i];
if sum > 255 then sum := sum - 256;
end;
TxBuf[19] := sum;
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
TxBuf[20] := $54; // READ
TxBuf[21] := 0; // <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>Ǵ<EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
if (type_ck = 'BIT') then // DataType = WORD : $02 , BIT : $00
TxBuf[22] := $00
else if (type_ck = 'BIT_A') then // DataType = WORD : $02 , BIT : $00
TxBuf[22] := $00
else if type_ck = 'WORD' then
TxBuf[22] := $02
else
TxBuf[22] := $02; // WORD
TxBuf[23] := 0; // $30; DataType (<28>̾<EFBFBD><CCBE><EFBFBD>)
TxBuf[24] := 0; // $30; LinkID (2)
TxBuf[25] := 0; // $30; (<28>̾<EFBFBD><CCBE><EFBFBD>)
TxBuf[26] := $01; // Variable count
TxBuf[27] := 0; // $30; (<28>̾<EFBFBD><CCBE><EFBFBD>)
addrStr := Trim(str);
varcnt := Length(addrStr);
TxBuf[28] := varcnt;
TxBuf[29] := 0;
for i := 1 to varcnt do TxBuf[29 + i] := Ord(addrStr[i]);
end;
procedure TF_LSPLCAgent.BuildReadPacketMulti(const AddrList: TStrings);
var
i, j, sum, pos: Integer;
addrStr: string;
addrLen: Integer;
totalLen: Integer;
begin
FillChar(TxBuf, SizeOf(TxBuf), 0);
// 1. Header ('LSIS-XGT')
TxBuf[0] := $4C; // L
TxBuf[1] := $53; // S
TxBuf[2] := $49; // I
TxBuf[3] := $53; // S
TxBuf[4] := $2d; // -
TxBuf[5] := $58; // X
TxBuf[6] := $47; // G
TxBuf[7] := $54; // T
TxBuf[8] := $00; // NULL
TxBuf[9] := $00; // NULL
// 2. Fixed header data
TxBuf[10] := $00; // Ŭ<><C5AC><EFBFBD>̾<EFBFBD>Ʈ -> <20><><EFBFBD><EFBFBD> (0x00)
TxBuf[11] := $00;
TxBuf[12] := $A0; // XGK 0xA0 , XGB(MK) 0xB0 , XGI 0xA4 , XGB(IEC) 0x11 , XGR 0xA8
TxBuf[13] := $33; // Ŭ<><C5AC><EFBFBD>̾<EFBFBD>Ʈ(HMI) -> <20><><EFBFBD><EFBFBD>(PLC) (0x33) / <20><><EFBFBD><EFBFBD>(PLC) -> Ŭ<><C5AC><EFBFBD>̾<EFBFBD>Ʈ(HMI) (0x11)
TxBuf[14] := $00; // <20><><EFBFBD><EFBFBD><EFBFBD>Ӱ<EFBFBD><D3B0><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϱ<EFBFBD> <20><><EFBFBD><EFBFBD> ID
TxBuf[15] := $00;
// <20>ϴ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ְ<EFBFBD> <20><><EFBFBD>߿<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
TxBuf[16] := $00; // Length (<28><><EFBFBD>ɿ<EFBFBD><C9BF><EFBFBD> 16<31><36><EFBFBD><EFBFBD>Ʈ) - <20><><EFBFBD>ɾ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>Ʈ ũ<><C5A9>
TxBuf[17] := $00; // <20>̴<EFBFBD><CCB4><EFBFBD><EFBFBD><EFBFBD>ġ
TxBuf[18] := $00; // <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> (0x00)
///////////////////////// 3. Checksum <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>߿<EFBFBD> ó<><C3B3><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><> <20><>ġ<EFBFBD><C4A1> [19]
// 4. <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
TxBuf[20] := $54; // READ
TxBuf[21] := 0; // <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>Ǵ<EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
TxBuf[22] := $02; // DataType = WORD <20><><EFBFBD><EFBFBD> / $0E - <20><><EFBFBD><EFBFBD>
TxBuf[23] := 0; // $30; DataType (<28>̾<EFBFBD><CCBE><EFBFBD>)
TxBuf[24] := 0; // $30; LinkID (2)
TxBuf[25] := 0; // $30; (<28>̾<EFBFBD><CCBE><EFBFBD>)
TxBuf[26] := AddrList.Count; // Variable Count
TxBuf[27] := $00; // $30; (<28>̾<EFBFBD><CCBE><EFBFBD>)
pos := 28; // <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><>ġ
for i := 0 to AddrList.Count - 1 do
begin
addrStr := Trim(AddrList[i]); // <20><>: %MW301
addrLen := Length(addrStr);
TxBuf[pos] := addrLen; // <20><><EFBFBD>ڿ<EFBFBD> <20><><EFBFBD><EFBFBD>
TxBuf[pos + 1] := 0; // Reserved
for j := 1 to addrLen do
TxBuf[pos + 1 + j] := Ord(addrStr[j]);
Inc(pos, addrLen + 2); // <20><><EFBFBD><EFBFBD> <20><>ġ <20>̵<EFBFBD>
end;
// 5. <20><>ü Length <20><><EFBFBD><EFBFBD>
totalLen := pos - 20; // <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
TxBuf[16] := totalLen;
TxBuf[17] := 0;
// 6. Checksum <20><><EFBFBD><EFBFBD> (0~18<31><38><EFBFBD><EFBFBD> <20>ջ<EFBFBD>)
sum := 0;
for i := 0 to 18 do
begin
sum := sum + TxBuf[i];
if sum > 255 then sum := sum - 256;
end;
TxBuf[19] := sum;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> TxBuf <20><> ũ<><C5A9><EFBFBD><EFBFBD> pos <20><><EFBFBD><EFBFBD>Ʈ<EFBFBD><C6AE><EFBFBD><EFBFBD> <20><>ȿ<EFBFBD><C8BF>
end;
procedure TF_LSPLCAgent.Button10Click(Sender: TObject);
begin
EmgAlarmlistrefresh;
end;
procedure TF_LSPLCAgent.Button11Click(Sender: TObject);
begin
{
TThread.Synchronize(nil,
procedure
begin
try
LoadCK := False;
if Button11.Caption = 'Connect' then begin
ClientSocket1.Host := Edit5.Text;
ClientSocket1.Port := StrToIntDef(Edit6.Text,2004);
ClientSocket1.Active := True;
LoadCK := True;
end
else begin
ClientSocket1.Active := False;
end;
except
on E: Exception do
begin
Memo1_ADD('PLC Connect Except : ' + E.Message);
end;
end;
end
);
}
{ 20251013
if PLCconnectCK = 0 then begin // <20>ʱⰪ : 0 - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
PLCconnectCK := 1; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
try
LoadCK := False;
if Button11.Caption = 'Connect' then begin
ClientSocket1.Host := Edit5.Text;
ClientSocket1.Port := StrToIntDef(Edit6.Text,2004);
ClientSocket1.Active := True;
LoadCK := True;
end
else begin
ClientSocket1.Active := False;
end;
except
on E: Exception do
begin
Memo1_ADD('Except : ' + E.Message);
PLCconnectCK := 0; // <20>ʱⰪ : 0 - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
end;
end;
end;
if PLCconnectCK = 1 then begin
if Pos('<27><><EFBFBD><EFBFBD> <20>õ<EFBFBD>',Memo1.Lines[Memo1.Lines.Count-1]) > 0 then begin
Memo1.Lines[Memo1.Lines.Count-1] := Memo1.Lines[Memo1.Lines.Count-1]+'.';
end;
end;
}
if Button11.Caption = 'Connect' then begin
PLC_connect;
end
else begin
// ClientSocket1.Active := False;
ClientSocket_Close;
end;
end;
function TF_LSPLCAgent.My_ExecuteAndWait(const CmdLine: string; var ExitCode: DWord): Boolean;
var
StartupInfo: TStartupInfo;
ProcessInfo: TProcessInformation;
CmdLineW: WideString;
begin
Result := False;
FillChar(StartupInfo, SizeOf(StartupInfo), 0);
StartupInfo.cb := SizeOf(StartupInfo);
// <20>ٽ<EFBFBD> <20><><EFBFBD><EFBFBD>: â<><C3A2> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ʰ<EFBFBD> <20><><EFBFBD><EFBFBD>
StartupInfo.dwFlags := STARTF_USESHOWWINDOW;
StartupInfo.wShowWindow := SW_HIDE; // â <20><><EFBFBD><EFBFBD> <20>ɼ<EFBFBD>
CmdLineW := CmdLine;
if CreateProcess(nil, PChar(CmdLineW), nil, nil, False, 0, nil, nil, StartupInfo, ProcessInfo) then
begin
// ... (<28><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD> <20>ڵ<EFBFBD> Ȯ<><C8AE> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>)
WaitForSingleObject(ProcessInfo.hProcess, 500); // <20><>: 500ms <20><><EFBFBD><EFBFBD>
if GetExitCodeProcess(ProcessInfo.hProcess, ExitCode) then
Result := True;
CloseHandle(ProcessInfo.hProcess);
CloseHandle(ProcessInfo.hThread);
end;
end;
function TF_LSPLCAgent.PingHost(const AHost: string): Boolean;
var
Code: DWord;
begin
// edit2.Text := booltostr(WinExec(PAnsiChar(AnsiString('ping -n 1 -w 500 ' + AHost)), SW_HIDE) = 0);
if My_ExecuteAndWait('ping -n 1 -w 500 ' + AHost, Code) then
begin
// ping <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>ڵ尡 0<≯<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Դϴ<D4B4>.
Result := Code = 0;
end
else
begin
Result:= false;
Memo1_ADD('Ping Test - Execution Failed'+FormatDateTime('yyyymmdd hhnnss.zzz',Now));
end;
end;
procedure TF_LSPLCAgent.PLC_connect;
begin
try
if PLCconnectCK = 0 then begin // <20>ʱⰪ : 0 - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
try
LoadCK := False;
if Button11.Caption = 'Connect' then begin
if PingHost(Edit5.Text) then begin
{
ClientSocket1.Host := Edit5.Text;
ClientSocket1.Port := StrToIntDef(Edit6.Text,2004);
ClientSocket1.Active := True;
LoadCK := True;
}
// ClientSocket1.Active := False;
ClientSocket_Close;
ClientSocket1 := TClientSocket.Create(nil);
ClientSocket1.ClientType := ctNonBlocking;
ClientSocket1.Host := Edit5.Text;
ClientSocket1.Port := StrToIntDef(Edit6.Text, 2004);
ClientSocket1.OnConnect := OnConnect;
ClientSocket1.OnConnecting := OnConnecting;
ClientSocket1.OnDisconnect := OnDisconnect;
ClientSocket1.OnError := OnError;
ClientSocket1.OnRead := OnRead;
PLCconnectCK := 1; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
ClientSocket1.Active := True;
LoadCK := True;
end
else begin
if Pos('ping_PLC NOT Connect',Memo1.Lines[Memo1.Lines.Count-1]) > 0 then begin
Memo1.Lines[Memo1.Lines.Count-1] := 'ping_PLC NOT Connect'+' - '+FormatDateTime('yyyymmdd hhnnss.zzz',Now);
log_save('SYS','ping_PLC NOT Connect'+' - '+FormatDateTime('yyyymmdd hhnnss.zzz',Now));
end
else begin
Memo1_ADD('ping_PLC NOT Connect'+' - '+FormatDateTime('yyyymmdd hhnnss.zzz',Now));
end;
if lb_status.Caption <> '<27><><EFBFBD><EFBFBD>' then begin
PLC_statusUpdate('<27><><EFBFBD><EFBFBD>');
end;
// ClientSocket1.Active := False;
ClientSocket_Close
end;
end
else begin
// ClientSocket1.Active := False;
ClientSocket_Close;
end;
except
on E: Exception do
begin
Memo1_ADD('Except : ' + E.Message);
PLCconnectCK := 0; // <20>ʱⰪ : 0 - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
end;
end;
end;
if PLCconnectCK = 1 then begin
if Pos('<27><><EFBFBD><EFBFBD> <20>õ<EFBFBD>',Memo1.Lines[Memo1.Lines.Count-1]) > 0 then begin
Memo1.Lines[Memo1.Lines.Count-1] := Memo1.Lines[Memo1.Lines.Count-1]+'.';
end;
end;
except
on E: Exception do begin
Memo1_ADD('PLC_connect Error : ' + E.Message);
end;
end;
end;
procedure TF_LSPLCAgent.ClientSocket_Close;
begin
if Assigned(ClientSocket1) then begin
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
try
if ClientSocket1.Active then
ClientSocket1.Active := False;
// <20><><EFBFBD><EFBFBD> <20>ڵ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
ClientSocket1.Close;
Sleep(100); // OS <20>ڵ<EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> (<28>ʿ<EFBFBD><CABF><EFBFBD> 100~300ms)
// <20><><EFBFBD>õ<EFBFBD> <20><> <20><>ü <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> (<28>ڵ<EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>)
FreeAndNil(ClientSocket1);
except
on E: Exception do
Memo1_ADD('Socket close error: ' + E.Message);
end;
end;
end;
procedure TF_LSPLCAgent.Button13Click(Sender: TObject);
var
Sent, Recv: Integer;
begin
{ // <20><><EFBFBD><EFBFBD> <20>ּҰ<D6BC> <20>б<EFBFBD>
if not ClientSocket1.Active then PLC_connect;
if ClientSocket1.Active then begin
try
BuildReadPacket(ComboBox5.Text+Edit10.Text);
Sent := ClientSocket1.Socket.SendBuf(TxBuf, 36);
if Sent <> 36 then begin
Memo1_ADD('<27><>Ŷ <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> : [ '+ComboBox5.Text+Edit10.Text+' ]');
Exit;
end;
Recv := ClientSocket1.Socket.ReceiveBuf(RxBuf, 34);
if Recv < 34 then begin
Memo1_ADD('<27><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> : [ '+ComboBox5.Text+Edit10.Text+' ]');
Exit;
end;
if cb_logview.Checked then begin
// 1. Memo1: <20><><EFBFBD><EFBFBD> HEX
var hexStr := '';
for var i := 0 to Recv - 1 do hexStr := hexStr + IntToHex(RxBuf[i], 2) + ' ';
Memo2_ADD(hexStr);
// 2. Memo2: <20>ؼ<EFBFBD><D8BC><EFBFBD> <20><><EFBFBD><EFBFBD>
var value := RxBuf[32] + (RxBuf[33] shl 8);
Memo2_ADD('DEC: ' + IntToStr(value));
// StringGrid1.Cells[1,1] := Trim(Edit2.Text) + '=' + IntToStr(value);
Memo2_ADD('HEX: ' + IntToHex(value, 4));
end;
except
on E: ESocketError do
begin
Memo1_ADD('Ŭ<><C5AC><EFBFBD>̾<EFBFBD>Ʈ <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>: ' + E.Message);
// <20><><EFBFBD><EFBFBD> <20>߻<EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
ClientSocket1.Active := False;
end;
on E: Exception do
begin
Memo1_ADD('<27><><EFBFBD><EFBFBD>ġ <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>: ' + E.Message);
ClientSocket1.Active := False;
end;
end;
end;
}
end;
function TF_LSPLCAgent.PLCDataLoad:boolean;
var
i : integer;
Sent, Recv: Integer;
LastError: Integer;
ErrorMsg: string;
Recv_count_ck : integer;
alarmreadck : Boolean;
// ===== [<5B>߰<EFBFBD>] <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> =====
JunkBuf: array[0..1023] of Byte;
ClearLen: Integer;
// ===== [<5B>߰<EFBFBD>] <20><><EFBFBD><EFBFBD> <20><><EFBFBD>۸<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϰ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>Լ<EFBFBD> =====
procedure FlushSocketBuffer;
begin
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD>ۿ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ͱ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>о<20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
while ClientSocket1.Socket.ReceiveLength > 0 do
begin
ClearLen := ClientSocket1.Socket.ReceiveLength;
if ClearLen > SizeOf(JunkBuf) then ClearLen := SizeOf(JunkBuf);
ClientSocket1.Socket.ReceiveBuf(JunkBuf, ClearLen);
Sleep(10); // <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>پ<EFBFBD><D9BE><EFBFBD><EFBFBD><EFBFBD> <20>ܿ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ͱ<EFBFBD><CDB1><EFBFBD> Ȯ<><C8AE><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD>
end;
Memo2_ADD('<27><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> Ŭ<><C5AC><EFBFBD><EFBFBD> <20>Ϸ<EFBFBD> (<28><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>ȭ <20><EFBFBD><E7BCB3>)');
end;
begin
alarmreadck := False;
Result := False;
if PLCconnectCK <> 2 then exit;
Button1.Enabled := False;
try
try
Memo1_ADD('['+FormatDateTime('yymmdd hhnnss.zzz',now)+'] PLCDataLoad - start');
GridAddressListTV.DataController.BeginUpdate;
for i := 0 to GridAddressListTV.DataController.RecordCount - 1 do begin
with GridAddressListTV.DataController do begin
if ClientSocket1.Active then begin
BuildReadPacket(Values[i, GridAddressListTVColumn6.Index],Values[i, GridAddressListTVColumn2.Index]);
Sent := ClientSocket1.Socket.SendBuf(TxBuf, 38);
if Sent <> 38 then begin
Memo2_ADD('<27><>Ŷ <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> PLCDataLoad: ['+IntToStr(Sent)+']-[ '+Values[i, GridAddressListTVColumn2.Index]+' ]');
LoadCK := False;
end
else begin
Sleep(StrToIntDef(Edit1.Text,0));
Recv := ClientSocket1.Socket.ReceiveBuf(RxBuf, 34);
Recv_count_ck := 34;
if (Values[i, GridAddressListTVColumn6.Index] = 'BIT') or (Values[i, GridAddressListTVColumn6.Index] = 'BIT_A') then Recv_count_ck := 33;
if Recv < Recv_count_ck then begin
Memo2_ADD('<27><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> PLCDataLoad: [Sent:'+IntToStr(Sent)+']-[Recv:'+IntToStr(Recv)+']-[ '+Values[i, GridAddressListTVColumn2.Index]+' ]');
// 2. Memo2: <20>ؼ<EFBFBD><D8BC><EFBFBD> <20><><EFBFBD><EFBFBD> - <20><><EFBFBD>а<EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ͱ<EFBFBD> <20><><EFBFBD><EFBFBD>.20251204
if (Values[i, GridAddressListTVColumn6.Index] = 'BIT') then begin
var hexStr := '';
for var x := 0 to Recv - 1 do hexStr := hexStr + IntToHex(RxBuf[x], 2) + ' ';
Memo2_ADD(hexStr);
end else
if (Values[i, GridAddressListTVColumn6.Index] = 'BIT_A') then begin
var hexStr := '';
for var x := 0 to Recv - 1 do hexStr := hexStr + IntToHex(RxBuf[x], 2) + ' ';
Memo2_ADD(hexStr);
end else
if Values[i, GridAddressListTVColumn6.Index] = 'WORD' then begin
var hexStr := '';
for var x := 0 to Recv - 1 do hexStr := hexStr + IntToHex(RxBuf[x], 2) + ' ';
Memo2_ADD(hexStr);
end;
if Recv = -1 then begin
LastError := WSAGetLastError;
case LastError of
10054: ErrorMsg := 'Connection reset by peer (PLC<4C><43><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>)';
10060: ErrorMsg := 'Connection timed out (<28><><EFBFBD><EFBFBD> Ÿ<>Ӿƿ<D3BE>)';
10004: ErrorMsg := 'Interrupted function call (<28><><EFBFBD><EFBFBD>ŷ <20><><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD>)';
else
ErrorMsg := 'Unknown socket error';
end;
Memo2_ADD('<27><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> Recv: ['+IntToStr(Recv)+'] - WSAGetLastError: ['+IntToStr(LastError)+'] - Message: ['+ErrorMsg+']');
end else if Recv = 0 then begin
Memo2_ADD('<27><><EFBFBD><EFBFBD> PLC<4C><43><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> (Recv: 0) - <20>ּ<EFBFBD>: ['+Values[i, GridAddressListTVColumn2.Index]+']');
end else begin
Memo2_ADD('<27><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>ҿ<EFBFBD><D2BF><EFBFBD> (Recv < 34) PLCDataLoad: [Sent:'+IntToStr(Sent)+']-[Recv:'+IntToStr(Recv)+']-[ '+Values[i, GridAddressListTVColumn2.Index]+' ]');
end;
LoadCK := False;
FlushSocketBuffer; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ҿ<EFBFBD><D2BF><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
end
else begin
// 4. [<5B>ű<EFBFBD> <20>߰<EFBFBD>] <20><>û<EFBFBD><C3BB> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Ÿ<>԰<EFBFBD> <20><><EFBFBD>ŵ<EFBFBD> Payload <20><><EFBFBD><EFBFBD> <20><>ġ <20><><EFBFBD><EFBFBD>
var PayloadLen: Integer := RxBuf[16] + (RxBuf[17] shl 8);
var ExpectedLen: Integer := 0;
// BIT <20><>û<EFBFBD><C3BB> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD>̷ε<CCB7><CEB5><EFBFBD> 13<31><33><EFBFBD><EFBFBD>Ʈ (0x0D) <20><><EFBFBD><EFBFBD> <20><>
if (Values[i, GridAddressListTVColumn6.Index] = 'BIT') or (Values[i, GridAddressListTVColumn6.Index] = 'BIT_A') then
ExpectedLen := 13
// WORD <20><>û<EFBFBD><C3BB> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD>̷ε<CCB7><CEB5><EFBFBD> 14<31><34><EFBFBD><EFBFBD>Ʈ (0x0E) <20><><EFBFBD><EFBFBD> <20><>
else if Values[i, GridAddressListTVColumn6.Index] = 'WORD' then
ExpectedLen := 14;
// 1. <20><><EFBFBD><EFBFBD> <20>ñ״<C3B1>ó <20><><EFBFBD><EFBFBD>
if (RxBuf[0] <> $4C) or (RxBuf[1] <> $53) or (RxBuf[2] <> $49) or (RxBuf[3] <> $53) or
(RxBuf[4] <> $2D) or (RxBuf[5] <> $58) or (RxBuf[6] <> $47) or (RxBuf[7] <> $54) then
begin
Memo2_ADD('<27><>Ŷ <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> (<28><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>): LSIS-XGT <20>ñ״<C3B1>ó <20><><EFBFBD><EFBFBD>ġ - <20>ּ<EFBFBD>: ['+Values[i, GridAddressListTVColumn2.Index]+']');
LoadCK := False;
FlushSocketBuffer; // <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
Continue;
end;
// 2. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> (0x11: <20><><EFBFBD><EFBFBD>)
if RxBuf[13] <> $11 then
begin
Memo2_ADD('<27><>Ŷ <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>: PLC <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ƴ<EFBFBD> ['+IntToHex(RxBuf[13], 2)+'] - <20>ּ<EFBFBD>: ['+Values[i, GridAddressListTVColumn2.Index]+']');
LoadCK := False;
FlushSocketBuffer; // <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
Continue;
end;
// 3. <20><><EFBFBD>ɾ<EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> (0x55: Read <20><><EFBFBD><EFBFBD>)
if RxBuf[20] <> $55 then
begin
Memo2_ADD('<27><>Ŷ <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>: Read <20><><EFBFBD><EFBFBD>(0x55) <20><><EFBFBD>ɾ <20>ƴ<EFBFBD> ['+IntToHex(RxBuf[20], 2)+'] - <20>ּ<EFBFBD>: ['+Values[i, GridAddressListTVColumn2.Index]+']');
LoadCK := False;
FlushSocketBuffer; // <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
Continue;
end;
// 4-1. <20><><EFBFBD><EFBFBD> <20><><EFBFBD>̿<EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD>ŵ<EFBFBD> <20><><EFBFBD>̰<EFBFBD> <20>ٸ<EFBFBD><D9B8><EFBFBD> <20>ٸ<EFBFBD> <20><>Ŷ<EFBFBD><C5B6> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>(<28>и<EFBFBD> <20><><EFBFBD><EFBFBD>)<29><>
if (ExpectedLen > 0) and (PayloadLen <> ExpectedLen) then
begin
Memo2_ADD('<27><>Ŷ <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>: <20><>Ŷ <20><>Ŵ <20><><EFBFBD><EFBFBD>. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>:['+IntToStr(ExpectedLen)+'] <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>:['+IntToStr(PayloadLen)+'] - <20>ּ<EFBFBD>: ['+Values[i, GridAddressListTVColumn2.Index]+']');
LoadCK := False;
FlushSocketBuffer; // <20><>Ų <20><><EFBFBD>۸<EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD>ź<EFBFBD><C5BA><EFBFBD> <20><><EFBFBD><EFBFBD>ȭ
Continue;
end;
// 5. [<5B>ſ<EFBFBD> <20>߿<EFBFBD>] <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> (RxBuf[26], RxBuf[27])
// PLC<4C><43><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><><C2AA> <20><>Ŷ)<29><> <20><> 1,2,3<><33> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>մϴ<D5B4>. <20><><EFBFBD><20>ɷ<EFBFBD><C9B7><EFBFBD><EFBFBD><EFBFBD> <20>մϴ<D5B4>!
if (RxBuf[26] <> $00) or (RxBuf[27] <> $00) then
begin
var ErrorStatus: Word := RxBuf[26] + (RxBuf[27] shl 8);
Memo2_ADD('<27><>Ŷ <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>: PLC <20><> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>߻<EFBFBD> [<5B><><EFBFBD><EFBFBD><EFBFBD>ڵ<EFBFBD>: 0x'+IntToHex(ErrorStatus, 4)+'] - <20>ּ<EFBFBD>: ['+Values[i, GridAddressListTVColumn2.Index]+']');
LoadCK := False;
FlushSocketBuffer; // <20><><EFBFBD><EFBFBD> <20><>Ŷ<EFBFBD><C5B6><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>Ϻ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
Continue;
end;
// ==========================================
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> - <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>Ľ<EFBFBD> <20><><EFBFBD><EFBFBD>
// ==========================================
if Values[i, GridAddressListTVColumn6.Index] = 'BIT' then begin
var value := RxBuf[32];
var hexStr_ := '';
for var x := 0 to 38 - 1 do hexStr_ := hexStr_ + IntToHex(TxBuf[x], 2) + ' ';
var hexStr := '';
for var x := 0 to Recv - 1 do hexStr := hexStr + IntToHex(RxBuf[x], 2) + ' ';
Memo2_ADD(Values[i, GridAddressListTVColumn2.Index]+
' // '+'DEC : '+IntToStr(value) +
' // '+'HEX : '+IntToHex(value, 2) +
' // '+'TxBuf: '+hexStr_ +
' // '+'RxBuf: '+hexStr );
Values[i, GridAddressListTVColumn4.Index] := IntToHex(value, 2);
Values[i, GridAddressListTVColumn5.Index] := FormatDateTime('yymmdd hhnnss.zzz',Now);
Values[i, GridAddressListTVColumn7.Index] := 0;
if value = 0 then begin
Values[i, GridAddressListTVColumn3.Index] := 'False';
end
else begin
Values[i, GridAddressListTVColumn3.Index] := 'True';
end;
end else
if Values[i, GridAddressListTVColumn6.Index] = 'BIT_A' then begin
var value := RxBuf[32];
var hexStr_ := '';
for var x := 0 to 38 - 1 do hexStr_ := hexStr_ + IntToHex(TxBuf[x], 2) + ' ';
var hexStr := '';
for var x := 0 to Recv - 1 do hexStr := hexStr + IntToHex(RxBuf[x], 2) + ' ';
Memo2_ADD(Values[i, GridAddressListTVColumn2.Index]+
' // '+'DEC : '+IntToStr(value) +
' // '+'HEX : '+IntToHex(value, 2) +
' // '+'TxBuf: '+hexStr_ +
' // '+'RxBuf: '+hexStr );
Values[i, GridAddressListTVColumn4.Index] := IntToHex(value, 2);
Values[i, GridAddressListTVColumn5.Index] := FormatDateTime('yymmdd hhnnss.zzz',Now);
if value = 0 then begin
Values[i, GridAddressListTVColumn3.Index] := 'False';
if Values[i, GridAddressListTVColumn7.Index] > 0 then begin
Alarm_use := Alarm_use_CK;
if AlarmSend('<27><><EFBFBD><EFBFBD><EFBFBD>Ұ<EFBFBD><D2B0><EFBFBD>-0'+inttostr(PLC_NO),Values[i, GridAddressListTVColumn1.Index],'<27>Ϸ<EFBFBD>') then begin
Values[i, GridAddressListTVColumn7.Index] := 0;
end;
end;
end
else begin
alarmreadck := true;
Values[i, GridAddressListTVColumn3.Index] := 'True';
if (Values[i, GridAddressListTVColumn7.Index] = 0) or (Values[i, GridAddressListTVColumn7.Index] >= Alarm_re) then begin
Alarm_use := Alarm_use_CK;
if AlarmSend('<27><><EFBFBD><EFBFBD><EFBFBD>Ұ<EFBFBD><D2B0><EFBFBD>-0'+inttostr(PLC_NO),Values[i, GridAddressListTVColumn1.Index],'<27>߻<EFBFBD>') then begin
Values[i, GridAddressListTVColumn7.Index] := 1;
end
else begin
Values[i, GridAddressListTVColumn7.Index] := Values[i, GridAddressListTVColumn7.Index] + 1;
end;
end
else begin
Values[i, GridAddressListTVColumn7.Index] := Values[i, GridAddressListTVColumn7.Index] + 1;
end;
end;
end else
if Values[i, GridAddressListTVColumn6.Index] = 'WORD' then begin
var DataWord: Word := RxBuf[32] + (RxBuf[33] shl 8);
var SignedValue: SmallInt := SmallInt(DataWord);
var hexStr_ := '';
for var x := 0 to 38 - 1 do hexStr_ := hexStr_ + IntToHex(TxBuf[x], 2) + ' ';
var hexStr := '';
for var x := 0 to Recv - 1 do hexStr := hexStr + IntToHex(RxBuf[x], 2) + ' ';
Memo2_ADD(Values[i, GridAddressListTVColumn2.Index]+
' // '+'DEC : '+IntToStr(SignedValue) +
' // '+'HEX : '+IntToHex(DataWord, 4) +
' // '+'TxBuf: '+hexStr_ +
' // '+'RxBuf: '+hexStr );
Values[i, GridAddressListTVColumn3.Index] := IntToStr(SignedValue);
Values[i, GridAddressListTVColumn4.Index] := IntToHex(DataWord, 4);
Values[i, GridAddressListTVColumn5.Index] := FormatDateTime('yymmdd hhnnss.zzz',Now);
end;
LoadCK := True;
end;
end;
end;
end;
Refresh;
end;
except
on E: Exception do begin
Memo1_ADD('PLCDataLoad Error : ' + E.Message);
LoadCK := False;
FlushSocketBuffer; // <20><><EFBFBD><EFBFBD> <20>߻<EFBFBD> <20>ÿ<EFBFBD><C3BF><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϰ<EFBFBD> <20>ʱ<EFBFBD>ȭ
end;
end;
finally
Memo1_ADD('['+FormatDateTime('yymmdd hhnnss.zzz',now)+'] PLCDataLoad - end');
Result := LoadCK;
GridAddressListTV.DataController.EndUpdate;
Button1.Enabled := True;
Refresh;
if alarmreadck then DB_Insert;
end;
end;
function TF_LSPLCAgent.PLCDataLoadMulti:boolean;
var
t, i, j, t_count : integer;
Sent, Recv: Integer;
addrList: TStringList;
addr_Values: TArray<Word>;
Addr_Count: Integer;
begin
Button1.Enabled := False;
addrList := TStringList.Create;
try
try
GridAddressListTV.DataController.BeginUpdate;
t_count := GridAddressListTV.DataController.RecordCount;
if (t_count mod 10) > 0 then begin
t := (t_count div 10) +1;
end
else begin
if t_count < 10 then t := 1 else t := (t_count div 10);
end;
for i := 0 to t - 1 do begin
Addr_Count := 0;
with GridAddressListTV.DataController do begin
addrList.Clear;
for j := 0 to 9 do begin
if ((i*10) + j) <= t_count then begin
// Values[(i*10) + j, GridAddressListTVColumn5.Index] := '';
addrList.Add(Values[(i*10) + j, GridAddressListTVColumn2.Index]);
end
else begin
Break;
end;
end;
if ClientSocket1.Active then begin
BuildReadPacketMulti(addrList);
Sent := ClientSocket1.Socket.SendBuf(TxBuf, 36);
if Sent <> 36 then begin
Memo1_ADD('<27><>Ŷ <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> : [ '+Values[i, GridAddressListTVColumn2.Index]+' ]');
// Exit;
end
else begin
Recv := ClientSocket1.Socket.ReceiveBuf(RxBuf, 34);
if Recv < 34 then begin
Memo1_ADD('<27><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> : [ '+Values[i, GridAddressListTVColumn2.Index]+' ]');
// Exit;
end
else begin
ParseMultiReadResponse(RxBuf, addrList.Count, addr_Values);
// addr_Values <20><EFBFBD><E8BFAD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// ShowMessage('ù<><C3B9>° <20>ּҰ<D6BC>: ' + IntToStr(Values[0]));
for j := 0 to 9 do begin
if ((i*10) + j) <= t_count then begin
Values[(i*10) + j, GridAddressListTVColumn3.Index] := addr_Values[j].ToString;
Values[(i*10) + j, GridAddressListTVColumn4.Index] := addr_Values[j].ToHexString;
Values[(i*10) + j, GridAddressListTVColumn5.Index] := FormatDateTime('yymmdd hhnnss.zzz',Now);
end
else begin
Break;
end;
end;
end;
end;
end;
end;
Sleep(StrToIntDef(Edit1.Text,0));
Refresh;
end;
except
on E: Exception do begin
Memo1_ADD('PLCDataLoadMulti Error : ' + E.Message);
end;
end;
finally
Result := True;
GridAddressListTV.DataController.EndUpdate;
Button1.Enabled := True;
addrList.Free;
end;
end;
procedure TF_LSPLCAgent.insertSQL(status,sql : string);
begin
try
if not FDConnection1.Connected then FDConnection1.Connected := True;
if FDConnection1.Connected then
begin
FDQuery1.Active := false;
FDQuery1.SQL.Clear;
FDQuery1.SQL.Add(sql);
FDQuery1.ExecSQL;
lastDBInsert := now;
if (status = '<27><><EFBFBD><EFBFBD>') and (lb_status.Caption <> status) then begin
lb_status.Caption := '<27><><EFBFBD><EFBFBD>';
end;
end;
except
on e : exception do
begin
Memo2_ADD('[insertSQL()]Database insertSQL Error :: '+e.Message);
end;
end;
end;
procedure TF_LSPLCAgent.ParseMultiReadResponse(var RxBuf: array of Byte; AddrCount: Integer; out Values: TArray<Word>);
var
i, pos: Integer;
begin
SetLength(Values, AddrCount);
// <20><20><><EFBFBD><EFBFBD> 20<32><30><EFBFBD><EFBFBD>Ʈ<EFBFBD><C6AE> <20>dzʶ<C7B3>, <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><>ġ
pos := 20;
// <20><><EFBFBD><EFBFBD><EFBFBD>ڵ<EFBFBD> üũ
if RxBuf[pos] <> $54 then
raise Exception.Create('Invalid response command code.');
pos := pos + 7;
// pos<6F><73> 27<32><37> <20><> (<28><>û <20><> Variable count <20><>ġ)
// Variable count Ȯ<><C8AE> (<28><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>)
if RxBuf[pos] <> AddrCount then
raise Exception.Create('Response variable count mismatch.');
pos := pos + 2; // <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><>ġ
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>б<EFBFBD> (WORD Ÿ<><C5B8>, 2<><32><EFBFBD><EFBFBD>Ʈ<EFBFBD><C6AE>)
for i := 0 to AddrCount - 1 do
begin
if pos + 1 > High(RxBuf) then
raise Exception.Create('Response packet too short.');
Values[i] := (RxBuf[pos] shl 8) or RxBuf[pos + 1];
Inc(pos, 2);
end;
end;
procedure TF_LSPLCAgent.Tmr_DBInsertTimer(Sender: TObject);
begin
Tmr_DBInsert.Enabled := False;
if LoadCK and (not close_ck) then begin
DB_Insert;
if not Button6.Enabled then
Tmr_DBInsert.Enabled := True;
end;
end;
procedure TF_LSPLCAgent.Tmr_PLCReadTimer(Sender: TObject);
begin
Tmr_PLCRead.Enabled := False;
if not close_ck then begin
if RadioButton1.Checked then
Button1.Click
else
Button5.Click;
if not Button6.Enabled then
Tmr_PLCRead.Enabled := True;
end;
end;
procedure TF_LSPLCAgent.tmrExitTimer(Sender: TObject);
begin
case tmrExit.Tag of
0 : begin
tmrExit.Tag := tmrExit.Tag+1;
end;
1..4 : tmrExit.Tag := tmrExit.Tag+1;
5 : begin
tmrExit.Tag := tmrExit.Tag+1;
tmrExit.Enabled := false;
ExitOk := true;
Close;
end;
end;//case..
end;
procedure TF_LSPLCAgent.TrayIcon1Click(Sender: TObject);
begin
TrayIcon1.Visible := False;
Show;
WindowState := wsNormal;
Application.BringToFront;
end;
procedure TF_LSPLCAgent.Button1Click(Sender: TObject);
begin
if PLCconnectCK <> 2 then begin
if lb_status.Caption <> '<27><><EFBFBD><EFBFBD>' then begin
PLC_statusUpdate('<27><><EFBFBD><EFBFBD>');
end;
PLC_connect;
end
else begin
// if PLCconnectCK = 2 then begin
if PLCDataLoad then begin
// LoadCK := True;
if LoadCK then
Memo1_ADD('['+FormatDateTime('yymmdd hhnnss.zzz',now)+'] PLCDataLoad - ok')
else
Memo1_ADD('['+FormatDateTime('yymmdd hhnnss.zzz',now)+'] PLCDataLoad - fail');
end
else begin
LoadCK := False;
end;
if not LoadCK then begin
if lb_status.Caption <> '<27><><EFBFBD><EFBFBD>' then begin
PLC_statusUpdate('<27><><EFBFBD><EFBFBD>');
end;
end;
// end;
end;
end;
procedure TF_LSPLCAgent.PLC_statusUpdate(Plc_status:string);
var
update_sql : string;
begin
try
update_sql := '';
update_sql := 'UPDATE "plc_Data" SET '+
'"dev_status"='''+Plc_status+''', '+
'"UpdateDT"=now() '+
' WHERE "plcID"='+inttostr(PLC_NO);
if not FDConnection1.Connected then FDConnection1.Connected := True;
if FDConnection1.Connected then
begin
FDQuery1.Active := false;
FDQuery1.SQL.Clear;
FDQuery1.SQL.Add(update_sql);
FDQuery1.ExecSQL;
lastDBInsert := now;
if lb_status.Caption <> Plc_status then begin
lb_status.Caption := Plc_status;
end;
end;
except
on e : exception do
begin
Memo2_ADD('[insertSQL()]Database Connect Error :: '+e.Message);
end;
end;
end;
procedure TF_LSPLCAgent.Button2Click(Sender: TObject);
var
i : integer;
Ini: TIniFile;
begin
// ini <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>..
Ini := TIniFile.Create(inifilename);
try
Ini.WriteString('PLC', 'IP', Edit5.Text);
Ini.WriteString('PLC', 'PORT', Edit6.Text);
finally
Ini.Free;
end;
if FileExists(StringReplace(Application.ExeName,'.exe','_list1.ini',[rfReplaceAll])) then
RenameFile(StringReplace(Application.ExeName,'.exe','_list1.ini',[rfReplaceAll]),
StringReplace(Application.ExeName,'.exe','_list1_'+FormatDateTime('yymmdd_hhnnss.zzz',now)+'.ini.bak',[rfReplaceAll]));
if FileExists(StringReplace(Application.ExeName,'.exe','_list2.ini',[rfReplaceAll])) then
RenameFile(StringReplace(Application.ExeName,'.exe','_list2.ini',[rfReplaceAll]),
StringReplace(Application.ExeName,'.exe','_list2_'+FormatDateTime('yymmdd_hhnnss.zzz',now)+'.ini.bak',[rfReplaceAll]));
if FileExists(StringReplace(Application.ExeName,'.exe','_list3.ini',[rfReplaceAll])) then
RenameFile(StringReplace(Application.ExeName,'.exe','_list3.ini',[rfReplaceAll]),
StringReplace(Application.ExeName,'.exe','_list3_'+FormatDateTime('yymmdd_hhnnss.zzz',now)+'.ini.bak',[rfReplaceAll]));
ListBox3.Clear;
ListBox2.Clear;
ListBox1.Clear;
for i := 0 to GridAddressListTV.DataController.RecordCount - 1 do begin
with GridAddressListTV.DataController do begin
ListBox3.Items.Add(Values[i, GridAddressListTVColumn6.Index]);
ListBox2.Items.Add(Values[i, GridAddressListTVColumn1.Index]);
ListBox1.Items.Add(Values[i, GridAddressListTVColumn2.Index]);
end;
end;
ListBox1.Items.SaveToFile(StringReplace(Application.ExeName,'.exe','_list1.ini',[rfReplaceAll]));
ListBox2.Items.SaveToFile(StringReplace(Application.ExeName,'.exe','_list2.ini',[rfReplaceAll]));
ListBox3.Items.SaveToFile(StringReplace(Application.ExeName,'.exe','_list3.ini',[rfReplaceAll]));
end;
procedure TF_LSPLCAgent.Button3Click(Sender: TObject);
var
SL: TStringList;
i, j: Integer;
Row: string;
begin
SL := TStringList.Create;
try
for i := 0 to GridAddressListTV.DataController.RecordCount - 1 do
begin
Row := '';
for j := 0 to GridAddressListTV.ColumnCount - 1 do
Row := Row + GridAddressListTV.DataController.DisplayTexts[i, j] + ',';
SL.Add(Copy(Row, 1, Length(Row) - 1)); // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> , <20><><EFBFBD><EFBFBD>
end;
SL.SaveToFile('.\grid.dat');
finally
SL.Free;
end;
end;
procedure TF_LSPLCAgent.Button4Click(Sender: TObject);
var
SL, Items: TStringList;
i, j: Integer;
begin
SL := TStringList.Create;
Items := TStringList.Create;
try
SL.LoadFromFile('.\grid.dat');
GridAddressListTV.BeginUpdate;
GridAddressListTV.DataController.RecordCount := SL.Count;
for i := 0 to SL.Count - 1 do
begin
Items.Delimiter := ','; // <20>޸<EFBFBD><DEB8><EFBFBD> <20><><EFBFBD><EFBFBD>
Items.StrictDelimiter := True; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
Items.CommaText := SL[i];
for j := 0 to Min(Items.Count - 1, GridAddressListTV.ColumnCount - 1) do
begin
GridAddressListTV.DataController.Values[i, j] := Items[j];
end;
end;
GridAddressListTV.EndUpdate;
finally
Items.Free;
SL.Free;
end;
end;
procedure TF_LSPLCAgent.Button5Click(Sender: TObject); // <20>ϰ<EFBFBD>
begin
if not ClientSocket1.Active then PLC_connect;
if PLCDataLoadMulti then
Memo1_ADD('['+FormatDateTime('yymmdd hhnnss.zzz',now)+'] PLCDataLoadMulti - ok');
end;
procedure TF_LSPLCAgent.Button6Click(Sender: TObject);
begin
if Button11.Caption = 'Connect' then begin
PLC_connect;
end;
Button1.Enabled := False;
Tmr_PLCRead.Enabled := False;
Tmr_PLCRead.Interval := StrToIntDef(Edit2.Text,1000);
Tmr_PLCRead.Enabled := True;
Sleep(500);
Tmr_DBInsert.Enabled := False;
Tmr_DBInsert.Interval := StrToIntDef(Edit2.Text,1000);
Tmr_DBInsert.Enabled := True;
Timer_runningCK.Enabled := False;
Timer_runningCK.Enabled := True;
Button6.Enabled := False;
Button7.Enabled := True;
end;
procedure TF_LSPLCAgent.Button7Click(Sender: TObject);
begin
Button1.Enabled := True;
Tmr_PLCRead.Enabled := False;
Button6.Enabled := True;
Button7.Enabled := False;
end;
procedure TF_LSPLCAgent.Button8Click(Sender: TObject);
var
Ini: TIniFile;
begin
inifilename := StringReplace(Application.ExeName,'.exe','.ini',[rfReplaceAll]);
Ini := TIniFile.Create(inifilename);
try
if Trim(Edit3.Text) <> '' then
Alarm_re := strtoint(Edit3.Text)
else
Alarm_re := 60;
Ini.WriteInteger('ALARM_RE','sec',Alarm_re);
finally
Ini.Free;
end;
end;
procedure TF_LSPLCAgent.Button9Click(Sender: TObject);
begin
Alarm_use := Alarm_use_CK;
if AlarmSend(Edit30.Text,Edit31.Text,Edit33.Text) then begin
ShowMessage('SMS <20><><EFBFBD><EFBFBD> <20>Ϸ<EFBFBD>');
end
else begin
ShowMessage('SMS <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>');
end;
end;
function TF_LSPLCAgent.qCreateGetUniqueString(clsName: string): string;
var
randomInt: Integer;
tmStmp: TTimeStamp;
dbName: string;
begin
//****************OBID<49><44>Ģ*****************//
//Result := clsName(Ŭ<><C5AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>) + '-Ÿ<>Խ<EFBFBD><D4BD><EFBFBD><EFBFBD><EFBFBD>-' + '-6<>ڸ<EFBFBD><DAB8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>-' + '<27><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>';
//****************OBID<49><44>Ģ*****************//
Result := '';
tmStmp := DateTimeToTimeStamp(Now);
randomInt := random(899998) + 100001; //100001 ~ 999999
dbName := 'neol_data';
Result := 'T' + clsName + '-' + IntToStr(tmStmp.Date) + IntToStr(tmStmp.Time) + '-' + IntToStr(randomInt) + '-' + dbName;
end;
procedure TF_LSPLCAgent.RadioButton4Click(Sender: TObject);
begin
if RadioButton1.Checked then begin
Memo3.Clear;
Memo3.Lines.Add('[<5B>׿<EFBFBD>]');
Memo3.Lines.Add('%s');
Memo3.Lines.Add('%s');
Memo3.Lines.Add('<27><><EFBFBD><EFBFBD> %s<><73>');
Memo3.Lines.Add('https://neol.co.kr');
end
else begin
Memo3.Clear;
Memo3.Lines.Add('[<5B>׿<EFBFBD>]');
Memo3.Lines.Add('%s');
Memo3.Lines.Add('-');
Memo3.Lines.Add('%s');
Memo3.Lines.Add('-');
Memo3.Lines.Add('%s');
Memo3.Lines.Add('-');
Memo3.Lines.Add('https://neol.co.kr');
end;
end;
function TF_LSPLCAgent.xGenerateHMACSHA256(const Key, Data: string): string;
var
HashBytes: TBytes;
begin
HashBytes := THashSHA2.GetHMACAsBytes(TEncoding.UTF8.GetBytes(Data), TEncoding.UTF8.GetBytes(Key), SHA256);
Result := TNetEncoding.Base64.EncodeBytesToString(HashBytes);
end;
function TF_LSPLCAgent.xSendSMS(const Options: TSMSOptions; const ServiceId,
AccessKey, SecretKey: string): string;
var
i: Integer;
Client: TNetHTTPClient;
Request: TStringStream;
JsonObj, MsgObj: TJSONObject;
JsonArray: TJSONArray;
Response: IHTTPResponse;
Timestamp: Int64;
SignTarget, Signature, URL: string;
begin
Client := TNetHTTPClient.Create(nil);
try
Timestamp := DateTimeToUnix(TTimeZone.Local.ToUniversalTime(Now)) * 1000;
//SignTarget := METHOD + ' ' + URL + #10 + IntToStr(Timestamp) + #10 + AccessKey;
SignTarget := METHOD + ' ' + '/sms/v2/services/' + ServiceId + '/messages' + #10 + IntToStr(Timestamp) + #10 + AccessKey;
//HMAC-SHA256 <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> (`THashSHA2` <20><><EFBFBD><EFBFBD>)
Signature := xGenerateHMACSHA256(SecretKey, SignTarget);
URL := Format(Edit25.Text, [ServiceId]);
JsonObj := TJSONObject.Create;
try
if RadioButton1.Checked then
JsonObj.AddPair('type', 'SMS')
else
JsonObj.AddPair('type', 'MMS');
JsonObj.AddPair('contentType', 'COMM');
JsonObj.AddPair('countryCode', COUNTRY_CODE);
JsonObj.AddPair('from', Options.FromNumber);
JsonObj.AddPair('content', Options.Text);
JsonArray := TJSONArray.Create;
for i := 0 to Options.ToNumber.Count-1 do begin
MsgObj := TJSONObject.Create;
MsgObj.AddPair('to', Options.ToNumber.Strings[i]);
MsgObj.AddPair('content', Options.Text);
JsonArray.AddElement(MsgObj);
end;
JsonObj.AddPair('messages', JsonArray);
Request := TStringStream.Create(JsonObj.ToJSON, TEncoding.UTF8);
try
Client.CustomHeaders['Content-Type'] := CONTENT_TYPE;
Client.CustomHeaders['x-ncp-apigw-timestamp'] := IntToStr(Timestamp);
Client.CustomHeaders['x-ncp-iam-access-key'] := AccessKey;
Client.CustomHeaders['x-ncp-apigw-signature-v2'] := Signature;
Response := Client.Post(Format(Edit25.Text, [ServiceId]), Request);
Result := Response.ContentAsString;
finally
Request.Free;
end;
finally
JsonObj.Free;
end;
finally
Client.Free;
end;
end;
procedure TF_LSPLCAgent.EmgAlarmlistrefresh;
var
empmst : Tempmst;
tmpList : TList;
row, x : integer;
begin
try
tmpList := TList.Create;
empmst := Tempmst.Create(self);
tmpList := empmst.xGetStrSqlEmpMstList(FDQuery1,'<27><><EFBFBD><EFBFBD>','','');
with cxGridTableView3.DataController do begin
try
BeginUpdate;
RecordCount := 0;
finally
EndUpdate;
end;
end;
for x := 0 to tmpList.Count-1 do begin
empmst := tmpList.Items[x];
if StrToBool(empmst.IsAlarm) then begin
with cxGridTableView3.DataController do begin
try
BeginUpdate;
row := AppendRecord;
Values[row,cxGridTableView3Column1.Index] := StringReplace(empmst.EmpTelNum, '-', '', [rfReplaceAll]);
Values[row,cxGridTableView3Column2.Index] := empmst.Name;
Values[row,cxGridTableView3Column3.Index] := empmst.Position;
Values[row,cxGridTableView3Column4.Index] := empmst.Role;
finally
EndUpdate;
end;
end;
end;
end;
finally
tmpList.free;
end;
end;
function TF_LSPLCAgent.AlarmSend(devName,alarm_detail,alarm_status:string):Boolean;
var
i: Integer;
Response, pID, aKey, sKey: string;
sql : string;
ToNum : string;
ToNumlist : TStringList;
begin
Result := False;
EmgAlarmlistrefresh;
if RadioGroup1.ItemIndex = 1 then begin //TEST
//ȸ<><C8B8> <20><><EFBFBD><EFBFBD>..ť<><C5A5><EFBFBD><EFBFBD>..
pID := 'ncp:sms:kr:337071110685:qst';
aKey := 'qW8o6nlh4ORI7zpt0ai2';
sKey := 'Uqt8kJECZxvrBBYN1EMlmJfEGQuR4hStkvVuiSTS';
//ť<><C5A5><EFBFBD><EFBFBD> <20>߽<EFBFBD><DFBD><EFBFBD><EFBFBD><EFBFBD> <20><>ȣ..
FsmsObj.FromNumber := '07082802424';
end
else begin // REAL
//<2F>׿<EFBFBD>..Access key, Secret key..
pID := Edit32.Text;
aKey := Edit26.Text;
sKey := Edit27.Text;
//<2F>׿<EFBFBD> <20>߽<EFBFBD><DFBD><EFBFBD><EFBFBD><EFBFBD> <20><>ȣ..
FsmsObj.FromNumber := '0336480037';
end;
try
ToNumlist := TStringList.Create;
with cxGridTableView3.DataController do begin
for I := 0 to RecordCount-1 do begin
ToNumlist.Add(Values[i,cxGridTableView3Column1.Index]);
end;
end;
// <20><><EFBFBD><EFBFBD><EFBFBD>ڹ<EFBFBD>ȣ
FsmsObj.ToNumber := ToNumlist;
if Alarm_use then begin
if (FormatDateTime('hh:nn',Now) <= '02:55') and
(FormatDateTime('hh:nn',Now) >= '03:05') then begin
FsmsObj.Text := Format(Memo3.Text, [alarm_status,devName,alarm_detail]);
end
else begin
FsmsObj.Text := '[<5B>˶<EFBFBD> <20><><EFBFBD><EFBFBD>] '+Format(Memo3.Text, [alarm_status,devName,alarm_detail]);
end;
end
else begin
FsmsObj.Text := '[<5B>˶<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>] '+Format(Memo3.Text, [alarm_status,devName,alarm_detail]);
end;
if (Trim(FsmsObj.FromNumber) <> '') and
(Trim(FsmsObj.Text) <> '') and
(FsmsObj.ToNumber.Count > 0) then begin
Memo4.Clear;
Memo5.Clear;
if Alarm_use then begin
if (FormatDateTime('hh:nn',Now) <= '02:55') and
(FormatDateTime('hh:nn',Now) >= '03:05') then begin
Response := xSendSMS(FsmsObj, pID, aKey, sKey);
end
else begin
Response := '[<5B>˶<EFBFBD> <20><><EFBFBD><EFBFBD>] : success';
end;
end
else begin
Response := '[<5B>˶<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>] : success';
end;
ToNum := '';
for i := 0 to FsmsObj.ToNumber.Count-1 do begin
Memo4.Lines.Add(FsmsObj.ToNumber.Strings[i]);
if i = 0 then
ToNum := FsmsObj.ToNumber.Strings[i]
else
ToNum := ToNum +' / '+ FsmsObj.ToNumber.Strings[i];
end;
Memo4.Lines.Add(FsmsObj.FromNumber);
Memo4.Lines.Add(FsmsObj.Text);
Memo5.Lines.Add('<27><><EFBFBD><EFBFBD>: ' + Response);
if pos('success',Response) > 0 then result := True;
sql := '';
sql := 'INSERT INTO "AlarmLog" VALUES( '+
''''+''+''', '+
''''+qCreateGetUniqueString('AlarmLog')+''', '+
''''+'AlarmLog'+''', '+
''''+FormatDateTime('yyyy-mm-dd',Now)+''', '+
''''+FormatDateTime('hh:nn:ss.zzzzzz',Now)+''', '+
''''+F_LSPLCAgent.Caption+''', '+
''''+'t'+''', '+
''''+'Working'+''', '+
''''+devName+''', '+
''''+'<27>Ұ<EFBFBD>'+''', '+
''''+StringReplace(FsmsObj.Text, #$D#$A, '', [rfReplaceAll])+''', '+
''''+FormatDateTime('yyyy-mm-dd',Now)+''', '+
''''+FormatDateTime('hh:nn:ss.zzzzzz',Now)+''', '+
''''+ToNum+''', '+
''''+FormatDateTime('yyyy-mm-dd',Now)+''', '+
''''+FormatDateTime('hh:nn:ss.zzzzzz',Now)+''', '+
''''+alarm_detail+''', '+
''''+alarm_detail+''', '+
''''+alarm_status+''', '+
'NULL '+
')';
// ShowMessage(sql);
insertSQL('<27>˶<EFBFBD>',sql);
end
else begin
if Trim(FsmsObj.FromNumber) = '' then begin
Memo4.Lines.Add('<27>߽<EFBFBD><DFBD>ڹ<EFBFBD>ȣ Ȯ<><C8AE><EFBFBD>ʿ<EFBFBD>!');
end;
if Trim(FsmsObj.Text) = '' then begin
Memo4.Lines.Add('<27>޼<EFBFBD><DEBC><EFBFBD> <20><><EFBFBD><EFBFBD> Ȯ<><C8AE><EFBFBD>ʿ<EFBFBD>!');
end;
if FsmsObj.ToNumber.Count <= 0 then begin
Memo4.Lines.Add('<27><><EFBFBD><EFBFBD><EFBFBD>ڹ<EFBFBD>ȣ Ȯ<><C8AE><EFBFBD>ʿ<EFBFBD>!');
end;
end;
finally
ToNumlist.Free;
end;
end;
procedure TF_LSPLCAgent.CheckBox1Click(Sender: TObject);
var
Ini: TIniFile;
begin
// ini <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>..
Ini := TIniFile.Create(inifilename);
try
Ini.WriteString('START', 'AUTO', BoolToStr(CheckBox1.Checked));
finally
Ini.Free;
end;
end;
procedure TF_LSPLCAgent.ClientSocket1_oldConnect(Sender: TObject;
Socket: TCustomWinSocket);
begin
Button11.Caption := 'DisConnect';
Memo1_ADD('['+FormatDateTime('yymmdd hhnnss.zzz',now)+'] PLC <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>!');
PLCconnectCK := 2; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
end;
procedure TF_LSPLCAgent.ClientSocket1_oldConnecting(Sender: TObject;
Socket: TCustomWinSocket);
begin
Memo1_ADD('['+FormatDateTime('yymmdd hhnnss.zzz',now)+'] <20><><EFBFBD><EFBFBD> <20>õ<EFBFBD>.');
end;
procedure TF_LSPLCAgent.ClientSocket1_oldDisconnect(Sender: TObject;
Socket: TCustomWinSocket);
begin
Memo1_ADD('['+FormatDateTime('yymmdd hhnnss.zzz',now)+'] <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>!');
Button11.Caption := 'Connect';
PLCconnectCK := 0; // <20>ʱⰪ : 0 - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
LoadCK := False;
end;
procedure TF_LSPLCAgent.ClientSocket1_oldError(Sender: TObject;
Socket: TCustomWinSocket; ErrorEvent: TErrorEvent; var ErrorCode: Integer);
begin
Memo1_ADD('['+FormatDateTime('yymmdd hhnnss.zzz',now)+'] PLC <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>: ' + IntToStr(ErrorCode));
PLCconnectCK := 0; // <20>ʱⰪ : 0 - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
ErrorCode := 0; // <20><><EFBFBD><EFBFBD> <20>߻<EFBFBD> <20><><EFBFBD><EFBFBD>
LoadCK := False;
end;
procedure TF_LSPLCAgent.ClientSocket1_oldRead(Sender: TObject;
Socket: TCustomWinSocket);
var
Buf: array[0..1023] of Byte;
i, Len: Integer;
RawData: TBytes;
BufCopy: TBytes;
S: string;
Recv: Integer;
begin
try
Len := Socket.ReceiveBuf(Buf, SizeOf(Buf));
if Len > 0 then begin
SetLength(RawData, Len);
Move(Buf, RawData[0], Len);
// 1. Memo1<6F><31> <20><><EFBFBD><EFBFBD> ǥ<><C7A5>
S := '';
for i := 0 to Len - 1 do S := S + IntToHex(RawData[i], 2) + ' ';
Memo2_ADD('>> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> (HEX) : ' + S);
// Memo2_ADD(S);
end;
except
on E: Exception do begin
Memo1_ADD('Read error: ' + E.Message);
LoadCK := False;
end;
end;
end;
procedure TF_LSPLCAgent.AppEvtMinimize(Sender: TObject);
begin
Hide;
WindowState := wsMinimized;
TrayIcon1.Visible := True;
TrayIcon1.Animate := True;
TrayIcon1.ShowBalloonHint;
end;
procedure TF_LSPLCAgent.FormClose(Sender: TObject; var Action: TCloseAction);
begin
close_ck := true;
Timer_runningCK.Enabled := False;
Tmr_DBInsert.Enabled := False;
Tmr_PLCRead.Enabled := False;
end;
procedure TF_LSPLCAgent.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
if ExitOk then begin
CanClose := true;
end else begin
CanClose := false;
case MessageBox(handle, '"<22><>(Y)"<22><> Ŭ<><C5AC><EFBFBD>ϸ<EFBFBD>, LSPLC Agent01<30><31> Ʈ<><C6AE><EFBFBD>̷<EFBFBD> <20>ּ<EFBFBD>ȭ <20>˴ϴ<CBB4>.'+#$0D#$0A#$0D#$0A+'"<22>ƴϿ<C6B4>(N)"<22><> Ŭ<><C5AC><EFBFBD>ϸ<EFBFBD> <20><><EFBFBD>α׷<CEB1><D7B7><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>˴ϴ<CBB4>. ', 'LSPLC Agent01 :: Ʈ<><C6AE><EFBFBD>̷<EFBFBD> <20>ּ<EFBFBD>ȭ <20>ұ<EFBFBD><D2B1><EFBFBD>?', MB_YESNOCANCEL) of
ID_YES : begin
TrayIcon1.BalloonTitle := 'LSPLC Agent ȭ<><C8AD><EFBFBD><EFBFBD> <20>ٽ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>...';
TrayIcon1.BalloonHint := <><C6AE><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>Ŭ<EFBFBD><C5AC><EFBFBD>ϼ<EFBFBD><CFBC><EFBFBD>.';
//TrayIcon1.BalloonFlags := bfInfo;
AppEvtMinimize(self);
end;
ID_NO : begin
//<2F><><EFBFBD><EFBFBD> Ÿ<≯<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϰ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ExitOk~
tmrExit.Tag := 0;
tmrExit.Enabled := true;
end;
end;//case..
end;//if~
end;
procedure TF_LSPLCAgent.FormCreate(Sender: TObject);
var
i, j : Integer;
Sections: TStringList;
CK_ROW : integer;
Ini: TIniFile;
begin
close_ck := False;
LoadCK := False;
PLCconnectCK := 0;
lastDBInsert := now;
inifilename := StringReplace(Application.ExeName,'.exe','.ini',[rfReplaceAll]);
Ini := TIniFile.Create(inifilename);
try
Edit5.Text := Ini.ReadString('PLC', 'IP', '192.168.100.11');
Edit6.Text := Ini.ReadString('PLC', 'PORT', '2004');
CheckBox1.Checked := Ini.ReadBool('START', 'AUTO', False);
dbIP_PG := Ini.ReadString('DATABASE_PG','IP','192.168.200.199');
dbUser_PG := Ini.ReadString('DATABASE_PG','User','root');
dbPW_PG := Ini.ReadString('DATABASE_PG','PW','54323');
dbSchema_PG := Ini.ReadString('DATABASE_PG','Schema','neol');
dbPort_PG := Ini.ReadInteger('DATABASE_PG','Port',3306);
Alarm_re := Ini.ReadInteger('ALARM_RE','sec',60);
Edit3.Text := IntToStr(Alarm_re);
finally
Ini.Free;
end;
if FileExists(StringReplace(Application.ExeName,'.exe','_list1.ini',[rfReplaceAll])) then
ListBox1.Items.LoadFromFile(StringReplace(Application.ExeName,'.exe','_list1.ini',[rfReplaceAll]));
if FileExists(StringReplace(Application.ExeName,'.exe','_list2.ini',[rfReplaceAll])) then
ListBox2.Items.LoadFromFile(StringReplace(Application.ExeName,'.exe','_list2.ini',[rfReplaceAll]));
if FileExists(StringReplace(Application.ExeName,'.exe','_list3.ini',[rfReplaceAll])) then
ListBox3.Items.LoadFromFile(StringReplace(Application.ExeName,'.exe','_list3.ini',[rfReplaceAll]));
try
GridAddressListTV.DataController.BeginUpdate;
GridAddressListTV.DataController.RecordCount:=0;
finally
GridAddressListTV.DataController.EndUpdate;
end;
try
GridAddressListTV.DataController.BeginUpdate;
for i := 0 to ListBox1.Items.Count - 1 do begin
CK_ROW := 0;
with GridAddressListTV.DataController do begin
CK_ROW := AppendRecord;
Values[CK_ROW, GridAddressListTVColumn1.Index] := ListBox2.Items[i];
Values[CK_ROW, GridAddressListTVColumn2.Index] := ListBox1.Items[i];
Values[CK_ROW, GridAddressListTVColumn3.Index] := '';
Values[CK_ROW, GridAddressListTVColumn4.Index] := '';
Values[CK_ROW, GridAddressListTVColumn5.Index] := '';
Values[CK_ROW, GridAddressListTVColumn6.Index] := ListBox3.Items[i];
Values[CK_ROW, GridAddressListTVColumn7.Index] := '0';
end;
end;
finally
GridAddressListTV.DataController.EndUpdate;
end;
// PG <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if not DB_Connect then begin
Memo1_ADD('['+FormatDateTime('yymmdd hhnnss.zzz',now)+'] Database Connect Error :: PG');
end;
// <20>ڵ<EFBFBD> <20>α<EFBFBD> <20><><EFBFBD><EFBFBD>
if CheckBox1.Checked then Button6.Click;
end;
function TF_LSPLCAgent.DB_Connect:Boolean;
begin
FDPhysPgDriverLink1.VendorLib := '.\libpq-10.dll';
FDConnection1.Connected := False;
FDConnection1.Params.Clear;
FDConnection1.Params.DriverID := 'PG';
FDConnection1.Params.Database := Trim(dbSchema_PG);
FDConnection1.Params.UserName := Trim(dbUser_PG);
FDConnection1.Params.Password := Trim(dbPW_PG);
FDConnection1.Params.Add('Server=' + Trim(dbIP_PG));
FDConnection1.Params.Add('Port=' + Trim(IntToStr(dbPort_PG)));
FDConnection1.Params.Add('CharacterSet=UTF8');
try
FDConnection1.Connected := True;
DB_MainTableCreate;
// DB_MainTableDescriptCreate;
DB_LogTableCreate;
Result := True;
// Memo1_ADD('<27><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>');
// Memo1_ADD('"Q1" <20><>ư<EFBFBD><C6B0> <20><><EFBFBD><EFBFBD> <20><> "<22><><EFBFBD><EFBFBD>" <20><>ư<EFBFBD><C6B0> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>!!');
except
on E: Exception do begin
Result := False;
// Memo1_ADD('<27><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>: ' + E.Message);
end;
end;
end;
procedure TF_LSPLCAgent.DB_Insert;
var
sql, update_sql : string;
i : Integer;
ck_data : Float64;
begin
try
sql := '';
sql := 'INSERT INTO "plc_'+format('%.3d',[PLC_NO])+'" '+
' ( "Idx","CreateDT","plcID"' ;
for i := 0 to GridAddressListTV.DataController.RecordCount - 1 do begin
sql := sql +', "data'+format('%.2d',[i+1])+'"';
end;
sql := sql + ' ) ';
sql := sql + ' VALUES (DEFAULT, '+
'now(),'+
inttostr(PLC_NO) ;
update_sql := '';
update_sql := 'UPDATE "plc_Data" SET ';
with GridAddressListTV.DataController do begin
for i := 0 to RecordCount - 1 do begin
if Trim(Values[i, GridAddressListTVColumn3.Index]) <> '' then begin
if (Values[i, GridAddressListTVColumn6.Index] = 'BIT') then begin
if Values[i, GridAddressListTVColumn3.Index] = 'True' then begin
sql := sql +','+ '1.0';
update_sql := update_sql +
'"data'+format('%.2d',[i+1])+'" = 1.0 , ';
end
else begin
sql := sql +','+ '0.0';
update_sql := update_sql +
'"data'+format('%.2d',[i+1])+'" = 0.0 , ';
end;
end else
if (Values[i, GridAddressListTVColumn6.Index] = 'BIT_A') then begin
if Values[i, GridAddressListTVColumn3.Index] = 'True' then begin
sql := sql +','+ '1.0';
update_sql := update_sql +
'"data'+format('%.2d',[i+1])+'" = 1.0 , ';
end
else begin
sql := sql +','+ '0.0';
update_sql := update_sql +
'"data'+format('%.2d',[i+1])+'" = 0.0 , ';
end;
end else
begin
sql := sql +','+ floattostr(Values[i, GridAddressListTVColumn3.Index]);
update_sql := update_sql +
'"data'+format('%.2d',[i+1])+'" = '+
floattostr(Values[i, GridAddressListTVColumn3.Index])+' , ';
end;
end
else begin
sql := sql +','+ '0.0';
update_sql := update_sql +
'"data'+format('%.2d',[i+1])+'" = 0.0 , ';
end;
end;
end;
sql := sql + ' ) ';
update_sql := update_sql +
'"dev_status"=''<27><><EFBFBD><EFBFBD>'', '+
'"UpdateDT"=now() '+
' WHERE "plcID"='+inttostr(PLC_NO);
insertSQL('<27><><EFBFBD><EFBFBD>',update_sql);
insertSQL('<27>α<EFBFBD>',sql);
Memo1_ADD('['+FormatDateTime('yymmdd hhnnss.zzz',now)+'] DB Update,Insert ok.');
except
on E: Exception do begin
Memo1_ADD('['+FormatDateTime('yymmdd hhnnss.zzz',now)+'] DB_Insert Error : ' + E.Message);
end;
end;
end;
function TF_LSPLCAgent.DB_Close:Boolean;
begin
try
if FDConnection1.Connected then FDConnection1.Connected := False;
Result := True;
except
Result := False;
end;
end;
function TF_LSPLCAgent.DB_MainTableCreate:Boolean;
var
sql : string;
i : integer;
x : Integer;
begin
try
sql := 'CREATE TABLE IF NOT EXISTS "plc_Data" ('+
'"Idx" SERIAL NOT NULL,'+
'"UpdateDT" TIMESTAMP ,'+
'"plcID" INTEGER ,';
for x := 1 to 50 do begin
sql := sql + '"data'+format('%.2d',[x])+'" REAL ,';
end;
sql := sql +
'"MachCode" VARCHAR(20) ,' +
'"devName" VARCHAR(50) ,' +
'"dev_status" VARCHAR(10) ,' +
'CONSTRAINT plc_Data_pkey PRIMARY KEY ("Idx"));';
{
'"data01" REAL ,'+
'"data02" REAL ,'+
'"data03" REAL ,'+
'"data04" REAL ,'+
'"data05" REAL ,'+
'"data06" REAL ,'+
'"data07" REAL ,'+
'"data08" REAL ,'+
'"data09" REAL ,'+
'"data10" REAL ,'+
'"data11" REAL ,'+
'"data12" REAL ,'+
'"data13" REAL ,'+
'"data14" REAL ,'+
'"data15" REAL ,'+
'"data16" REAL ,'+
'"data17" REAL ,'+
'"data18" REAL ,'+
'"data19" REAL ,'+
'"data20" REAL ,'+
'"data21" REAL ,'+
'"data22" REAL ,'+
'"data23" REAL ,'+
'"data24" REAL ,'+
'"data25" REAL ,'+
'"data26" REAL ,'+
'"data27" REAL ,'+
'"data28" REAL ,'+
'"data29" REAL ,'+
'"data30" REAL ,'+
'CONSTRAINT plc_Data_pkey PRIMARY KEY ("Idx"));';
}
insertSQL('<27><><EFBFBD><EFBFBD>',sql);
if not FDConnection1.Connected then FDConnection1.Connected := True;
if FDConnection1.Connected then
begin
FDQuery2.Close;
FDQuery2.SQL.Clear;
FDQuery2.SQL.Text := 'SELECT * FROM "plc_Data" WHERE "plcID"='+IntToStr(PLC_NO);
FDQuery2.Open;
if FDQuery2.RecordCount <= 0 then
begin
sql := '';
sql := 'INSERT INTO "plc_Data" ' +
'VALUES (DEFAULT, '+
'now(), '+
inttostr(PLC_NO)+ ' ' ;
for i := 0 to 49 do begin
sql := sql +','+ '0.0';
end;
sql := sql + ' ) ';
insertSQL('<27>ʱ<EFBFBD>',sql);
end;
end;
except
on E: Exception do begin
Memo1_ADD('DB_MainTableCreate Error : ' + E.Message);
end;
end;
end;
function TF_LSPLCAgent.DB_MainTableDescriptCreate:Boolean;
var
sql : string;
i : integer;
begin
exit;
try
sql := 'CREATE TABLE IF NOT EXISTS "plc_Data_Desc" ('+
'"Idx" SERIAL NOT NULL,'+
'"UpdateDT" TIMESTAMP ,'+
'"plcID" INTEGER ,'+
'"fieldname" VARCHAR(50) ,'+
'"address" VARCHAR(50) ,'+
'"addressDescription" VARCHAR(200) ,'+
'CONSTRAINT plc_Data_Desc_pkey PRIMARY KEY ("Idx"));';
insertSQL('<27><><EFBFBD><EFBFBD>',sql);
{
if not FDConnection1.Connected then FDConnection1.Connected := True;
if FDConnection1.Connected then
begin
FDQuery2.Close;
FDQuery2.SQL.Clear;
FDQuery2.SQL.Text := ' SELECT * FROM "plc_Data_Desc" '+
' WHERE "plcID" = '+IntToStr(PLC_NO)+
' and "address" = '''+'*****'+'''';
FDQuery2.Open;
if FDQuery2.RecordCount <= 0 then
begin
sql := '';
sql := 'INSERT INTO "plc_Data_Desc" ' +
'VALUES (DEFAULT, '+
'now(), '+
inttostr(PLC_NO)+
' '''+'*****'+''', '+
' '''+'*****'+''', '+
' '''+'*****'+'''); ';
insertSQL(sql);
end;
end;
}
except
on E: Exception do begin
Memo1_ADD('DB_MainTableDescriptCreate Error : ' + E.Message);
end;
end;
end;
function TF_LSPLCAgent.DB_LogTableCreate:Boolean;
var
sql : string;
x : integer;
begin
try
sql := 'CREATE TABLE IF NOT EXISTS "plc_'+format('%.3d',[PLC_NO])+'" ('+
'"Idx" SERIAL NOT NULL,'+
'"CreateDT" TIMESTAMP ,'+
'"plcID" INTEGER ,';
for x := 1 to 50 do begin
sql := sql + '"data'+format('%.2d',[x])+'" REAL ,';
end;
sql := sql + 'CONSTRAINT plc_'+format('%.3d',[PLC_NO])+'_pkey PRIMARY KEY ("Idx"));';
{
'"data01" REAL ,'+
'"data02" REAL ,'+
'"data03" REAL ,'+
'"data04" REAL ,'+
'"data05" REAL ,'+
'"data06" REAL ,'+
'"data07" REAL ,'+
'"data08" REAL ,'+
'"data09" REAL ,'+
'"data10" REAL ,'+
'"data11" REAL ,'+
'"data12" REAL ,'+
'"data13" REAL ,'+
'"data14" REAL ,'+
'"data15" REAL ,'+
'"data16" REAL ,'+
'"data17" REAL ,'+
'"data18" REAL ,'+
'"data19" REAL ,'+
'"data20" REAL ,'+
'"data21" REAL ,'+
'"data22" REAL ,'+
'"data23" REAL ,'+
'"data24" REAL ,'+
'"data25" REAL ,'+
'"data26" REAL ,'+
'"data27" REAL ,'+
'"data28" REAL ,'+
'"data29" REAL ,'+
'"data30" REAL ,'+
'"data30" REAL ,'+
'"data30" REAL ,'+
'"data30" REAL ,'+
'"data30" REAL ,'+
'"data30" REAL ,'+
'"data30" REAL ,'+
'"data30" REAL ,'+
'"data30" REAL ,'+
'"data30" REAL ,'+
'"data30" REAL ,'+
'"data30" REAL ,'+
'"data30" REAL ,'+
'"data30" REAL ,'+
'"data30" REAL ,'+
'"data30" REAL ,'+
'"data30" REAL ,'+
'"data30" REAL ,'+
'"data30" REAL ,'+
'"data30" REAL ,'+
'"data30" REAL ,'+
'CONSTRAINT plc_'+format('%.3d',[PLC_NO])+'_pkey PRIMARY KEY ("Idx"));';
}
insertSQL('<27><><EFBFBD><EFBFBD>',sql);
except
on E: Exception do begin
Memo1_ADD('DB_LogTableCreate Error : ' + E.Message);
end;
end;
end;
end.