File: pcm-win-power-tray.py

package info (click to toggle)
pcm 202502-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 4,164 kB
  • sloc: cpp: 44,347; ansic: 1,161; sh: 778; python: 388; awk: 28; makefile: 13
file content (125 lines) | stat: -rw-r--r-- 3,926 bytes parent folder | download
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()