From b1fea55405a7b58a44a4c62db6dc5b98f07f3d20 Mon Sep 17 00:00:00 2001
From: Arfouy <yussef.arfu@nure.ua>
Date: Thu, 23 Mar 2023 21:42:24 +0100
Subject: [PATCH] v2

---
 ehci4intel-main/.gitignore   |   1 +
 ehci4intel-main/README.md    |  12 +++
 ehci4intel-main/main.py      | 177 +++++++++++++++++++++++++++++++++++
 ehci4intel-main/powerlog.bat |   2 +
 4 files changed, 192 insertions(+)
 create mode 100644 ehci4intel-main/.gitignore
 create mode 100644 ehci4intel-main/README.md
 create mode 100644 ehci4intel-main/main.py
 create mode 100644 ehci4intel-main/powerlog.bat

diff --git a/ehci4intel-main/.gitignore b/ehci4intel-main/.gitignore
new file mode 100644
index 0000000..47fe223
--- /dev/null
+++ b/ehci4intel-main/.gitignore
@@ -0,0 +1 @@
+log.csv
\ No newline at end of file
diff --git a/ehci4intel-main/README.md b/ehci4intel-main/README.md
new file mode 100644
index 0000000..f0077cd
--- /dev/null
+++ b/ehci4intel-main/README.md
@@ -0,0 +1,12 @@
+# EHCI4Intel
+## REQUIREMENTS
+- PyQt5 `pip3 install PyQt5`
+- [IntelĀ® Power Gadget](https://www.intel.com/content/www/us/en/developer/articles/tool/power-gadget.html)
+
+### Usage
+**For now, each time the application is closed, these steps must be repeated**
+- Set the install location of IntelĀ® Power Gadget
+- Create the log file
+- Choose the application (.exe) to monitor
+
+This will open the application automatically, when the application being monitored is closed, the logging will end.
diff --git a/ehci4intel-main/main.py b/ehci4intel-main/main.py
new file mode 100644
index 0000000..39560d4
--- /dev/null
+++ b/ehci4intel-main/main.py
@@ -0,0 +1,177 @@
+from PyQt5.QtWidgets import *
+from PyQt5.QtCore import *
+from PyQt5.QtGui import *
+import sys
+import os
+import time
+import win32com.client
+import subprocess
+import pyqtgraph as pg 
+
+
+class Window(QMainWindow):
+    POWER_GADGET_PATH = None
+    LOG_FILE = None
+
+    def __init__(self):
+        super().__init__()
+        self.setWindowTitle("EHCI")
+        self.setGeometry(50, 50, 400, 400)
+        self.show()
+
+        main_widget = QWidget()
+        main_layout = QGridLayout(main_widget) 
+        self.setCentralWidget(main_widget)
+
+        self.energy_consumption_label = QLabel("", self)
+        main_layout.addWidget(self.energy_consumption_label, 9, 0, 1, 2)  # Add the new QLabel to the layout
+        
+        self.app_name_label = QLabel("", self)
+        main_layout.addWidget(self.app_name_label, 10, 0, 1, 2)
+
+        self.energy_consumption_graph = pg.PlotWidget(title="Energy Consumption")
+        main_layout.addWidget(self.energy_consumption_graph, 11, 0, 1, 2)
+
+        self.energy_data = []
+
+        
+        power_gadget_path_button = QPushButton("Set PowerLog3.0 path", self)
+        power_gadget_path_button.clicked.connect(self.set_power_gadget_path)
+        main_layout.addWidget(power_gadget_path_button)
+
+        log_file_button = QPushButton("Chose log file", self)
+        log_file_button.clicked.connect(self.create_log)
+        main_layout.addWidget(log_file_button)
+
+        monitor_app_button = QPushButton("Monitor Application", self)
+        monitor_app_button.clicked.connect(self.monitor_app)
+        main_layout.addWidget(monitor_app_button)
+
+        self.battery_name_label = QLabel("", self)
+        main_layout.addWidget(self.battery_name_label)
+
+        self.estimated_charge_remaining_label = QLabel("", self)
+        main_layout.addWidget(self.estimated_charge_remaining_label)
+
+        self.design_capacity_label = QLabel("", self)
+        main_layout.addWidget(self.design_capacity_label)
+
+        self.full_charge_capacity_label = QLabel("", self)
+        main_layout.addWidget(self.full_charge_capacity_label)
+
+        self.device_id_label = QLabel("", self)
+        main_layout.addWidget(self.device_id_label)
+
+        self.power_label = QLabel("", self)
+        main_layout.addWidget(self.power_label)
+
+        exit_button = QPushButton("Exit", self)
+        exit_button.clicked.connect(self.exit_app)
+        main_layout.addWidget(exit_button)
+
+        self.timer = QTimer(self)
+        self.timer.timeout.connect(self.update_data)
+        self.timer.start(1000)  # Update every second (1000 ms)
+        
+    def update_data(self):
+        self.get_battery_data()
+        if self.POWER_GADGET_PATH:
+            power_data = self.get_power_data(self.POWER_GADGET_PATH, 1)
+            if 'Processor Power_0(Watt)' in power_data:
+                power = float(power_data['Processor Power_0(Watt)'])
+                self.power_label.setText(f"Processor Power: {power:.2f} W")
+                energy_consumption = power * 1 / 3600
+                self.energy_consumption_label.setText(f"Energy Consumption: {energy_consumption:.5f} Wh")
+
+                self.energy_data.append(energy_consumption)
+                self.energy_consumption_graph.plot(self.energy_data, clear=True, pen="b")
+   
+    def get_battery_data(self):
+        wmi = win32com.client.GetObject("winmgmts:")
+        battery_data = wmi.ExecQuery("Select * from Win32_Battery")
+
+        for battery in battery_data:
+            self.battery_name_label.setText(f"Battery Name: {battery.Name}")
+            self.estimated_charge_remaining_label.setText(f"Estimated Charge Remaining: {battery.EstimatedChargeRemaining}%")
+            self.design_capacity_label.setText(f"Design Capacity: {battery.DesignCapacity} mWh")
+            self.full_charge_capacity_label.setText(f"Full Charge Capacity: {battery.FullChargeCapacity} mWh")
+
+    def get_power_data(self, power_gadget_path, duration):
+        power_log_path = os.path.join(power_gadget_path, "PowerLog3.0.exe")
+        log_file = "power_log.csv"
+        command = f'"{power_log_path}" -duration {duration} -file "{log_file}"'
+
+        process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+        time.sleep(duration + 1)  # Wait for the logging process to finish
+        process.terminate()
+
+        with open(log_file, "r") as f:
+            lines = f.readlines()
+            headers = lines[0].strip().split(',')
+            values = lines[1].strip().split(',')
+
+            power_data = {}
+            for i in range(len(headers)):
+                power_data[headers[i]] = values[i]
+
+        os.remove(log_file)
+        return power_data
+
+      
+    def set_power_gadget_path(self):
+        folder_path = QFileDialog.getExistingDirectory(self, "Select directory")
+
+        if folder_path:
+            self.POWER_GADGET_PATH = folder_path
+            print(f"PowerLog3.0 path set to {self.POWER_GADGET_PATH}")
+
+
+    def create_log(self):
+        file_name, _ = QFileDialog.getSaveFileName(self, "Save file", "log.csv", "csv files (*.csv);;All Files (*)")
+
+        if file_name:
+            if (os.path.exists(file_name)):
+                os.remove(file_name)
+            
+            f = open(file_name, "x")
+            f.close()
+            self.LOG_FILE = file_name
+
+
+    def monitor_app(self):
+        app_path, _ = QFileDialog.getOpenFileName(self, "Choose exe", "", "exe files (*.exe)")
+
+        if app_path:
+            print(f"Monitoring {app_path}")
+            os.system(f'powerlog.bat "{self.POWER_GADGET_PATH}" "{self.LOG_FILE}" "{app_path}"')
+    def run_monitoring(self, power_gadget_path, log_file, app_path):
+        powerlog_exe = os.path.join(power_gadget_path, "PowerLog3.0.exe")
+        command = f'"{powerlog_exe}" -duration 10 -file "{log_file}"'
+
+        batch_file_content = f"""
+@echo off
+start /b "" cmd /c "{command} >> {log_file}"
+start /wait "" "{app_path}"
+"""
+        batch_file_path = os.path.join(os.path.dirname(log_file), "monitoring.bat")
+
+        with open(batch_file_path, "w") as f:
+            f.write(batch_file_content)
+
+        try:
+            os.startfile(batch_file_path, "runas")
+        except Exception as e:
+            QMessageBox.critical(self, "Error", f"An error occurred while running the monitoring process: {e}")
+        finally:
+            os.remove(batch_file_path)
+
+
+    def exit_app(self):
+        sys.exit()
+
+if __name__ == '__main__':
+    app = QApplication(sys.argv)
+    window = Window()
+    sys.exit(app.exec())            
+    
+    
\ No newline at end of file
diff --git a/ehci4intel-main/powerlog.bat b/ehci4intel-main/powerlog.bat
new file mode 100644
index 0000000..1c7c1a0
--- /dev/null
+++ b/ehci4intel-main/powerlog.bat
@@ -0,0 +1,2 @@
+CD %1
+START .\PowerLog3.0.exe -file %2 -cmd %3
\ No newline at end of file
-- 
GitLab