223 lines
7.2 KiB
Plaintext
223 lines
7.2 KiB
Plaintext
unit uMain;
|
|
|
|
interface
|
|
|
|
uses
|
|
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
|
|
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl., Vcl.StdCtrlsStdCtrls,
|
|
Data.DB, FireDAC.Comp.Client, FireDAC.Stan.Def, FireDAC.Phys.MySQL, FireDAC.DApt,
|
|
System.JSON, Vcl.StdCtrls; // JSON 파싱용
|
|
|
|
// 사용자가 추가한 MQTT 및 매니저 라이브러리가 있을 경우 이곳에 uses 처리
|
|
// uses UMQTTClient, uNILMTypes;
|
|
|
|
type
|
|
TfMain = class(TForm)
|
|
btnStart: TButton;
|
|
btnStop: TButton;
|
|
memLog: TMemo;
|
|
procedure btnStartClick(Sender: TObject);
|
|
procedure btnStopClick(Sender: TObject);
|
|
private
|
|
FDConn: TFDConnection;
|
|
FDPhysMySQLDriverLink: TFDPhysMySQLDriverLink;
|
|
// FClient: TMQTTClient; // 실제 사용하실 컴포넌트 객체 선언
|
|
|
|
procedure SetupDatabase;
|
|
procedure LogMsg(const AMsg: string);
|
|
procedure InsertNilmData(SensorNo: Integer; PayloadJSON: string);
|
|
|
|
// MQTT 수신 이벤트 콜백 시그니처 (컴포넌트에 맞게 수정하세요)
|
|
procedure OnMqttMessageReceived(const Topic, Payload: string);
|
|
public
|
|
{ Public declarations }
|
|
end;
|
|
|
|
var
|
|
fMain: TfMain;
|
|
|
|
implementation
|
|
|
|
{$R *.dfm}
|
|
|
|
uses
|
|
System.IniFiles;
|
|
|
|
procedure TfMain.LogMsg(const AMsg: string);
|
|
begin
|
|
// 멀티스레딩 환경(MQTT 콜백 등)에서 VCL 메모 컨트롤 접근 시 에러 방지
|
|
TThread.Queue(nil,
|
|
procedure
|
|
begin
|
|
memLog.Lines.Add(FormatDateTime('yyyy-mm-dd hh:nn:ss', Now) + ' - ' + AMsg);
|
|
end);
|
|
end;
|
|
|
|
procedure TfMain.SetupDatabase;
|
|
var
|
|
Ini: TIniFile;
|
|
DBHost, DBUser, DBPass, DBName: string;
|
|
DBPort: Integer;
|
|
begin
|
|
if Assigned(FDConn) then Exit;
|
|
|
|
Ini := TIniFile.Create(ExtractFilePath(ParamStr(0)) + 'settings.ini');
|
|
try
|
|
DBHost := Ini.ReadString('DB', 'Host', '127.0.0.1');
|
|
DBPort := Ini.ReadInteger('DB', 'Port', 3306);
|
|
DBUser := Ini.ReadString('DB', 'User', 'root');
|
|
DBPass := Ini.ReadString('DB', 'Password', 'password');
|
|
DBName := Ini.ReadString('DB', 'Database', 'mmcl_db');
|
|
finally
|
|
Ini.Free;
|
|
end;
|
|
|
|
FDConn := TFDConnection.Create(Self);
|
|
FDPhysMySQLDriverLink := TFDPhysMySQLDriverLink.Create(Self);
|
|
|
|
FDConn.Params.DriverID := 'MySQL';
|
|
FDConn.Params.Database := DBName;
|
|
FDConn.Params.UserName := DBUser;
|
|
FDConn.Params.Password := DBPass;
|
|
FDConn.Params.Add('Server=' + DBHost);
|
|
FDConn.Params.Add('Port=' + IntToStr(DBPort));
|
|
|
|
try
|
|
FDConn.Connected := True;
|
|
LogMsg('MariaDB 연결 성공 (Host: ' + DBHost + ')');
|
|
except
|
|
on E: Exception do
|
|
LogMsg('DB 연결 오류: ' + E.Message);
|
|
end;
|
|
end;
|
|
|
|
procedure TfMain.InsertNilmData(SensorNo: Integer; PayloadJSON: string);
|
|
var
|
|
Qry: TFDQuery;
|
|
JSONObj: TJSONObject;
|
|
v1_pwr, v1_cur, v1_volt: Double;
|
|
v2_pwr, v2_cur, v2_volt: Double;
|
|
v3_pwr, v3_cur, v3_volt: Double;
|
|
begin
|
|
if not Assigned(FDConn) or not FDConn.Connected then Exit;
|
|
|
|
// 기본값 초기화
|
|
v1_pwr:=0; v1_cur:=0; v1_volt:=0;
|
|
v2_pwr:=0; v2_cur:=0; v2_volt:=0;
|
|
v3_pwr:=0; v3_cur:=0; v3_volt:=0;
|
|
|
|
// JSON 파싱 (System.JSON 활용)
|
|
// uNILMTypes.pas의 "wA", "currentA", "voltageA" 형식 파싱 대응
|
|
JSONObj := TJSONObject.ParseJSONValue(PayloadJSON) as TJSONObject;
|
|
if Assigned(JSONObj) then
|
|
begin
|
|
try
|
|
// CH1 (L1 / A)
|
|
JSONObj.TryGetValue<Double>('wA', v1_pwr);
|
|
JSONObj.TryGetValue<Double>('currentA', v1_cur);
|
|
JSONObj.TryGetValue<Double>('voltageA', v1_volt);
|
|
// CH2 (L2 / B)
|
|
JSONObj.TryGetValue<Double>('wB', v2_pwr);
|
|
JSONObj.TryGetValue<Double>('currentB', v2_cur);
|
|
JSONObj.TryGetValue<Double>('voltageB', v2_volt);
|
|
// CH3 (L3 / C)
|
|
JSONObj.TryGetValue<Double>('wC', v3_pwr);
|
|
JSONObj.TryGetValue<Double>('currentC', v3_cur);
|
|
JSONObj.TryGetValue<Double>('voltageC', v3_volt);
|
|
finally
|
|
JSONObj.Free;
|
|
end;
|
|
end;
|
|
|
|
Qry := TFDQuery.Create(nil);
|
|
try
|
|
Qry.Connection := FDConn;
|
|
|
|
// 1. sensor_history_log (시계열 이력) 적재 - CH1, CH2, CH3 모두 저장
|
|
Qry.SQL.Text :=
|
|
'INSERT INTO sensor_history_log (sensor_no, log_time, ' +
|
|
' value_ch1_pwr, value_ch1_current, value_ch1_volt, ' +
|
|
' value_ch2_pwr, value_ch2_current, value_ch2_volt, ' +
|
|
' value_ch3_pwr, value_ch3_current, value_ch3_volt) ' +
|
|
'VALUES (:SNo, NOW(), :P1, :C1, :V1, :P2, :C2, :V2, :P3, :C3, :V3)';
|
|
|
|
Qry.ParamByName('SNo').AsInteger := SensorNo;
|
|
Qry.ParamByName('P1').AsFloat := v1_pwr; Qry.ParamByName('C1').AsFloat := v1_cur; Qry.ParamByName('V1').AsFloat := v1_volt;
|
|
Qry.ParamByName('P2').AsFloat := v2_pwr; Qry.ParamByName('C2').AsFloat := v2_cur; Qry.ParamByName('V2').AsFloat := v2_volt;
|
|
Qry.ParamByName('P3').AsFloat := v3_pwr; Qry.ParamByName('C3').AsFloat := v3_cur; Qry.ParamByName('V3').AsFloat := v3_volt;
|
|
Qry.ExecSQL;
|
|
|
|
// 2. sensor_info (현재 상태) 업데이트
|
|
Qry.SQL.Text :=
|
|
'UPDATE sensor_info SET update_time = NOW(), ' +
|
|
' value_ch1_pwr = :P1, value_ch1_current = :C1, value_ch1_volt = :V1, ' +
|
|
' value_ch2_pwr = :P2, value_ch2_current = :C2, value_ch2_volt = :V2, ' +
|
|
' value_ch3_pwr = :P3, value_ch3_current = :C3, value_ch3_volt = :V3 ' +
|
|
'WHERE sensor_no = :SNo AND sensor_typeid = 1';
|
|
|
|
Qry.ParamByName('SNo').AsInteger := SensorNo;
|
|
Qry.ParamByName('P1').AsFloat := v1_pwr; Qry.ParamByName('C1').AsFloat := v1_cur; Qry.ParamByName('V1').AsFloat := v1_volt;
|
|
Qry.ParamByName('P2').AsFloat := v2_pwr; Qry.ParamByName('C2').AsFloat := v2_cur; Qry.ParamByName('V2').AsFloat := v2_volt;
|
|
Qry.ParamByName('P3').AsFloat := v3_pwr; Qry.ParamByName('C3').AsFloat := v3_cur; Qry.ParamByName('V3').AsFloat := v3_volt;
|
|
Qry.ExecSQL;
|
|
|
|
LogMsg(Format('DB Insert/Update 완료 [Sensor: %d]', [SensorNo]));
|
|
except
|
|
on E: Exception do
|
|
LogMsg('DB 처리 오류: ' + E.Message);
|
|
end;
|
|
Qry.Free;
|
|
end;
|
|
|
|
procedure TfMain.OnMqttMessageReceived(const Topic, Payload: string);
|
|
begin
|
|
LogMsg('MQTT 수신 Topic: ' + Topic);
|
|
LogMsg('MQTT 페이로드: ' + Payload);
|
|
|
|
// 하드코딩된 센서 번호 101 사용 (실제로는 Topic이나 JSON에서 추출)
|
|
// 예: Topic = '/nilm/cnc/101'
|
|
InsertNilmData(101, Payload);
|
|
end;
|
|
|
|
procedure TfMain.btnStartClick(Sender: TObject);
|
|
var
|
|
Ini: TIniFile;
|
|
MqttHost: string;
|
|
MqttPort: Integer;
|
|
begin
|
|
LogMsg('NILM 에이전트 구동을 시작합니다...');
|
|
SetupDatabase;
|
|
|
|
Ini := TIniFile.Create(ExtractFilePath(ParamStr(0)) + 'settings.ini');
|
|
try
|
|
MqttHost := Ini.ReadString('MQTT', 'Host', '127.0.0.1');
|
|
MqttPort := Ini.ReadInteger('MQTT', 'Port', 1883);
|
|
finally
|
|
Ini.Free;
|
|
end;
|
|
|
|
LogMsg(Format('MQTT 연결 정보 로드 (Host: %s, Port: %d)', [MqttHost, MqttPort]));
|
|
|
|
// TODO: 추가해주신 UMQTTClient.pas 클래스 인스턴스화 및 연결
|
|
// FClient := TMQTTClient.Create(...);
|
|
// FClient.Host := MqttHost;
|
|
// FClient.Port := MqttPort;
|
|
// FClient.OnMessage := OnMqttMessageReceived;
|
|
// FClient.Connect;
|
|
|
|
LogMsg('MQTT 브로커 리스닝 대기중...');
|
|
end;
|
|
|
|
procedure TfMain.btnStopClick(Sender: TObject);
|
|
begin
|
|
LogMsg('에이전트 중지 요청...');
|
|
// if Assigned(FClient) then FClient.Disconnect;
|
|
if Assigned(FDConn) and FDConn.Connected then
|
|
begin
|
|
FDConn.Connected := False;
|
|
LogMsg('DB 연결이 안전하게 해제되었습니다.');
|
|
end;
|
|
end;
|
|
|
|
end.
|