SmartFactory_NEOL/SOURCE/Agent,Kiosk/NEOL_GTWYAgent_D104_PG/uGtwyAgent.pas
2026-09-04 14:08:41 +09:00

1809 lines
56 KiB
ObjectPascal
Raw Permalink 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 uGtwyAgent;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, cxGraphics, cxControls, cxLookAndFeels,
cxLookAndFeelPainters, cxStyles, cxCustomData, cxFilter, cxData,
cxDataStorage, cxEdit, cxNavigator, dxDateRanges, dxScrollbarAnnotations,
Vcl.StdCtrls, Vcl.ExtCtrls, cxGridLevel, cxGridCustomTableView,
cxGridTableView, cxClasses, cxGridCustomView, cxGrid, Vcl.ComCtrls,
IniFiles, System.JSON, uMQTTComps, System.StrUtils, uMQTT, global,
System.Generics.Collections, 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, Data.DB,
FireDAC.Comp.DataSet, FireDAC.Comp.Client, cxTextEdit,
Calibration,
System.Net.URLClient, System.Net.HttpClientComponent, System.Net.HttpClient,
system.DateUtils, system.Hash, System.NetEncoding,
AlarmLog, RegisterClasses_base, empmst, cxCurrencyEdit,
MachineMst, FireDAC.Comp.ScriptCommands, FireDAC.Stan.Util,
FireDAC.Comp.Script;
type
TSMSOptions = record
// ToNumber: string;
ToNumber: TStrings;
FromNumber: string;
Text: string;
end;
type
TfGtwyAgent = class(TForm)
PageControl1: TPageControl;
TabSheet1: TTabSheet;
TabSheet2: TTabSheet;
TabSheet3: TTabSheet;
cxGrid_GTWY: TcxGrid;
cxGrid_GTWY_Tv: TcxGridTableView;
cxGrid_GTWY_TvColumn0: TcxGridColumn;
cxGrid_GTWY_TvColumn1: TcxGridColumn;
cxGrid_GTWY_TvColumn2: TcxGridColumn;
cxGrid_GTWY_TvColumn3: TcxGridColumn;
cxGrid_GTWY_TvColumn4: TcxGridColumn;
cxGrid_GTWY_TvColumn5: TcxGridColumn;
cxGrid_GTWY_Lv: TcxGridLevel;
Memo1: TMemo;
Splitter1: TSplitter;
Memo2: TMemo;
GroupBox1: TGroupBox;
Edit1: TEdit;
Edit2: TEdit;
Edit3: TEdit;
Edit4: TEdit;
Edit5: TEdit;
GroupBox2: TGroupBox;
Edit6: TEdit;
Edit7: TEdit;
Edit8: TEdit;
Label1: TLabel;
Label2: TLabel;
Label3: TLabel;
Label4: TLabel;
Edit9: TEdit;
Edit10: TEdit;
Label5: TLabel;
Label6: TLabel;
Label7: TLabel;
Label8: TLabel;
Label9: TLabel;
Label10: TLabel;
Button3: TButton;
Button4: TButton;
MQTTClient1: TMQTTClient;
Panel1: TPanel;
CheckBox1: TCheckBox;
CheckBox2: TCheckBox;
FDConnection1: TFDConnection;
FDQuery1: TFDQuery;
FDPhysPgDriverLink1: TFDPhysPgDriverLink;
FDGUIxWaitCursor1: TFDGUIxWaitCursor;
TabSheet4: TTabSheet;
GroupBox3: TGroupBox;
Label11: TLabel;
Label12: TLabel;
Label13: TLabel;
Label14: TLabel;
cxGrid1: TcxGrid;
cxGridTableView1: TcxGridTableView;
cxGridColumn1: TcxGridColumn;
cxGridColumn2: TcxGridColumn;
cxGridColumn3: TcxGridColumn;
cxGridColumn4: TcxGridColumn;
cxGridLevel1: TcxGridLevel;
Edit11: TEdit;
Edit12: TEdit;
Edit13: TEdit;
Edit14: TEdit;
Button1: TButton;
Button2: TButton;
cxGrid_GTWY_TvColumn6: TcxGridColumn;
cxGrid_GTWY_TvColumn7: TcxGridColumn;
cxGrid_GTWY_TvColumn8: TcxGridColumn;
cxGrid_GTWY_TvColumn9: TcxGridColumn;
cxGridColumn5: TcxGridColumn;
cxGridColumn6: TcxGridColumn;
cxGridColumn7: TcxGridColumn;
cxGridColumn8: TcxGridColumn;
Label19: TLabel;
Edit18: TEdit;
Label20: TLabel;
Edit19: TEdit;
Label21: TLabel;
Label22: TLabel;
Edit20: TEdit;
Edit21: TEdit;
cxGridColumn9: TcxGridColumn;
cxGridColumn10: TcxGridColumn;
cxGridColumn11: TcxGridColumn;
Label15: TLabel;
Edit15: TEdit;
Label16: TLabel;
Label17: TLabel;
Edit16: TEdit;
Edit17: TEdit;
TrayIcon1: TTrayIcon;
cxGridColumn12: TcxGridColumn;
cxGridColumn13: TcxGridColumn;
Edit22: TEdit;
Edit23: TEdit;
Label18: TLabel;
Edit24: TEdit;
cxGridColumn14: TcxGridColumn;
TabSheet5: TTabSheet;
cxGrid2: TcxGrid;
cxGridTableView2: TcxGridTableView;
cxGridLevel2: TcxGridLevel;
Panel2: TPanel;
GroupBox4: TGroupBox;
Label23: TLabel;
Label24: TLabel;
Label25: TLabel;
Edit25: TEdit;
Edit26: TEdit;
Edit27: TEdit;
GroupBox5: TGroupBox;
Label26: TLabel;
Edit28: TEdit;
DateTimePicker1: TDateTimePicker;
Label28: TLabel;
DateTimePicker2: TDateTimePicker;
Label29: TLabel;
Button7: TButton;
GroupBox6: TGroupBox;
Edit30: TEdit;
Button9: TButton;
Memo3: TMemo;
Edit31: TEdit;
Label30: TLabel;
Edit32: TEdit;
Memo4: TMemo;
Memo5: TMemo;
RadioButton1: TRadioButton;
RadioButton2: TRadioButton;
CheckBox3: TCheckBox;
Edit33: TEdit;
Label31: TLabel;
Label32: TLabel;
Label33: TLabel;
RadioGroup1: TRadioGroup;
cxGrid3: TcxGrid;
cxGridTableView3: TcxGridTableView;
cxGridLevel3: TcxGridLevel;
cxGridTableView3Column1: TcxGridColumn;
cxGridTableView3Column2: TcxGridColumn;
cxGridTableView3Column3: TcxGridColumn;
cxGridTableView3Column4: TcxGridColumn;
cxGridTableView2Column1: TcxGridColumn;
cxGridTableView2Column2: TcxGridColumn;
cxGridTableView2Column3: TcxGridColumn;
cxGridTableView2Column4: TcxGridColumn;
cxGridTableView2Column5: TcxGridColumn;
cxGridTableView2Column6: TcxGridColumn;
cxGridTableView2Column7: TcxGridColumn;
cxGridTableView2Column8: TcxGridColumn;
cxGridTableView2Column9: TcxGridColumn;
RadioGroup2: TRadioGroup;
Button5: TButton;
GroupBox7: TGroupBox;
Label27: TLabel;
Edit29: TEdit;
Button8: TButton;
cxGridColumn15: TcxGridColumn;
Label35: TLabel;
Edit34: TEdit;
cxGridColumn16: TcxGridColumn;
FDScript1: TFDScript;
procedure Button4Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
procedure MQTTClient1ClientID(Sender: TObject; var aClientID: UTF8String);
procedure MQTTClient1EnableChange(Sender: TObject);
procedure MQTTClient1Failure(Sender: TObject; aReason: Integer;
var CloseClient: Boolean);
procedure MQTTClient1Mon(Sender: TObject; aStr: string);
procedure MQTTClient1Msg(Sender: TObject; aTopic: UTF8String;
aMessage: AnsiString; aQos: TMQTTQOSType; aRetained: Boolean);
procedure MQTTClient1Offline(Sender: TObject; Graceful: Boolean);
procedure MQTTClient1Online(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure cxGridColumn2CustomDrawCell(Sender: TcxCustomGridTableView;
ACanvas: TcxCanvas; AViewInfo: TcxGridTableDataCellViewInfo;
var ADone: Boolean);
procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
procedure TrayIcon1DblClick(Sender: TObject);
procedure cxGridTableView1FocusedRecordChanged(
Sender: TcxCustomGridTableView; APrevFocusedRecord,
AFocusedRecord: TcxCustomGridRecord;
ANewItemRecordFocusingChanged: Boolean);
procedure Button9Click(Sender: TObject);
procedure RadioButton2Click(Sender: TObject);
procedure Button7Click(Sender: TObject);
procedure Button5Click(Sender: TObject);
procedure Button8Click(Sender: TObject);
private
inipath, deviceSettingpath : string;
FsmsObj: TSMSOptions;
procedure ini_Save;
procedure ini_Load;
procedure LoadTableViewFromFile(ATableView: TcxGridTableView;
const AFileName: string);
procedure SaveTableViewToFile(ATableView: TcxGridTableView;
const AFileName: string);
procedure PrintLog(msg, msgType: string);
function SmoothAdcValue(gtwy,AI_NO,NewValue: Integer): Integer;
function tempset_v2(gtwy,AI_NO,RawAdc:Integer):string;
function TempCalibration(gtwy,AI_NO:Integer; temp: string): string;
procedure AppEvtMinimize(Sender: TObject);
procedure devRefresh;
procedure insertSQL(sql: string);
function xGenerateHMACSHA256(const Key, Data: string): string;
function xSendSMS(const Options: TSMSOptions; const ServiceId, AccessKey,
SecretKey: string): string;
function qCreateGetUniqueString(clsName: string): string;
procedure EmgAlarmlistrefresh;
function AlarmSend(devName, temp_limit, temp_curr: string):Boolean;
procedure CreateTabledevtemp_log(dev_idxno: integer);
function Get_devtemp_idxNo: integer;
function Alarm_use_CK: Boolean;
{ Private declarations }
public
{ Public declarations }
aQos: TMQTTQOSType;
GTWY_ID_List : TList<Integer>;
GTWY_TOPIC_List : TList<string>;
procedure MQTTParsing(data : AnsiString; aTopic : String);
function DB_Connect:Boolean;
function DB_Close:Boolean;
function MQTT_Connect:Boolean;
end;
const
FILTER_SIZE = 10; // <20>ֱ<EFBFBD> 10<31><30> <20><><EFBFBD><EFBFBD>
var
fGtwyAgent: TfGtwyAgent;
AdcIndexBuffer: array[0..3,0..3] of Integer;
AdcBuffer: array[0..3,0..3,0..FILTER_SIZE-1] of Integer;
AdcIndex: Integer = 0;
Alarm_re: Integer;
Alarm_use: Boolean;
implementation
uses uTempCalc_Custom, TemperatureConverter;
const
METHOD = 'POST';
CONTENT_TYPE = 'application/json; charset=utf-8';
COUNTRY_CODE = '82';
{$R *.dfm}
function TfGtwyAgent.SmoothAdcValue(gtwy,AI_NO,NewValue: Integer): Integer;
var
i, Sum: Integer;
AdcIndex : integer;
begin
AdcIndex := AdcIndexBuffer[gtwy,AI_NO];
AdcBuffer[gtwy,AI_NO,AdcIndex] := NewValue;
AdcIndexBuffer[gtwy,AI_NO] := (AdcIndexBuffer[gtwy,AI_NO] + 1) mod FILTER_SIZE;
// AdcIndex := (AdcIndex + 1) mod FILTER_SIZE;
Sum := 0;
for i := 0 to FILTER_SIZE-1 do
Sum := Sum + AdcBuffer[gtwy,AI_NO,i];
Result := Round(Sum / FILTER_SIZE);
end;
function TfGtwyAgent.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
printlog('Database Connect Error :: '+e.Message, 'SYS');
end;
end;
end;
procedure TfGtwyAgent.Button1Click(Sender: TObject);
var
row : integer;
x, devtemp_idxno : Integer;
sql : string;
begin
if FDConnection1.Connected then begin
if (Trim(edit12.Text) <> '') and (Trim(edit14.Text) <> '') then begin
FDQuery1.Close;
FDQuery1.SQL.Clear;
FDQuery1.SQL.Text := ' SELECT * FROM "devtemp_info" '+
' WHERE "gatewayID"='+edit12.Text+
' AND "AIPortNo"='+edit14.Text+
' AND "isDeleted" = false ';
FDQuery1.Open;
end
else begin
ShowMessage('GTWY ID / AI Port No[0..3] <20>׸<EFBFBD><D7B8><EFBFBD> Ȯ<><C8AE><EFBFBD>ϼ<EFBFBD><CFBC><EFBFBD>!');
exit;
end;
if FDQuery1.RecordCount> 0 then
begin
if MessageBox(handle, '<27><><EFBFBD><EFBFBD> <20>Ͻðڽ<C3B0><DABD>ϱ<EFBFBD>?', '<27><><EFBFBD><EFBFBD> <20>Ͻðڽ<C3B0><DABD>ϱ<EFBFBD>?', MB_OKCANCEL) = ID_OK then begin
sql := '';
sql := 'UPDATE "devtemp_info" SET '+
'"deviceNAME" = '''+Edit11.Text+''', '+
'"gatewayID" = ' +Edit12.Text+', '+
'"mqttTOPIC" = '''+Edit13.Text+''', '+
'"AIPortNo" = ' +Edit14.Text+', '+
'"tempMAX" = ' +Edit18.Text+', '+
'"tempMIN" = ' +Edit34.Text+', '+
'"x_1" = ' +Edit19.Text+', '+
'"x_2" = ' +Edit20.Text+', '+
'"x_3" = ' +Edit21.Text+', '+
'"y_1" = ' +Edit15.Text+', '+
'"y_2" = ' +Edit16.Text+', '+
'"y_3" = ' +Edit17.Text+', '+
'"tempalarmMax" = ' +Edit24.Text+', '+
'"MachCode" = '''+Edit23.Text+''' '+
' WHERE "gatewayID"='+edit12.Text+
' AND "AIPortNo" ='+edit14.Text+
' AND "isDeleted" = false ; ';
insertSQL(sql);
devRefresh;
end;
end
else begin
if MessageBox(handle, '<27><><EFBFBD>ο<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>߰<EFBFBD><DFB0>Ͻðڽ<C3B0><DABD>ϱ<EFBFBD>?', '<27>߰<EFBFBD><DFB0>Ͻðڽ<C3B0><DABD>ϱ<EFBFBD>?', MB_OKCANCEL) = ID_OK then begin
sql := '';
sql := 'INSERT INTO devtemp_info VALUES(DEFAULT, '+
''''+Edit11.Text+''', '+
''+Edit12.Text+', '+
''''+Edit13.Text+''', '+
''+Edit14.Text+', '+
''+Edit18.Text+', '+
''+Edit19.Text+', '+
''+Edit20.Text+', '+
''+Edit21.Text+', '+
''+Edit15.Text+', '+
''+Edit16.Text+', '+
''+Edit17.Text+', '+
'0, '+
'NULL, '+
''+Edit24.Text+', '+
'now(), '+
'false,'+
''+Edit34.Text+
') ; ';
insertSQL(sql);
devtemp_idxno := Get_devtemp_idxNo;
if devtemp_idxno > 0 then CreateTabledevtemp_log(devtemp_idxno);
devRefresh;
end;
end;
end;
end;
function TfGtwyAgent.Get_devtemp_idxNo: integer;
begin
result := 0;
try
if not FDConnection1.Connected then FDConnection1.Connected := True;
if FDConnection1.Connected then
begin
FDQuery1.Close;
FDQuery1.SQL.Clear;
FDQuery1.SQL.Text := ' SELECT * FROM "devtemp_info" '+
' WHERE "gatewayID" = '+edit12.Text+
' AND "AIPortNo" = '+edit14.Text+
' AND "deviceNAME" = '''+edit11.Text+''''+
' AND "isDeleted" = false ';
FDQuery1.Open;
if FDQuery1.RecordCount> 0 then
begin
result := FDQuery1.FieldByName('idxNo').AsInteger;
end;
end;
except
on e : exception do
begin
printlog('Database Connect Error :: '+e.Message, 'SYS');
end;
end;
end;
procedure TfGtwyAgent.insertSQL(sql:string);
begin
try
if not FDConnection1.Connected then FDConnection1.Connected := True;
if FDConnection1.Connected then
begin
FDQuery1.ResourceOptions.DirectExecute := True;
FDQuery1.Active := false;
FDQuery1.SQL.Clear;
FDQuery1.SQL.Add(sql);
FDQuery1.ExecSQL;
end;
except
on e : exception do
begin
printlog('[insertSQL()]Database Connect Error :: '+e.Message, 'SYS');
end;
end;
end;
procedure TfGtwyAgent.Button2Click(Sender: TObject);
var
sql : string;
begin
if FDConnection1.Connected then begin
if MessageBox(handle, '<27><><EFBFBD><EFBFBD> <20>Ͻðڽ<C3B0><DABD>ϱ<EFBFBD>?', '<27><><EFBFBD><EFBFBD> <20>Ͻðڽ<C3B0><DABD>ϱ<EFBFBD>?', MB_OKCANCEL) = ID_OK then begin
sql := '';
{
sql := ' DELETE FROM "devtemp_info" '+
' WHERE "idxNo"='+edit22.Text+
' AND "gatewayID"='+edit12.Text+
' AND "AIPortNo" ='+edit14.Text;
}
sql := ' UPDATE "devtemp_info" SET '+
' "isDeleted" = true, '+
' "UpdateDT" = now()'+
' WHERE "idxNo"='+edit22.Text+
' AND "gatewayID"='+edit12.Text+
' AND "AIPortNo" ='+edit14.Text+
' ; ';
insertSQL(sql);
devRefresh;
end;
end;
{
with cxGridTableView1.DataController do begin
if FocusedRecordIndex >= 0 then begin
BeginUpdate;
try
DeleteSelection
finally
EndUpdate;
end;
end;
end;
}
end;
procedure TfGtwyAgent.Button3Click(Sender: TObject);
begin
Close;
end;
procedure TfGtwyAgent.Button4Click(Sender: TObject);
begin
ini_Save;
end;
procedure TfGtwyAgent.Button5Click(Sender: TObject);
begin
EmgAlarmlistrefresh;
end;
procedure TfGtwyAgent.CreateTabledevtemp_log(dev_idxno : integer);
var
sql : string;
begin
sql := '';
// PostgreSQL <20><><EFBFBD>̺<EFBFBD> <20><><EFBFBD><EFBFBD>
sql := 'CREATE TABLE IF NOT EXISTS "devtemp_'+format('%.5d',[dev_idxno])+'" ('+
'"aNo" SERIAL NOT NULL ,'+
'"MachCode" VARCHAR(20) ,'+
'"gatewayID" INTEGER ,'+
'"AIPortNo" INTEGER ,'+
'"TempC" REAL ,'+
'"lastUpdate" TIMESTAMP ,'+
'"RawAdc" INTEGER ,'+
'"SmoothedAdc" INTEGER ,'+
'CONSTRAINT devtemp_'+format('%.5d',[dev_idxno])+'_pkey PRIMARY KEY ("aNo"));';
insertSQL(sql);
end;
procedure TfGtwyAgent.Button7Click(Sender: TObject);
var
alarmlog : Talarmlog;
tmpList : TList;
row, x : integer;
ck_status : string;
begin
try
tmpList := TList.Create;
alarmlog := Talarmlog.Create(Self);
ck_status:= '';
if RadioGroup2.ItemIndex > 0 then ck_status:= RadioGroup2.Items[RadioGroup2.ItemIndex];
tmpList := alarmlog.xGetObjsAlarmList(FDQuery1,ck_status,'','',FormatDateTime('yyyy-mm-dd',DateTimePicker1.Date),FormatDateTime('yyyy-mm-dd',DateTimePicker2.Date));
with cxGridTableView2.DataController do begin
try
BeginUpdate;
RecordCount := 0;
finally
EndUpdate;
end;
end;
for x := 0 to tmpList.Count-1 do begin
alarmlog := tmpList.Items[x];
with cxGridTableView2.DataController do begin
try
BeginUpdate;
row := AppendRecord;
Values[row,cxGridTableView2Column1.Index] := alarmlog.MachType;
Values[row,cxGridTableView2Column2.Index] := alarmlog.MachName;
Values[row,cxGridTableView2Column3.Index] := alarmlog.CreateDate;
Values[row,cxGridTableView2Column4.Index] := alarmlog.CreateTime;
Values[row,cxGridTableView2Column5.Index] := alarmlog.AlarmStatus;
Values[row,cxGridTableView2Column6.Index] := alarmlog.SendMsgDate;
Values[row,cxGridTableView2Column7.Index] := alarmlog.SendMsgTime;
Values[row,cxGridTableView2Column8.Index] := alarmlog.SendMsgEmp;
Values[row,cxGridTableView2Column9.Index] := alarmlog.SendMsg;
finally
EndUpdate;
end;
end;
end;
finally
tmpList.free;
end;
end;
procedure TfGtwyAgent.Button8Click(Sender: TObject);
var
ini : TIniFile;
begin
Ini := TIniFile.Create(inipath);
try
if Trim(Edit29.Text) <> '' then
Alarm_re := strtoint(Edit29.Text)
else
Alarm_re := 60;
//Alarm_use := RadioButton5.Checked;
Ini.WriteInteger('ALARM_RE','sec',Alarm_re);
// Ini.WriteBool('ALARM','use',Alarm_use);
finally
Ini.Free;
end;
{
try
ini := TInifile.Create(inipath);
with ini do
begin
WriteString('serverDB','IP', edit1.Text);
WriteString('serverDB','PORT', edit2.Text);
WriteString('serverDB','User', edit3.Text);
WriteString('serverDB','Pass', edit4.Text);
WriteString('serverDB','Schema',edit5.Text);
WriteString('MQTTBroker','IP', edit6.Text);
WriteString('MQTTBroker','PORT', edit7.Text);
WriteString('MQTTBroker','ClientID',edit8.Text);
WriteString('MQTTBroker','UserID', edit9.Text);
WriteString('MQTTBroker','UserPASS',edit10.Text);
end;
finally
ini.Free;
end;
}
end;
function TfGtwyAgent.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 TfGtwyAgent.RadioButton2Click(Sender: TObject);
begin
if RadioButton1.Checked then begin
Memo3.Clear;
Memo3.Lines.Add('[<5B>׿<EFBFBD>]');
Memo3.Lines.Add('%s');
Memo3.Lines.Add('<27>Ӱ谪 %s<><73> / <20><><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 ] <20>µ<EFBFBD><C2B5>̻<EFBFBD> <20><><EFBFBD><EFBFBD>');
Memo3.Lines.Add('<27>Ӱ谪 [ %s <20><> ] / <20><><EFBFBD><EFBFBD> <20>µ<EFBFBD><C2B5><EFBFBD> [ %s <20><> ]');
Memo3.Lines.Add('https://neol.co.kr');
end;
end;
procedure TfGtwyAgent.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 TfGtwyAgent.AlarmSend(devName,temp_limit,temp_curr:string):Boolean;
var
i: Integer;
Response, pID, aKey, sKey: string;
sql : string;
ToNum : string;
ToNumlist : TStringList;
begin
Result := False;
EmgAlarmlistrefresh;
Alarm_use := Alarm_use_CK;
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
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
FsmsObj.Text := Format(Memo3.Text, [devName,temp_curr,temp_limit]);
end
else begin
FsmsObj.Text := '[<5B>˶<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>] '+Format(Memo3.Text, [devName,temp_curr,temp_limit]);
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
Response := xSendSMS(FsmsObj, pID, aKey, sKey);
end
else begin
Response := '<27>˶<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>';
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);
sql := '';
sql := 'INSERT INTO "AlarmLog" VALUES( '+
''''+''+''', '+
''''+qCreateGetUniqueString('AlarmLog')+''', '+
''''+'AlarmLog'+''', '+
''''+FormatDateTime('yyyy-mm-dd',Now)+''', '+
''''+FormatDateTime('hh:nn:ss.zzzzzz',Now)+''', '+
''''+'GtwyAgent'+''', '+
''''+'t'+''', '+
''''+'Working'+''', '+
''''+devName+''', '+
''''+<><C5BB>'+''', '+
''''+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)+''', ';
if StrToFloat(temp_curr) > StrToFloat(temp_limit) then begin
sql := sql + ''''+'<27>µ<EFBFBD><C2B5>̻<EFBFBD>'+''', '+
''''+'<27><>/<2F><>/<2F>ɰ<EFBFBD>'+''', '+
''''+'<27>߻<EFBFBD>'+''', '+
'NULL '+
');';
end
else begin
sql := sql + ''''+'<27>µ<EFBFBD><C2B5><EFBFBD><EFBFBD><EFBFBD>'+''', '+
''''+'<27><>/<2F><>/<2F>ɰ<EFBFBD>'+''', '+
''''+'<27>Ϸ<EFBFBD>'+''', '+
'NULL '+
');';
end;
insertSQL(sql);
Result := True;
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;
Result := False;
end;
except
on e : exception do
begin
printlog('AlarmSend Error :: '+e.Message, 'SYS');
end;
end;
finally
ToNumlist.Free;
end;
end;
procedure TfGtwyAgent.Button9Click(Sender: TObject);
begin
AlarmSend(Edit30.Text,Edit31.Text,Edit33.Text); // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> / <20>Ӱ谪 / <20><><EFBFBD>
end;
function TfGtwyAgent.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 TfGtwyAgent.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 TfGtwyAgent.cxGridColumn2CustomDrawCell(
Sender: TcxCustomGridTableView; ACanvas: TcxCanvas;
AViewInfo: TcxGridTableDataCellViewInfo; var ADone: Boolean);
begin
ACanvas.Font.Color := $000000EA;
end;
procedure TfGtwyAgent.cxGridTableView1FocusedRecordChanged(
Sender: TcxCustomGridTableView; APrevFocusedRecord,
AFocusedRecord: TcxCustomGridRecord; ANewItemRecordFocusingChanged: Boolean);
begin
if Assigned(AFocusedRecord) then
with cxGridTableView1.DataController do begin
Edit11.Text := Values[AFocusedRecord.RecordIndex,cxGridColumn1.Index];
Edit12.Text := Values[AFocusedRecord.RecordIndex,cxGridColumn2.Index];
Edit13.Text := Values[AFocusedRecord.RecordIndex,cxGridColumn3.Index];
Edit14.Text := Values[AFocusedRecord.RecordIndex,cxGridColumn4.Index];
Edit18.Text := Values[AFocusedRecord.RecordIndex,cxGridColumn5.Index];
Edit34.Text := Values[AFocusedRecord.RecordIndex,cxGridColumn16.Index];
Edit19.Text := Values[AFocusedRecord.RecordIndex,cxGridColumn6.Index];
Edit20.Text := Values[AFocusedRecord.RecordIndex,cxGridColumn7.Index];
Edit21.Text := Values[AFocusedRecord.RecordIndex,cxGridColumn8.Index];
Edit15.Text := Values[AFocusedRecord.RecordIndex,cxGridColumn9.Index];
Edit16.Text := Values[AFocusedRecord.RecordIndex,cxGridColumn10.Index];
Edit17.Text := Values[AFocusedRecord.RecordIndex,cxGridColumn11.Index];
Edit24.Text := Values[AFocusedRecord.RecordIndex,cxGridColumn14.Index];
Edit22.Text := Values[AFocusedRecord.RecordIndex,cxGridColumn12.Index];
Edit23.Text := Values[AFocusedRecord.RecordIndex,cxGridColumn13.Index];
end;
end;
function TfGtwyAgent.TempCalibration(gtwy,AI_NO:Integer; temp: string): string;
var
x : Integer;
Calib: TCalibration;
xValues, yValues: TArray<Double>;
inputTemperature, correctedTemperature: Double;
use_ck : Boolean;
begin
// <20>µ<EFBFBD><C2B5><EFBFBD>2(xValues)<29><> <20>µ<EFBFBD><C2B5><EFBFBD>1(yValues)<29><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
use_ck := false;
with cxGridTableView1.DataController do begin
for x := 0 to RecordCount-1 do begin
if (Values[x,cxGridColumn2.Index]=gtwy) and
(Values[x,cxGridColumn4.Index]=AI_NO) then begin
xValues := [Values[x,cxGridColumn6.Index], Values[x,cxGridColumn7.Index], Values[x,cxGridColumn8.Index]]; // <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>µ<EFBFBD>
yValues := [Values[x,cxGridColumn9.Index], Values[x,cxGridColumn10.Index], Values[x,cxGridColumn11.Index]]; // <20><><EFBFBD><EFBFBD> <20>µ<EFBFBD>
use_ck := true;
Break;
end;
end;
end;
try
if use_ck then begin
if (xValues[0]=0) or (xValues[0]=0) or (xValues[0]=0) or
(yValues[0]=0) or (yValues[0]=0) or (yValues[0]=0) then begin
result := temp;
end
else begin
// TCalibration <20><>ü <20><><EFBFBD><EFBFBD> <20><> <20>ʱ<EFBFBD>ȭ
Calib := TCalibration.Create(xValues, yValues);
try
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>Է<EFBFBD> <20>ޱ<EFBFBD>
inputTemperature := StrToFloatDef(temp,0);
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD>
correctedTemperature := Calib.Calibrate(inputTemperature);
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
result := Trim(Format('%14.1f',[correctedTemperature]));
finally
Calib.Free;
end;
end;
end
else begin
result := temp;
end;
except
on e : exception do
begin
printlog('TempCalibration_1 Error :: '+e.Message, 'SYS');
end;
// on E: Exception do
// Writeln(E.ClassName, ': ', E.Message);
end;
end;
function TfGtwyAgent.tempset_v2(gtwy,AI_NO,RawAdc:Integer):string;
var
ActualTemperature: Double;
SmoothedAdc: Integer;
Temp_s, devTemp_machcode:string;
TempMax, TempMin : integer;
devTemp_idxNo : Integer;
dev_use_ck : Boolean;
Temp_Limit: Double;
x, dev_use_row : integer;
sql : string;
begin
SmoothedAdc := SmoothAdcValue(gtwy,AI_NO,RawAdc); // <20>̵<EFBFBD><CCB5><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
if SmoothedAdc > 1 then begin
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>, ADC <20><><EFBFBD><EFBFBD> 383 (<28><><EFBFBD><EFBFBD> <20>߰<EFBFBD><DFB0><EFBFBD>)<29>̶<EFBFBD><CCB6><EFBFBD> <20><><EFBFBD><EFBFBD>
// CurrentADC := 383;
dev_use_ck := false; Temp_Limit := 0; dev_use_row := -1; devTemp_machcode := '';
for x := 0 to cxGridTableView1.DataController.RecordCount-1 do begin
if (cxGridTableView1.DataController.Values[x,cxGridColumn2.Index]=gtwy) and
(cxGridTableView1.DataController.Values[x,cxGridColumn4.Index]=AI_NO) then begin
TempMax := cxGridTableView1.DataController.Values[x,cxGridColumn5.Index];
TempMin := cxGridTableView1.DataController.Values[x,cxGridColumn16.Index];
Temp_Limit := cxGridTableView1.DataController.Values[x,cxGridColumn14.Index];
devTemp_machcode := cxGridTableView1.DataController.Values[x,cxGridColumn13.Index];
devTemp_idxNo := cxGridTableView1.DataController.Values[x,cxGridColumn12.Index];
dev_use_row := x;
dev_use_ck := true;
Break;
end;
end;
ActualTemperature := ConvertADCToTemperature(SmoothedAdc,TempMin,TempMax);
// <20><><EFBFBD><EFBFBD>: <20><> 849.67 <20><>
// ShowMessage(Format('ADC Value: %d -> Actual Temperature: %.2f', [SmoothedAdc, ActualTemperature]));
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> K1 <20><><EFBFBD><EFBFBD>Ŀ<EFBFBD><C4BF><EFBFBD>̹Ƿ<CCB9> <20>Ҽ<EFBFBD><D2BC><EFBFBD> <20><><EFBFBD><EFBFBD> ó<><C3B3><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><EFBFBD><E4B1B8><EFBFBD>׿<EFBFBD> <20><><EFBFBD><EFBFBD> <20>ݿø<DDBF><C3B8>Ͽ<EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>.
Temp_s := TempCalibration(gtwy,AI_NO,Format('%.2f', [ActualTemperature]));
try // <20>˶<EFBFBD> <20><><EFBFBD><EFBFBD>
// Alarm_use := Alarm_use_CK;
// if Alarm_use and (Temp_Limit > 0) then begin
if Temp_Limit > 0 then begin // <20>˶<EFBFBD><CBB6><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>϶<EFBFBD><CFB6><EFBFBD> <20>޼<EFBFBD><DEBC><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>̾<EFBFBD><CCBE>µ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
if Temp_Limit < StrToFloat(Temp_s) then begin
with cxGridTableView1.DataController do begin
try
BeginUpdate;
if (Values[dev_use_row, cxGridColumn15.Index] = 0) or (Values[dev_use_row, cxGridColumn15.Index] >= Alarm_re) then begin
// AlarmSend(Edit30.Text,Edit31.Text,Edit33.Text); // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> / <20>Ӱ谪 / <20><><EFBFBD>
if AlarmSend(Values[dev_use_row, cxGridColumn1.Index]+' <20>µ<EFBFBD> <20>̻<EFBFBD>',Format('%.2f', [Temp_Limit]),Temp_s) then begin
Values[dev_use_row, cxGridColumn15.Index] := 1;
end
else begin
Values[dev_use_row, cxGridColumn15.Index] := Values[dev_use_row, cxGridColumn15.Index] + 1;
end;
end
else begin
Values[dev_use_row, cxGridColumn15.Index] := Values[dev_use_row, cxGridColumn15.Index] + 1;
end;
finally
EndUpdate;
end;
end;
end
else begin
with cxGridTableView1.DataController do begin
if Values[dev_use_row, cxGridColumn15.Index] > 0 then
if AlarmSend(Values[dev_use_row, cxGridColumn1.Index]+' <20>µ<EFBFBD> <20><><EFBFBD><EFBFBD>',Format('%.2f', [Temp_Limit]),Temp_s) then begin
Values[dev_use_row, cxGridColumn15.Index] := 0;
end
end;
end;
end;
except
on e : exception do
begin
printlog('Alarm Error :: '+e.Message, 'SYS');
end;
end;
try
if dev_use_ck then begin
if FDConnection1.Connected then begin
sql := '';
sql := ' UPDATE "devtemp_info" SET '+
' "tempCurr" = ''' +Temp_s+''', '+
' "UpdateDT" = now()'+
' WHERE "gatewayID"='+IntToStr(gtwy)+
' AND "AIPortNo" ='+IntToStr(AI_NO)+
' AND "isDeleted" = false ; '+
' INSERT INTO "devtemp_'+format('%.5d',[devTemp_idxNo])+'" VALUES(DEFAULT, '+
' '''+devTemp_machcode+''', '+
' '+IntToStr(gtwy)+', '+
' '+IntToStr(AI_NO)+', '+
' '+Temp_s+', '+
' now(), '+
' '+IntToStr(RawAdc)+', '+
' '+IntToStr(SmoothedAdc)+
' ) ; ';
insertSQL(sql);
end;
end;
Except
on e : exception do
begin
printlog('Database Update Error :: '+e.Message, 'SYS');
end;
end;
Result := IntToStr(SmoothedAdc)+'/'+Temp_s;
end
else begin
Result := 'OFF';
end;
end;
procedure TfGtwyAgent.TrayIcon1DblClick(Sender: TObject);
begin
TrayIcon1.Visible := False;
Show;
WindowState := wsNormal;
Application.BringToFront;
end;
procedure TfGtwyAgent.FormClose(Sender: TObject; var Action: TCloseAction);
begin
CheckBox1.Checked := False;
CheckBox2.Checked := False;
try
MQTTClient1.Activate(false);
except
end;
try
if FDConnection1.Connected then FDConnection1.Close;
except
end;
try
GTWY_ID_List.Free;
GTWY_TOPIC_List.Free;
except
end;
end;
procedure TfGtwyAgent.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
case MessageBox(handle, '"<22><>(Y)"<22><> Ŭ<><C5AC><EFBFBD>ϸ<EFBFBD>, MQTT Client for GTWY Agent<6E><74> Ʈ<><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>. ', 'MQTT Client for GTWY Agent :: Ʈ<><C6AE><EFBFBD>̷<EFBFBD> <20>ּ<EFBFBD>ȭ <20>ұ<EFBFBD><D2B1><EFBFBD>?', MB_YESNOCANCEL) of
ID_YES : begin
CanClose := false;
TrayIcon1.BalloonTitle := 'MQTT Client for GTWY 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_CANCEL : begin
CanClose := false;
end;
end;//case..
end;
procedure TfGtwyAgent.AppEvtMinimize(Sender: TObject);
begin
Hide;
WindowState := wsMinimized;
TrayIcon1.Visible := True;
TrayIcon1.Animate := True;
TrayIcon1.ShowBalloonHint;
end;
procedure TfGtwyAgent.FormCreate(Sender: TObject);
var
x : Integer;
begin
DateTimePicker1.DateTime := Now;
DateTimePicker2.DateTime := Now;
inipath := ExtractFilePath(Application.ExeName)+'GtwyAgent.ini';
deviceSettingpath := ExtractFilePath(Application.ExeName)+'GtwyAgent_device.dat';
ini_Load;
FillChar(AdcBuffer, SizeOf(AdcBuffer), 0);
FillChar(AdcIndexBuffer, SizeOf(AdcIndexBuffer), 0);
GTWY_ID_List := TList<Integer>.Create;
GTWY_TOPIC_List := TList<string>.Create;
GTWY_TOPIC_List.Clear;
try
if DB_Connect then
printlog('DB Connected', 'SYS')
else
printlog('DB Connect Fail', 'SYS');
except
on e : exception do
begin
printlog('DB Connect Error :: '+e.Message, 'SYS');
end;
end;
try
if MQTT_Connect then
printlog('MQTT Connected', 'SYS')
else
printlog('MQTT Connect Fail', 'SYS');
except
on e : exception do
begin
printlog('MQTT Connect Error :: '+e.Message, 'SYS');
end;
end;
devRefresh;
if cxGridTableView1.DataController.RecordCount > 0 then begin
for x := 0 to cxGridTableView1.DataController.RecordCount-1 do begin
GTWY_TOPIC_List.Add(cxGridTableView1.DataController.Values[x,cxGridColumn3.Index]);
end;
end;
end;
procedure TfGtwyAgent.devRefresh;
var
row : integer;
begin
with cxGridTableView1.DataController do begin
try
BeginUpdate;
RecordCount := 0;
finally
EndUpdate;
end;
end;
if FDConnection1.Connected then begin
FDQuery1.Close;
FDQuery1.SQL.Clear;
FDQuery1.SQL.Text := 'SELECT * FROM "devtemp_info" WHERE "isDeleted" = false ';
FDQuery1.Open;
if FDQuery1.RecordCount> 0 then
begin
FDQuery1.First;
while not FDQuery1.Eof do begin
with cxGridTableView1.DataController do begin
try
BeginUpdate;
row := AppendRecord;
Values[row,cxGridColumn1.Index] := FDQuery1.FieldByName('deviceNAME').asString;
Values[row,cxGridColumn2.Index] := FDQuery1.FieldByName('gatewayID').asString;
Values[row,cxGridColumn3.Index] := FDQuery1.FieldByName('mqttTOPIC').asString;
Values[row,cxGridColumn4.Index] := FDQuery1.FieldByName('AIPortNo').asString;
Values[row,cxGridColumn5.Index] := StrToIntDef(FDQuery1.FieldByName('tempMAX').asString, 0);
Values[row,cxGridColumn16.Index] := StrToIntDef(FDQuery1.FieldByName('tempMIN').asString, 0);
Values[row,cxGridColumn6.Index] := StrToIntDef(FDQuery1.FieldByName('x_1').asString, 0);
Values[row,cxGridColumn7.Index] := StrToIntDef(FDQuery1.FieldByName('x_2').asString, 0);
Values[row,cxGridColumn8.Index] := StrToIntDef(FDQuery1.FieldByName('x_3').asString, 0);
Values[row,cxGridColumn9.Index] := StrToIntDef(FDQuery1.FieldByName('y_1').asString, 0);
Values[row,cxGridColumn10.Index] := StrToIntDef(FDQuery1.FieldByName('y_2').asString, 0);
Values[row,cxGridColumn11.Index] := StrToIntDef(FDQuery1.FieldByName('y_3').asString, 0);
Values[row,cxGridColumn14.Index] := StrToIntDef(FDQuery1.FieldByName('tempalarmMax').asString, 0);
Values[row,cxGridColumn12.Index] := FDQuery1.FieldByName('idxNo').asString;
Values[row,cxGridColumn13.Index] := FDQuery1.FieldByName('MachCode').asString;
Values[row,cxGridColumn15.Index] := 0;
finally
EndUpdate;
end;
end;
FDQuery1.Next;
end;
end;
end;
end;
procedure TfGtwyAgent.ini_Save;
var
ini : TIniFile;
begin
try inipath := ExtractFilePath(Application.ExeName)+'GtwyAgent.ini';
ini := TInifile.Create(inipath);
with ini do
begin
WriteString('serverDB','IP', edit1.Text);
WriteString('serverDB','PORT', edit2.Text);
WriteString('serverDB','User', edit3.Text);
WriteString('serverDB','Pass', edit4.Text);
WriteString('serverDB','Schema',edit5.Text);
WriteString('MQTTBroker','IP', edit6.Text);
WriteString('MQTTBroker','PORT', edit7.Text);
WriteString('MQTTBroker','ClientID',edit8.Text);
WriteString('MQTTBroker','UserID', edit9.Text);
WriteString('MQTTBroker','UserPASS',edit10.Text);
end;
finally
ini.Free;
end;
end;
procedure TfGtwyAgent.ini_Load;
var
ini : TIniFile;
begin
if FileExists(inipath) then
begin
ini := TInifile.Create(inipath);
with ini do
begin
edit1.Text := ReadString('serverDB','IP','');
edit2.Text := ReadString('serverDB','PORT','');
edit3.Text := ReadString('serverDB','User','');
edit4.Text := ReadString('serverDB','Pass','');
edit5.Text := ReadString('serverDB','Schema','');
edit6.Text := ReadString('MQTTBroker','IP','');
edit7.Text := ReadString('MQTTBroker','PORT','');
edit8.Text := ReadString('MQTTBroker','ClientID','');
edit9.Text := ReadString('MQTTBroker','UserID','');
edit10.Text := ReadString('MQTTBroker','UserPASS','');
Alarm_re := Ini.ReadInteger('ALARM_RE','sec',60);
Edit29.Text := IntToStr(Alarm_re);
end;
ini.Free;
end;
// LoadTableViewFromFile(cxGridTableView1,deviceSettingpath);
end;
procedure TfGtwyAgent.SaveTableViewToFile(ATableView: TcxGridTableView; const AFileName: string);
var
JSONArray: TJSONArray;
RowObj: TJSONObject;
Row, Col: Integer;
JSONText: TStringList;
ValueStr: string;
begin
JSONArray := TJSONArray.Create;
try
// <20><><EFBFBD><EFBFBD> Row <20>ݺ<EFBFBD>
for Row := 0 to ATableView.DataController.RecordCount - 1 do
begin
RowObj := TJSONObject.Create;
for Col := 0 to ATableView.ColumnCount - 1 do
begin
ValueStr := VarToStr(ATableView.DataController.Values[Row, ATableView.Columns[Col].Index]);
RowObj.AddPair(ATableView.Columns[Col].Name, ValueStr);
end;
JSONArray.AddElement(RowObj);
end;
JSONText := TStringList.Create;
try
JSONText.Text := JSONArray.Format(2); // <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><EFBFBD><E9BFA9><EFBFBD><EFBFBD>
JSONText.SaveToFile(AFileName, TEncoding.UTF8);
finally
JSONText.Free;
end;
finally
JSONArray.Free;
end;
end;
procedure TfGtwyAgent.LoadTableViewFromFile(ATableView: TcxGridTableView; const AFileName: string);
var
JSONArray: TJSONArray;
RowObj: TJSONObject;
Row, Col: Integer;
JSONStr: TStringList;
JSONVal: TJSONValue;
ColName, ColValue: string;
ValueObj: TJSONValue;
begin
if not FileExists(AFileName) then Exit;
JSONStr := TStringList.Create;
try
JSONStr.LoadFromFile(AFileName, TEncoding.UTF8);
JSONVal := TJSONObject.ParseJSONValue(JSONStr.Text);
try
if not (JSONVal is TJSONArray) then Exit;
JSONArray := TJSONArray(JSONVal);
ATableView.DataController.RecordCount := JSONArray.Count;
for Row := 0 to JSONArray.Count - 1 do
begin
RowObj := JSONArray.Items[Row] as TJSONObject;
for Col := 0 to ATableView.ColumnCount - 1 do
begin
ColName := ATableView.Columns[Col].Name;
ValueObj := RowObj.GetValue(ColName);
if Assigned(ValueObj) then
begin
ColValue := ValueObj.Value;
ATableView.DataController.Values[Row, ATableView.Columns[Col].Index] := ColValue;
end;
end;
end;
finally
JSONVal.Free;
end;
finally
JSONStr.Free;
end;
end;
procedure TfGtwyAgent.MQTTClient1ClientID(Sender: TObject;
var aClientID: UTF8String);
begin
PrintLog('ClientID :: ' + aClientID, 'SYS');
end;
procedure TfGtwyAgent.MQTTClient1EnableChange(Sender: TObject);
begin
if TMQTTClient(Sender).Enabled then
printlog('Client is enabled.', 'SYS')
else
printlog('Client is disabled.', 'SYS');
end;
procedure TfGtwyAgent.MQTTClient1Failure(Sender: TObject; aReason: Integer;
var CloseClient: Boolean);
begin
printlog('---- Failure Reported ' + FailureNames(aReason), 'SYS');
end;
procedure TfGtwyAgent.MQTTClient1Mon(Sender: TObject; aStr: string);
begin
printlog(aStr, 'SYS');
end;
procedure TfGtwyAgent.MQTTClient1Msg(Sender: TObject; aTopic: UTF8String;
aMessage: AnsiString; aQos: TMQTTQOSType; aRetained: Boolean);
begin
try
if (LeftStr(aMessage,1)='{') and (RightStr(aMessage,1)='}') then
begin
PrintLog('Topic : '+Utf8ToAnsi(aTopic)+', Msg='+aMessage, 'mqtt');
MQTTParsing(aMessage,Utf8ToAnsi(aTopic));
end else
begin
PrintLog('[Not Entry]Topic : '+Utf8ToAnsi(aTopic), 'DEBUG');
end;
except
on e : exception do
begin
printlog('MQTTClient1Msg Error :: '+e.Message, 'SYS');
end;
end;
end;
procedure TfGtwyAgent.MQTTClient1Offline(Sender: TObject; Graceful: Boolean);
begin
if Graceful then
begin
printlog('Client Gracefully Disconnected.', 'SYS');
end
else
begin
printlog('Client Terminated Unexpectedly.', 'SYS');
end;
end;
procedure TfGtwyAgent.MQTTClient1Online(Sender: TObject);
var
s: TStringList;
x : Integer;
begin
printlog('Client is online.', 'SYS');
s := TStringList.Create;
if GTWY_TOPIC_List.Count > 0 then begin
for x := 0 to GTWY_TOPIC_List.Count-1 do
s.AddObject(GTWY_TOPIC_List[x], TObject(aQos));
end;
MQTTClient1.Subscribe(s);
s.Free;
end;
procedure TfGtwyAgent.PrintLog(msg, msgType : string);
var
f : TextFile;
log: TStringList;
i : integer;
logfile, buf : string;
begin
if msgType = 'mqtt' then begin
if CheckBox1.Checked then begin
while Memo2.Lines.Count > 100 do begin
Memo2.Lines.Delete(0);
end;
Memo2.Lines.Add(FormatDateTime('yyyy-mm-dd hh:nn:ss :: ',now)+msg);
end;
end
else begin
if CheckBox1.Checked or (msgType = 'SYS') then begin
while Memo1.Lines.Count > 100 do begin
Memo1.Lines.Delete(0);
end;
Memo1.Lines.Add(FormatDateTime('yyyy-mm-dd hh:nn:ss :: ',now)+msg);
end;
end;
if CheckBox2.Checked or (msgType = 'SYS') then begin
logfile := '';
logfile := ExtractFilePath(Application.ExeName)+'log\GTWYAgent_'+formatdatetime('yyyymmddhh',now())+'.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 :: ',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 :: ',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;
end;
procedure TfGtwyAgent.MQTTParsing(data : AnsiString; aTopic : String);
var
tempTopic_list, tempAI_list : TStringList;
AI_01, AI_02, AI_03, AI_04 : Single;
gtwyID, x : integer;
tempAI : string;
grid_rowck : integer;
ck1,ck2 : string;
str_list : TStringList;
JSONObject: TJSONObject;
begin
try
if Trim(data) <> '' then
begin
// InsertData(aTopic, data);
try
tempTopic_list := TStringList.Create;
tempAI_list := TStringList.create;
// JSON <20><><EFBFBD>ڿ<EFBFBD><DABF><EFBFBD> TJSONObject<63><74> <20>Ľ<EFBFBD>
JSONObject := TJSONObject.ParseJSONValue(data) as TJSONObject;
Strsplit('/',aTopic, tempTopic_list);
if tempTopic_list.Count>3 then
begin
gtwyID := StrToIntDef(tempTopic_list.Strings[ tempTopic_list.Count-1 ], 0);
grid_rowck := GTWY_ID_List.IndexOf(gtwyID);
if (gtwyID > 0) and (gtwyID <= 4) then
begin
if JSONObject.GetValue('AI') <> nil then begin
tempAI := JSONObject.GetValue('AI').Value;
Strsplit('|',tempAI, tempAI_list);
grid_rowck := -1;
// if PageControl1.TabIndex = 0 then
with cxGrid_GTWY_Tv.DataController do begin
for x := 0 to RecordCount-1 do begin
if Values[x,cxGrid_GTWY_TvColumn0.Index] = gtwyID then
grid_rowck := x;
end;
if grid_rowck < 0 then begin
grid_rowck := AppendRecord;
end;
try
BeginUpdate;
Values[grid_rowck,cxGrid_GTWY_TvColumn0.Index] := gtwyID;
Values[grid_rowck,cxGrid_GTWY_TvColumn1.Index] := FormatDateTime('yymmdd hhnnss',Now);
str_list := TStringList.Create;
str_list.Delimiter := '/';
str_list.DelimitedText := tempset_v2(gtwyID,0,StrToIntDef(tempAI_list.Strings[0],0));
if str_list.DelimitedText <> 'OFF' then begin
Values[grid_rowck,cxGrid_GTWY_TvColumn2.Index] := str_list.Strings[0];
Values[grid_rowck,cxGrid_GTWY_TvColumn6.Index] := str_list.Strings[1];
end
else begin
Values[grid_rowck,cxGrid_GTWY_TvColumn2.Index] := 'OFF';
Values[grid_rowck,cxGrid_GTWY_TvColumn6.Index] := 'OFF';
end;
str_list.DelimitedText := tempset_v2(gtwyID,1,StrToIntDef(tempAI_list.Strings[1],0));
if str_list.DelimitedText <> 'OFF' then begin
Values[grid_rowck,cxGrid_GTWY_TvColumn3.Index] := str_list.Strings[0];
Values[grid_rowck,cxGrid_GTWY_TvColumn7.Index] := str_list.Strings[1];
end
else begin
Values[grid_rowck,cxGrid_GTWY_TvColumn3.Index] := 'OFF';
Values[grid_rowck,cxGrid_GTWY_TvColumn7.Index] := 'OFF';
end;
str_list.DelimitedText := tempset_v2(gtwyID,2,StrToIntDef(tempAI_list.Strings[2],0));
if str_list.DelimitedText <> 'OFF' then begin
Values[grid_rowck,cxGrid_GTWY_TvColumn4.Index] := str_list.Strings[0];
Values[grid_rowck,cxGrid_GTWY_TvColumn8.Index] := str_list.Strings[1];
end
else begin
Values[grid_rowck,cxGrid_GTWY_TvColumn4.Index] := 'OFF';
Values[grid_rowck,cxGrid_GTWY_TvColumn8.Index] := 'OFF';
end;
str_list.DelimitedText := tempset_v2(gtwyID,3,StrToIntDef(tempAI_list.Strings[3],0));
if str_list.DelimitedText <> 'OFF' then begin
Values[grid_rowck,cxGrid_GTWY_TvColumn5.Index] := str_list.Strings[0];
Values[grid_rowck,cxGrid_GTWY_TvColumn9.Index] := str_list.Strings[1];
end
else begin
Values[grid_rowck,cxGrid_GTWY_TvColumn5.Index] := 'OFF';
Values[grid_rowck,cxGrid_GTWY_TvColumn9.Index] := 'OFF';
end;
{
Values[grid_rowck,cxGrid_GTWY_TvColumn2.Index] := tempAI_list.Strings[0];
Values[grid_rowck,cxGrid_GTWY_TvColumn3.Index] := tempAI_list.Strings[1];
Values[grid_rowck,cxGrid_GTWY_TvColumn4.Index] := tempAI_list.Strings[2];
Values[grid_rowck,cxGrid_GTWY_TvColumn5.Index] := tempAI_list.Strings[3];
Values[grid_rowck,cxGrid_GTWY_TvColumn6.Index] := tempset_v1(gtwyID,0,StrToIntDef(tempAI_list.Strings[0],0));
Values[grid_rowck,cxGrid_GTWY_TvColumn7.Index] := tempset_v1(gtwyID,1,StrToIntDef(tempAI_list.Strings[1],0));
Values[grid_rowck,cxGrid_GTWY_TvColumn8.Index] := tempset_v1(gtwyID,2,StrToIntDef(tempAI_list.Strings[2],0));
Values[grid_rowck,cxGrid_GTWY_TvColumn9.Index] := tempset_v1(gtwyID,3,StrToIntDef(tempAI_list.Strings[3],0));
}
{ 2025-11-14 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>ӽ<EFBFBD> <20><><EFBFBD><EFBFBD>
if StrToIntDef(tempAI_list.Strings[0],0) > 3 then
Values[grid_rowck,cxGrid_GTWY_TvColumn6.Index] := tempset(gtwyID,0,StrToInt(tempAI_list.Strings[0]))
else
Values[grid_rowck,cxGrid_GTWY_TvColumn6.Index] := 'OFF';
if StrToIntDef(tempAI_list.Strings[1],0) > 3 then
Values[grid_rowck,cxGrid_GTWY_TvColumn7.Index] := tempset(gtwyID,1,StrToInt(tempAI_list.Strings[1]))
else
Values[grid_rowck,cxGrid_GTWY_TvColumn7.Index] := 'OFF';
if StrToIntDef(tempAI_list.Strings[2],0) > 3 then
Values[grid_rowck,cxGrid_GTWY_TvColumn8.Index] := tempset(gtwyID,2,StrToInt(tempAI_list.Strings[2]))
else
Values[grid_rowck,cxGrid_GTWY_TvColumn8.Index] := 'OFF';
if StrToIntDef(tempAI_list.Strings[3],0) > 3 then
Values[grid_rowck,cxGrid_GTWY_TvColumn9.Index] := tempset(gtwyID,3,StrToInt(tempAI_list.Strings[3]))
else
Values[grid_rowck,cxGrid_GTWY_TvColumn9.Index] := 'OFF';
}
finally
EndUpdate;
end;
end;
end;
end;
end;
finally
tempTopic_list.Free;
tempAI_list.Free;
JSONObject.Free;
end;
end;
except
on e : exception do
begin
printlog('MQTTParsing Error :: '+e.Message, 'SYS');
end;
end;
end;
function TfGtwyAgent.DB_Connect:Boolean;
begin
try
FDPhysPgDriverLink1.VendorLib := '.\libpq-10.dll';
FDConnection1.Connected := False;
FDConnection1.Params.Clear;
FDConnection1.Params.DriverID := 'PG';
FDConnection1.Params.Database := Trim(Edit5.Text);
FDConnection1.Params.UserName := Trim(Edit3.Text);
FDConnection1.Params.Password := Trim(Edit4.Text);
FDConnection1.Params.Add('Server=' + Trim(Edit1.Text));
FDConnection1.Params.Add('Port=' + Trim(Edit2.Text));
FDConnection1.Params.Add('CharacterSet=UTF8');
FDConnection1.Connected := True;
Result := True;
// Memo1.Lines.Add('<27><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>');
// Memo1.Lines.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.Lines.Add('DB <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>: ' + e.Message);
end;
end;
end;
function TfGtwyAgent.DB_Close:Boolean;
begin
try
if FDConnection1.Connected then FDConnection1.Connected := False;
Result := True;
except
Result := False;
end;
end;
function TfGtwyAgent.MQTT_Connect: Boolean;
begin
try
Result := False;
MQTTClient1.Activate(false);
Sleep(300);
randomize();
MQTTClient1.ClientID := Trim(Edit8.Text)+'_'+inttostr(random(999999));
MQTTClient1.Host := Trim(Edit6.Text);
MQTTClient1.Port := StrToInt(Trim(Edit7.Text));
MQTTClient1.Username := Trim(Edit9.Text);
MQTTClient1.Password := Trim(Edit10.Text);
MQTTClient1.Activate(true);
Result := True;
except
on E: Exception do begin
Result := False;
Memo1.Lines.Add('MQTT <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>: ' + E.Message);
end;
end;
end;
end.