unit uMain; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, uMQTTComps, StdCtrls, Grids, BaseGrid, AdvGrid, uMQTT ,uSysLog, ExtCtrls, DateUtils, ComCtrls, Menus, ScktComp, inifiles, FarmSMem, JsonConvertor, Buttons, IntNum, NumEdit, ZConnection, MQTT, ZAbstractDataset, ZDataset, DB, ZAbstractRODataset; type TfrmMain = class(TForm) MQTTClient1: TMQTTClient; initTimer: TTimer; StatusBar1: TStatusBar; MainMenu1: TMainMenu; File1: TMenuItem; Config1: TMenuItem; N2: TMenuItem; Connect1: TMenuItem; Disconnect1: TMenuItem; JsonConvertor1: TJsonConvertor; insertTimer: TTimer; ListBox1: TListBox; File2: TMenuItem; DebugMode1: TMenuItem; N8: TMenuItem; ProgramExit1: TMenuItem; Panel1: TPanel; Label1: TLabel; Label2: TLabel; Label3: TLabel; Label4: TLabel; ZConnection1: TZConnection; ZReadOnlyQuery1: TZReadOnlyQuery; ZQuery1: TZQuery; NILM1: TMenuItem; Edit1: TMenuItem; N1: TMenuItem; 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: String; aQos: TMQTTQOSType; aRetained: Boolean); procedure MQTTClient1Offline(Sender: TObject; Graceful: Boolean); procedure MQTTClient1Online(Sender: TObject); procedure initTimerTimer(Sender: TObject); procedure FormClose(Sender: TObject; var Action: TCloseAction); procedure Connect1Click(Sender: TObject); procedure Disconnect1Click(Sender: TObject); procedure FormCreate(Sender: TObject); procedure insertTimerTimer(Sender: TObject); procedure ListBox1DblClick(Sender: TObject); procedure ProgramExit1Click(Sender: TObject); procedure DebugMode1Click(Sender: TObject); procedure Config1Click(Sender: TObject); procedure Edit1Click(Sender: TObject); procedure N1Click(Sender: TObject); private { Private declarations } debug_mode : Boolean; msg_flaw_stop : boolean; dumyTopic : string; debug_mode_count, hubPort : integer; procedure InsertData(topic, msg : string); public //read_gwid : integer; fIOTGW : array [1..max_gw] of TIOTGW; fNILM : array [1..max_gw] of TNILM; appPath : string; dbIP, dbPW, dbUser, dbSchema : string; dbPort, brokerPort : integer; mqtt_topic, brokerIP, ClientID, mqtt_user, mqtt_pw : string; aRetain: Boolean; old_NilmID : integer; aQos: TMQTTQOSType; procedure PrintLog(msg, msgType : String); procedure MQTTParsing(data, aTopic : String); procedure ClearIOTGW(); procedure SendMQTT_CtrlCommand(sTopic, sMsg : string); procedure insertSQL(sql : string); end; var frmMain: TfrmMain; implementation {$R *.dfm} uses global, uConfigMQTT, uConfigNILM, uDevConfig; procedure TfrmMain.ClearIOTGW(); var p, i : integer; begin for p:=1 to max_gw do begin fIOTGW[p]._TOPIC := ''; for i:=0 to 15 do fIOTGW[p]._DI[i] := false; for i:=0 to 7 do fIOTGW[p]._DO[i] := false; for i:=0 to 3 do fIOTGW[p]._AI[i] := 0; for i:=0 to 9 do fIOTGW[p]._TEMP[i] := 0.0; for i:=0 to 9 do fIOTGW[p]._HUMID[i] := 0.0; fIOTGW[p].run_dd := 0; fIOTGW[p].run_hh := 0; fIOTGW[p].run_mm := 0; fIOTGW[p].run_ss := 0; 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.InsertData(topic, msg : string); begin end; //MQTT µ¥ÀÌÅÍ ÆÄ½Ì procedure TfrmMain.MQTTParsing(data, aTopic : String); var tempTopic_list : TStringList; aVal, pf, Vrms, Irms, Var_, Va, Pwr, gX, gY, gZ, aX, aY, aZ, TempC : Single; sVal : String; nilmID, ch : integer; sql : string; begin try if Trim(data) <> '' then begin InsertData(aTopic, data); try tempTopic_list := TStringList.Create; Strsplit('/',aTopic, tempTopic_list); if tempTopic_list.Count>3 then begin nilmID := StrToIntDef(tempTopic_list.Strings[ tempTopic_list.Count-1 ], 0); Label1.Caption := format('NILM ID = %d',[nilmID]); if (nilmID > 0) and (nilmID <= max_gw) and (fNILM[nilmID].idxNo>0) then begin JsonConvertor1.srcJson_Colon := data; ch := StrToIntDef(JsonConvertor1.GetItemValue('CH'), 0); case ch of 01, 02 : begin pf := StrToFloatDef(JsonConvertor1.GetItemValue('PF'), 0.0); Vrms := StrToFloatDef(JsonConvertor1.GetItemValue('Vrms'), 0.0); Irms := StrToFloatDef(JsonConvertor1.GetItemValue('Irms'), 0.0); Var_ := StrToFloatDef(JsonConvertor1.GetItemValue('Var'), 0.0); Va := StrToFloatDef(JsonConvertor1.GetItemValue('Va'), 0.0); Pwr := StrToFloatDef(JsonConvertor1.GetItemValue('Pwr'), 0.0); fNILM[nilmID]._VALUE.PF[ch] := pf; fNILM[nilmID]._VALUE.Vrms[ch] := Vrms; fNILM[nilmID]._VALUE.Irms[ch] := Irms; fNILM[nilmID]._VALUE._Var[ch] := Var_; fNILM[nilmID]._VALUE.Va[ch] := Va; fNILM[nilmID]._VALUE.Pwr[ch] := Pwr; if ch = 01 then Label2.Caption := format('PF : %.3f, Vrms : %.3f, Irms : %.3f, Var : %.3f, Va : %.3f, Pwr : %.3f',[pf, Vrms, Irms, Var_, Va, Pwr]); if ch = 02 then Label3.Caption := format('PF : %.3f, Vrms : %.3f, Irms : %.3f, Var : %.3f, Va : %.3f, Pwr : %.3f',[pf, Vrms, Irms, Var_, Va, Pwr]); end; 03 : begin gX := StrToFloatDef(JsonConvertor1.GetItemValue('gX'), 0.0); gY := StrToFloatDef(JsonConvertor1.GetItemValue('gY'), 0.0); gZ := StrToFloatDef(JsonConvertor1.GetItemValue('gZ'), 0.0); aX := StrToFloatDef(JsonConvertor1.GetItemValue('aX'), 0.0); aY := StrToFloatDef(JsonConvertor1.GetItemValue('aY'), 0.0); aZ := StrToFloatDef(JsonConvertor1.GetItemValue('aZ'), 0.0); TempC := StrToFloatDef(JsonConvertor1.GetItemValue('TempC'), 0.0); Label4.Caption := format('gX : %.3f, gY : %.3f, gZ : %.3f, aX : %.3f, aY : %.3f, aZ : %.3f, Temp : %.2f',[gX, gY, gZ, aX, aY, aZ, TempC]); fNILM[nilmID]._VALUE.Gyro[1] := gX; fNILM[nilmID]._VALUE.Gyro[2] := gY; fNILM[nilmID]._VALUE.Gyro[3] := gZ; fNILM[nilmID]._VALUE.Accel[1] := aX; fNILM[nilmID]._VALUE.Accel[2] := aY; fNILM[nilmID]._VALUE.Accel[3] := aZ; fNILM[nilmID]._VALUE.TempC := TempC; fNILM[nilmID].rcvCount := fNILM[nilmID].rcvCount + 1; if fNILM[nilmID].rcvCount > 65535 then fNILM[nilmID].rcvCount := 1; end; end; end; end; finally tempTopic_list.Free; end; end; except end; end; procedure TfrmMain.PrintLog(msg, msgType : string); var f : TextFile; log: TStringList; i : integer; logfile, buf : string; begin if ListBox1.Items.Count >= 300 then ListBox1.Items.Clear; if msgType = 'DEBUG' then begin if debug_mode then begin if not msg_flaw_stop then ListBox1.Items.Insert(0, FormatDateTime('hh:nn:ss :: ',now)+msg); end; end else if msgType = 'SYS' then begin ListBox1.Items.Insert(0, FormatDateTime('hh:nn:ss :: ',now)+msg); logfile := ''; logfile := appPath+'log\'+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(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(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 TfrmMain.MQTTClient1ClientID(Sender: TObject; var aClientID: UTF8String); begin PrintLog('ClientID :: ' + aClientID, 'SYS'); end; procedure TfrmMain.MQTTClient1EnableChange(Sender: TObject); begin if TMQTTClient(Sender).Enabled then printlog('Client is enabled.', 'SYS') else printlog('Client is disabled.', 'SYS'); end; procedure TfrmMain.MQTTClient1Failure(Sender: TObject; aReason: Integer; var CloseClient: Boolean); begin printlog('---- Failure Reported ' + FailureNames(aReason), 'SYS'); end; procedure TfrmMain.MQTTClient1Mon(Sender: TObject; aStr: string); begin printlog(aStr, 'SYS'); end; procedure TfrmMain.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 TfrmMain.MQTTClient1Online(Sender: TObject); var s: TStringList; begin printlog('Client is online.', 'SYS'); s := TStringList.Create; s.AddObject(mqtt_topic, TObject(aQos)); MQTTClient1.Subscribe(s); s.Free; end; procedure TfrmMain.MQTTClient1Msg(Sender: TObject; aTopic: UTF8String; aMessage: string; aQos: TMQTTQOSType; aRetained: Boolean); var str : string; a : integer; begin str := aMessage; //PrintLog('Message : '+str); if (Pos('{',str)<=0) or (Pos('}',str)<=0) then begin PrintLog('[Not Entry]Topic : '+Utf8ToAnsi(aTopic), 'DEBUG'); end else begin PrintLog('Topic : '+Utf8ToAnsi(aTopic)+', Msg='+str, 'DEBUG'); MQTTParsing(str,Utf8ToAnsi(aTopic)); end; //FRecvTime := now;//IncSecond(Now + (FTimeout -1)); //NotifySessionReadOk(FPtrSession); end; procedure TfrmMain.initTimerTimer(Sender: TObject); var ini : TInifile; pwd : string; begin old_NilmID := 0; debug_mode := false; debug_mode_count := 0; msg_flaw_stop := false; 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); hubPort := ReadInteger('MQTT_HUB','Port',6969); end; ini.Free; end; Statusbar1.Panels.Items[2].Text := format('%d',[MQTTClient1.Port]); Statusbar1.Panels.Items[3].Text := mqtt_topic; MQTTClient1.Activate(false); Sleep(300); MQTTClient1.ClientID := ClientID; MQTTClient1.Host := brokerIP; MQTTClient1.Port := brokerPort; MQTTClient1.Username := mqtt_user; MQTTClient1.Password := mqtt_pw; MQTTClient1.Activate(true); if ZConnection1.Connected then ZConnection1.disConnect(); Sleep(300); ZConnection1.HostName := dbIP; ZConnection1.Port := dbPort; ZConnection1.User := dbUser; ZConnection1.Password := dbPW; ZConnection1.Database := dbSchema; try if not ZConnection1.Connected then ZConnection1.Connect(); except on e : exception do begin printlog('Database Connect Error :: '+e.Message, 'DB'); end; end; frmNILM.ShowNILM(); frmDevConfig.ShowDev(); insertTimer.Enabled := True; initTimer.Enabled := false; end; procedure TfrmMain.FormClose(Sender: TObject; var Action: TCloseAction); begin MQTTClient1.Activate(false); end; procedure TfrmMain.Connect1Click(Sender: TObject); begin MQTTClient1.Activate(false); sleep(300); MQTTClient1.Activate(true); end; procedure TfrmMain.Disconnect1Click(Sender: TObject); begin MQTTClient1.Activate(false); end; procedure TfrmMain.FormCreate(Sender: TObject); begin appPath := ''; appPath := ExtractFilePath(Application.ExeName); if not DirectoryExists(appPath + 'log') then if not CreateDir(appPath + 'log') then raise Exception.Create('Cannot create ' + appPath + 'log'); ClearIOTGW(); end; procedure TfrmMain.SendMQTT_CtrlCommand(sTopic, sMsg : string); var pTopic : UTF8String; begin pTopic := ''; pTopic := sTopic; MQTTClient1.Publish(pTopic, sMsg, aQos, false); end; procedure TfrmMain.insertSQL(sql : string); begin try try if not ZConnection1.Connected then ZConnection1.Connect(); if ZConnection1.Connected then begin ZQuery1.Active := false; ZQuery1.SQL.Clear; ZQuery1.SQL.Add(sql); ZQuery1.ExecSQL; end; finally if ZConnection1.Connected then ZConnection1.Disconnect; end; except on e : exception do begin printlog('[insertSQL()]Database Connect Error :: '+e.Message, 'DB'); end; end; end; procedure TfrmMain.insertTimerTimer(Sender: TObject); var pMsg, S, sql : string; pTopic : UTF8String; p : integer; begin if debug_mode then begin Statusbar1.Panels.Items[0].Text := 'DEBUG'; Inc(debug_mode_count, 1); if debug_mode_count > 1800 then // Debug Mode´Â 30ºÐ¸¸ µ¿ÀÛÇÑ´Ù. CPU Á¡À¯·ü ¶§¹®¿¡, 24½Ã°£ µ¹¸®Áö ¾Ê´Â´Ù. begin debug_mode_count := 0; debug_mode := false; DebugMode1.Checked := debug_mode; end; end else begin Statusbar1.Panels.Items[0].Text := 'RUN'; end; if (MQTTClient1.Online) then begin Statusbar1.Panels.Items[1].Text := 'CONN'; // dumyTopic := ''; // dumyTopic := 'SMART-FARM/QST/MQTT_HUB/PUB/0000'; // pTopic := ''; // pTopic := dumyTopic; // pMsg := ''; // S := ''; // S := formatdatetime('yyyymmddhhnnss',now()); // pMsg := format('{DATE_TIME=%s}', [S]);; // MQTTClient1.Publish(pTopic, pMsg, aQos, false); end else begin Statusbar1.Panels.Items[1].Text := 'DisCON'; end; for p:=1 to max_gw do begin if (fNILM[p].rcvCount>0) and (fNILM[p].rcvCount <> fNILM[p].oldRcvCount) then begin fNILM[p].oldRcvCount := fNILM[p].RcvCount; sql := ''; sql := 'UPDATE nilm_value SET '+ 'pf_1='+floattostr(fNILM[p]._VALUE.PF[1] )+', '+ 'pf_2='+floattostr(fNILM[p]._VALUE.PF[2] )+', '+ 'pf_3='+floattostr(fNILM[p]._VALUE.PF[3] )+', '+ 'Vrms_1='+floattostr(fNILM[p]._VALUE.Vrms[1] )+', '+ 'Vrms_2='+floattostr(fNILM[p]._VALUE.Vrms[2] )+', '+ 'Vrms_3='+floattostr(fNILM[p]._VALUE.Vrms[3] )+', '+ 'Irms_1='+floattostr(fNILM[p]._VALUE.Irms[1] )+', '+ 'Irms_2='+floattostr(fNILM[p]._VALUE.Irms[2] )+', '+ 'Irms_3='+floattostr(fNILM[p]._VALUE.Irms[3] )+', '+ 'Var_1='+floattostr(fNILM[p]._VALUE._Var[1] )+', '+ 'Var_2='+floattostr(fNILM[p]._VALUE._Var[2] )+', '+ 'Var_3='+floattostr(fNILM[p]._VALUE._Var[3] )+', '+ 'Va_1='+floattostr(fNILM[p]._VALUE.Va[1] )+', '+ 'Va_2='+floattostr(fNILM[p]._VALUE.Va[2] )+', '+ 'Va_3='+floattostr(fNILM[p]._VALUE.Va[3] )+', '+ 'Pwr_1='+floattostr(fNILM[p]._VALUE.Pwr[1] )+', '+ 'Pwr_2='+floattostr(fNILM[p]._VALUE.Pwr[2] )+', '+ 'Pwr_3='+floattostr(fNILM[p]._VALUE.Pwr[3] )+', '+ 'gX='+floattostr(fNILM[p]._VALUE.Gyro[1])+', '+ 'gY='+floattostr(fNILM[p]._VALUE.Gyro[2])+', '+ 'gZ='+floattostr(fNILM[p]._VALUE.Gyro[3])+', '+ 'aX='+floattostr(fNILM[p]._VALUE.Accel[1])+', '+ 'aY='+floattostr(fNILM[p]._VALUE.Accel[2])+', '+ 'aZ='+floattostr(fNILM[p]._VALUE.Accel[3])+', '+ 'TempC='+floattostr(fNILM[p]._VALUE.TempC)+', '+ 'lastUpdate=now()'+ ' WHERE NilmID='+inttostr(p); if fNILM[p].idxNo > 0 then insertSQL(sql); sql := ''; sql := 'INSERT INTO '+format('nilm_%.5d',[fNILM[p].idxNo])+' VALUES(null, '+ ''+inttostr(p)+', '+ // Nilm ID ''+floattostr(fNILM[p]._VALUE.PF[1] )+', 0, '+ ''+floattostr(fNILM[p]._VALUE.Vrms[1] )+', '+ ''+floattostr(fNILM[p]._VALUE.Irms[1] )+', '+ ''+floattostr(fNILM[p]._VALUE._Var[1] )+', '+ ''+floattostr(fNILM[p]._VALUE.Va[1] )+', '+ ''+floattostr(fNILM[p]._VALUE.Pwr[1] )+', '+ ''+floattostr(fNILM[p]._VALUE.PF[2] )+', 0, '+ ''+floattostr(fNILM[p]._VALUE.Vrms[2] )+', '+ ''+floattostr(fNILM[p]._VALUE.Irms[2] )+', '+ ''+floattostr(fNILM[p]._VALUE._Var[2] )+', '+ ''+floattostr(fNILM[p]._VALUE.Va[2] )+', '+ ''+floattostr(fNILM[p]._VALUE.Pwr[2] )+', '+ ''+floattostr(fNILM[p]._VALUE.PF[3] )+', 0, '+ ''+floattostr(fNILM[p]._VALUE.Vrms[3] )+', '+ ''+floattostr(fNILM[p]._VALUE.Irms[3] )+', '+ ''+floattostr(fNILM[p]._VALUE._Var[3] )+', '+ ''+floattostr(fNILM[p]._VALUE.Va[3] )+', '+ ''+floattostr(fNILM[p]._VALUE.Pwr[3] )+', '+ ''+floattostr(fNILM[p]._VALUE.Gyro[1])+', '+ ''+floattostr(fNILM[p]._VALUE.Gyro[2])+', '+ ''+floattostr(fNILM[p]._VALUE.Gyro[3])+', '+ ''+floattostr(fNILM[p]._VALUE.Accel[1])+', '+ ''+floattostr(fNILM[p]._VALUE.Accel[2])+', '+ ''+floattostr(fNILM[p]._VALUE.Accel[3])+', '+ ''+floattostr(fNILM[p]._VALUE.TempC)+', '+ 'now())'; if fNILM[p].idxNo > 0 then insertSQL(sql); end; end; end; procedure TfrmMain.ListBox1DblClick(Sender: TObject); begin msg_flaw_stop := not msg_flaw_stop; end; procedure TfrmMain.ProgramExit1Click(Sender: TObject); begin frmMain.Close; end; procedure TfrmMain.DebugMode1Click(Sender: TObject); begin DebugMode1.Checked := not DebugMode1.Checked; debug_mode := DebugMode1.Checked; debug_mode_count := 0; end; procedure TfrmMain.Config1Click(Sender: TObject); begin frmConfigMQTT.Show; end; procedure TfrmMain.Edit1Click(Sender: TObject); begin frmNILM.Show; end; procedure TfrmMain.N1Click(Sender: TObject); begin frmDevConfig.Show; end; end.