SmartFactory_NEOL/SOURCE/NILM_Viewer_D104_PostgreSQL/uMain.pas
2026-09-04 14:06:10 +09:00

461 lines
12 KiB
ObjectPascal

unit uMain;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, uMQTTComps, StdCtrls, Grids, BaseGrid, AdvGrid, uMQTT,
ExtCtrls, DateUtils, ComCtrls, Menus, ScktComp, inifiles,
Buttons, MQTT, DB, VclTee.TeeGDIPlus,
VCLTee.TeEngine, VCLTee.Series, VCLTee.TeeProcs, VCLTee.Chart,
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;
type
TfrmMain = class(TForm)
initTimer: TTimer;
StatusBar1: TStatusBar;
MainMenu1: TMainMenu;
ListBox1: TListBox;
File2: TMenuItem;
ProgramExit1: TMenuItem;
N3: TMenuItem;
CONFIG1: TMenuItem;
NILM2: TMenuItem;
Device1: TMenuItem;
N1: TMenuItem;
Panel1: TPanel;
TreeView1: TTreeView;
Splitter1: TSplitter;
Panel2: TPanel;
Timer1: TTimer;
MQTTClient1: TMQTTClient;
Chart_main: TChart;
FDConnection1: TFDConnection;
FDQuery1: TFDQuery;
FDPhysPgDriverLink1: TFDPhysPgDriverLink;
FDGUIxWaitCursor1: TFDGUIxWaitCursor;
procedure initTimerTimer(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure ProgramExit1Click(Sender: TObject);
procedure CONFIG1Click(Sender: TObject);
procedure NILM2Click(Sender: TObject);
procedure Device1Click(Sender: TObject);
procedure TreeView1Click(Sender: TObject);
procedure Timer1Timer(Sender: TObject);
private
{ Private declarations }
Series1: TLineSeries; // 전력량 데이터를 저장할 라인 시리즈
Series2: TLineSeries; // 전력량 데이터를 저장할 라인 시리즈
Series3: TLineSeries; // 전력량 데이터를 저장할 라인 시리즈
Series4: TLineSeries; // 전력량 데이터를 저장할 라인 시리즈
Series5: TLineSeries; // 전력량 데이터를 저장할 라인 시리즈
select_nilmID, select_nilm_idxNo : integer;
FMaxPoints: Integer; // 차트에 표시할 최대 데이터 포인트 수
procedure InitializeChart;
public
//read_gwid : integer;
fNILM : array [1..max_gw] of TNILM;
appPath : string;
hubPort : integer;
dbIP, dbPW, dbUser, dbSchema, mqtt_topic, ClientID : string;
dbIP_PG, dbUser_PG, dbPW_PG, dbSchema_PG : string;
dbPort, dbPort_PG, brokerPort : integer;
brokerIP, mqtt_user, mqtt_pw : string;
old_NilmID : integer;
procedure PrintLog(msg : String);
procedure ClearIOTGW();
procedure insertSQL(sql : string);
procedure ShowNilmTreeView();
function DB_Connect:Boolean;
function DB_Close:Boolean;
end;
var
frmMain: TfrmMain;
no : Double;
implementation
{$R *.dfm}
uses global, uConfigMQTT, uConfigNILM, uDevConfig, math;
procedure TfrmMain.ClearIOTGW();
var
p, i : integer;
begin
for p:=1 to max_gw do
begin
fNILM[p].idxNo := 0;
fNILM[p]._TOPIC := '';
fNILM[p]._NAME := '';
for i:=1 to 3 do
begin
fNILM[p]._VALUE.PF[i] := 0.0;
fNILM[p]._VALUE.Vrms[i] := 0.0;
fNILM[p]._VALUE.Irms[i] := 0.0;
fNILM[p]._VALUE._Var[i] := 0.0;
fNILM[p]._VALUE.Va[i] := 0.0;
fNILM[p]._VALUE.Pwr[i] := 0.0;
fNILM[p]._VALUE.Gyro[i] := 0.0;
fNILM[p]._VALUE.Accel[i] := 0.0;
end;
fNILM[p]._VALUE.TempC := 0;
fNILM[p].rcvCount := 0;
fNILM[p].oldRcvCount := 0;
end;
end;
procedure TfrmMain.ShowNilmTreeView();
var
nilmID : integer;
subNode : TTreenode;
begin
TreeView1.Items.Clear;
for nilmID:=1 to max_gw do
begin
if fNILM[nilmID].idxNo> 0 then
begin
subNode := TreeView1.Items.AddChild(nil, format('%.5d',[nilmID]));
TreeView1.items.AddChild(subNode, 'IDXNO:'+inttostr(fNILM[nilmID].idxNo));
TreeView1.items.AddChild(subNode, 'NAME :'+fNILM[nilmID]._NAME);
TreeView1.items.AddChild(subNode, 'TOPIC:'+fNILM[nilmID]._TOPIC);
end;
end;
end;
procedure TfrmMain.PrintLog(msg : string);
begin
if ListBox1.Items.Count >= 300 then ListBox1.Items.Clear;
ListBox1.Items.Insert(0, FormatDateTime('hh:nn:ss :: ',now)+msg);
end;
procedure TfrmMain.initTimerTimer(Sender: TObject);
var
ini : TInifile;
pwd : string;
begin
// FANTrend1.SetItem(1, 'PF', clLime, 1, 0);
// FANTrend1.SetItem(2, 'Vrms', clYellow, 300, 0);
// FANTrend1.SetItem(3, 'Irms', clSkyBlue, 10, 0);
// FANTrend1.SetItem(4, 'Pwr', clRed, 5000, 0);
{
Series1.Clear;
Series2.Clear;
Series3.Clear;
Series4.Clear;
Series5.Clear;
}
old_NilmID := 0;
ListBox1.Clear;
mqtt_topic := '';
mqtt_topic := 'QST/NILM/LVDT/#';
pwd := '';
pwd := appPath+'NILM_Manager.ini';
if FileExists(pwd) then
begin
ini := TInifile.Create(pwd);
with ini do
begin
mqtt_topic := ReadString('MQTT','TOPIC',mqtt_topic);
brokerIP := ReadString('MQTT','BrokerIP','183.111.125.203');
brokerPort := ReadInteger('MQTT','BrokerPort',1883);
ClientID := ReadString('MQTT','ClientID','NILM_1st');
mqtt_user := ReadString('MQTT','User','qsentech');
mqtt_pw := ReadString('MQTT','Password','qsentech!1233');
dbIP := ReadString('DATABASE','IP','192.168.200.199');
dbUser := ReadString('DATABASE','User','root');
dbPW := ReadString('DATABASE','PW','1233');
dbSchema := ReadString('DATABASE','Schema','nilm');
dbPort := ReadInteger('DATABASE','Port',3306);
dbIP_PG := ReadString('DATABASE_PG','IP','192.168.200.199');
dbUser_PG := ReadString('DATABASE_PG','User','root');
dbPW_PG := ReadString('DATABASE_PG','PW','54323');
dbSchema_PG := ReadString('DATABASE_PG','Schema','neol');
dbPort_PG := ReadInteger('DATABASE_PG','Port',3306);
hubPort := ReadInteger('MQTT_HUB','Port',6969);
end;
ini.Free;
end;
// PG 서버접속
if not DB_Connect then begin
printlog('Database Connect Error :: PG');
end;
frmNILM.ShowNILM();
frmDevConfig.ShowDev();
ShowNilmTreeView();
Timer1.Enabled := True;
initTimer.Enabled := false;
end;
function TfrmMain.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;
Result := True;
// Memo1.Lines.Add('연결 성공');
// Memo1.Lines.Add('"Q1" 버튼을 누른 후 "쿼리" 버튼을 누르세요!!');
except
on E: Exception do begin
Result := False;
// Memo1.Lines.Add('연결 실패: ' + E.Message);
end;
end;
end;
function TfrmMain.DB_Close:Boolean;
begin
try
if FDConnection1.Connected then FDConnection1.Connected := False;
Result := True;
except
Result := False;
end;
end;
procedure TfrmMain.FormCreate(Sender: TObject);
begin
appPath := '';
appPath := ExtractFilePath(Application.ExeName);
ClearIOTGW();
FMaxPoints := 30; // 차트에 100개의 데이터 포인트만 표시
// 차트 초기화 함수 호출
InitializeChart;
end;
procedure TfrmMain.InitializeChart;
var
ck : Integer;
begin
// 기존 시리즈가 있다면 모두 제거
Chart_Main.SeriesList.Clear;
Series1 := TLineSeries.Create(Self);
Series2 := TLineSeries.Create(Self);
Series3 := TLineSeries.Create(Self);
Series4 := TLineSeries.Create(Self);
Series5 := TLineSeries.Create(Self);
// 라인 시리즈 추가
Chart_Main.AddSeries(Series1);
Chart_Main.AddSeries(Series2);
Chart_Main.AddSeries(Series3);
Chart_Main.AddSeries(Series4);
// 시리즈 설정
Series1.Title := '실시간 PF';
Series1.Color := clBlue; // 선 색상
Series1.LinePen.Width := 1; // 선 두께
Series1.Pointer.Visible := False; // 포인트 표시 여부 (선만 보려면 False)
// 시리즈 설정
Series2.Title := '실시간 Vrms';
Series2.Color := clGray; // 선 색상
Series2.LinePen.Width := 1; // 선 두께
Series2.Pointer.Visible := False; // 포인트 표시 여부 (선만 보려면 False)
// 시리즈 설정
Series3.Title := '실시간 Irms';
Series3.Color := clGreen; // 선 색상
Series3.LinePen.Width := 1; // 선 두께
Series3.Pointer.Visible := False; // 포인트 표시 여부 (선만 보려면 False)
// 시리즈 설정
Series4.Title := '실시간 Pwr';
Series4.Color := clRed; // 선 색상
Series4.LinePen.Width := 1; // 선 두께
Series4.Pointer.Visible := False; // 포인트 표시 여부 (선만 보려면 False)
// 차트 축 설정
Chart_Main.Axes.Bottom.Title.Caption := '시간';
Chart_Main.Axes.Left.Title.Caption := 'PF / Vrms / Irms / Pwr';
Chart_Main.Axes.Left.Minimum := 0; // 최소값 설정 (필요에 따라 조절)
Chart_Main.Axes.Left.Maximum := 100; // 최대값 설정 (필요에 따라 조절)
Chart_Main.Axes.Bottom.DateTimeFormat := 'mm:ss'; // 시간 포맷 설정
// 차트 제목
Chart_Main.Title.Text.Text := '실시간 (PF / Vrms / Irms / Pwr) 모니터링';
Chart_Main.Title.Visible := True;
// 범례 표시
Chart_Main.Legend.Visible := True;
// 애니메이션 효과 (선택 사항)
// Chart1.Options.ClipSeries := False; // 스크롤링 시 부드러운 움직임
for ck := 0 to FMaxPoints-1 do begin
Series1.AddXY(ck, 0, '', clBlue); // x: 시간, y: PF
Series2.AddXY(ck, 0, '', clGray); // x: 시간, y: Vrms
Series3.AddXY(ck, 0, '', clGreen); // x: 시간, y: Irms
Series4.AddXY(ck, 0, '', clRed); // x: 시간, y: Pwr
end;
no := FMaxPoints;
end;
procedure TfrmMain.insertSQL(sql : string);
begin
end;
procedure TfrmMain.ProgramExit1Click(Sender: TObject);
begin
frmMain.Close;
end;
procedure TfrmMain.CONFIG1Click(Sender: TObject);
begin
frmConfigMQTT.Show;
end;
procedure TfrmMain.NILM2Click(Sender: TObject);
begin
frmNILM.Show;
end;
procedure TfrmMain.Device1Click(Sender: TObject);
begin
frmDevConfig.Show;
end;
procedure TfrmMain.TreeView1Click(Sender: TObject);
var
str1, str : string;
li : LongInt;
sub : TTreeNode;
begin
if TreeView1.Selected = nil then exit;
str := TreeView1.Selected.Text;
Statusbar1.Panels.Items[0].text := str;
if Pos(':', str)<= 0 then
begin
select_nilmID := StrTointDef(str, 0);
end;
if TreeView1.Selected.HasChildren then
begin
sub := TreeView1.Selected.getFirstChild;
str := sub.Text;
str1 := Copy(str, Pos(':', str)+1, Length(str)-Pos(':', str));
select_nilm_idxNo := StrTointDef(str1, 0);
printlog(str1);
end;
end;
procedure TfrmMain.Timer1Timer(Sender: TObject);
var
vPF, vVrms, vIrms, vPwr : single;
IntvPF, IntvVrms, IntvIrms, IntvPwr : Integer;
strlist : TStringList;
y_maxvalue : Double;
begin
if select_nilmID<= 0 then exit;
try
// try
// finally
// if frmMain.ZConnection1.Connected then frmMain.ZConnection1.Disconnect;
// end;
except
on e : exception do
begin
frmMain.printlog('Database Connect Error :: '+e.Message);
end;
end;
Series1.AddXY(no, vPF*100, '', clBlue); // x: 시간, y: PF
Series2.AddXY(no, vVrms, '', clGray); // x: 시간, y: Vrms
Series3.AddXY(no, vIrms*100, '', clGreen); // x: 시간, y: Irms
Series4.AddXY(no, vPwr, '', clRed); // x: 시간, y: Pwr
if Series1.Count > FMaxPoints then Series1.Delete(0);
if Series2.Count > FMaxPoints then Series2.Delete(0);
if Series3.Count > FMaxPoints then Series3.Delete(0);
if Series4.Count > FMaxPoints then Series4.Delete(0);
Series1.Visible := true;
Series2.Visible := true;
Series3.Visible := true;
Series4.Visible := true;
{
y_maxvalue := 0;
if y_maxvalue < Series1.YValues.MaxValue then y_maxvalue := Series1.YValues.MaxValue;
if y_maxvalue < Series2.YValues.MaxValue then y_maxvalue := Series2.YValues.MaxValue;
if y_maxvalue < Series3.YValues.MaxValue then y_maxvalue := Series3.YValues.MaxValue;
if y_maxvalue < Series4.YValues.MaxValue then y_maxvalue := Series4.YValues.MaxValue;
if Chart_Main.Axes.Left.Maximum <> (y_maxvalue + 100) then
Chart_Main.Axes.Left.Maximum := y_maxvalue + 100;
}
// 차트 자동 스크롤
Chart_Main.Axes.Bottom.SetMinMax(
Series1.XValues.Value[Max(0, Series1.Count - FMaxPoints)],
Series1.XValues.Value[Series1.Count - 1]
);
no := no + 1;
// Series2.Add(intvVrms, '', clRed);
// Series3.Add(intvIrms, '', clGreen);
// Series4.Add(intvPwr, '', $00FF0080);
// Series5.Add(strlist[4].ToInteger, str, $00FF8000);
// FANTrend1.Add(1, vPF, formatdatetime('hh:nn:ss',now()));
// FANTrend1.Add(2, vVrms, formatdatetime('hh:nn:ss',now()));
// FANTrend1.Add(3, vIrms, formatdatetime('hh:nn:ss',now()));
// FANTrend1.Add(4, vPwr, formatdatetime('hh:nn:ss',now()));
end;
end.