461 lines
12 KiB
ObjectPascal
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.
|