1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
|
import pystray
from PIL import Image, ImageDraw, ImageFont
import threading
import time
import subprocess
import csv
import io
def create_image(text, background_color):
width = 12
height = 12
image = Image.new('RGB', (width, height), background_color)
draw = ImageDraw.Draw(image)
# Use the default font and scale it
font = ImageFont.load_default()
# Calculate text size and position
text_bbox = draw.textbbox((0, 0), text, font=font)
text_width = text_bbox[2] - text_bbox[0]
text_height = text_bbox[3] - text_bbox[1]
text_x = (width - text_width) // 2
text_y = -2 + (height - text_height) // 2
# Draw the text on the image
draw.text((text_x, text_y), text, fill="white", font=font)
# Scale the image down to fit the system tray icon size
image = image.resize((64, 64), Image.LANCZOS)
return image
# global process variable to kill the pcm.exe process when the icon is clicked
process = None
def update_icon(icon):
# Start the pcm.exe process with -csv 3 parameters
# store process into the global process variable
global process
process = subprocess.Popen(
# change the path to pcm.exe as needed
["..\\windows_build22\\bin\\Release\\pcm.exe", "-r", "-csv", "3"],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True
)
count = 0
while True:
# find the header line to find the index of "SYSTEM Energy (Joules)"
if (count > 1000):
print (f"Can't find SYSTEM Energy (Joules) metric")
process.kill()
exit(0)
count = count + 1
line = process.stdout.readline()
csv_reader = csv.reader(io.StringIO(line))
header = next(csv_reader)
try:
system_energy_index = header.index("SYSTEM Energy (Joules)")
print (f"SYSTEM Energy (Joules) found at index {system_energy_index}")
break
except ValueError:
#print("SYSTEM Energy (Joules) not found in the header")
continue
# Skip the second header line
process.stdout.readline()
while True:
# Read the output line by line
line = process.stdout.readline()
# print (line)
if not line:
break
system_energy_joules = -1
# Parse the CSV output
csv_reader = csv.reader(io.StringIO(line))
for row in csv_reader:
# Extract the system power consumption in Watts
try:
system_energy_joules = float(row[system_energy_index])
print (f"SYSTEM Energy (Joules): {system_energy_joules}")
# Convert Joules to Watts
power_consumption_watts = system_energy_joules / 3.0
if (power_consumption_watts > 30) :
background_color = "red"
elif (power_consumption_watts > 20) :
background_color = "darkblue"
else:
background_color = "darkgreen"
# Update the icon with the current power consumption in Watts
icon.icon = create_image(f"{power_consumption_watts:.0f}", background_color)
except (IndexError, ValueError):
continue
if (system_energy_joules == -1):
continue
print (f"pcm.exe exited with code {process.returncode}")
def on_quit(icon, item):
icon.stop()
process.kill()
def main():
# Create the system tray icon
icon = pystray.Icon("Intel PCM: System Watts")
icon.icon = create_image("P", "darkblue")
icon.title = "Intel PCM: System Watts"
icon.menu = pystray.Menu(
pystray.MenuItem("Quit", on_quit)
)
# Start a thread to update the icon
threading.Thread(target=update_icon, args=(icon,), daemon=True).start()
# Run the icon
icon.run()
if __name__ == "__main__":
main()
|