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