-
Notifications
You must be signed in to change notification settings - Fork 1
/
letsrobot_pygame_overlay.py
265 lines (202 loc) · 8.64 KB
/
letsrobot_pygame_overlay.py
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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
import os
import pygame
import pygame.freetype
import pygame.display
import time
import random
from time import sleep
import sys
import datetime
#credit first goes to adafruit!
#https://learn.adafruit.com/pi-video-output-using-pygame/pointing-pygame-to-the-framebuffer
class pythonvideooverlay:
screen = None;
def __init__(self):
"Ininitializes a new pygame screen using the framebuffer"
# Based on "Python GUI in Linux frame buffer"
# http://www.karoltomala.com/blog/?p=679
os.environ["SDL_FBDEV"] = "/dev/fb0"
disp_no = os.getenv("DISPLAY")
if disp_no:
print "I'm running under X display = {0}".format(disp_no)
# Check which frame buffer drivers are available
# Start with fbcon since directfb hangs with composite output
drivers = ['directfb','fbcon', 'directfb', 'svgalib']
found = False
for driver in drivers:
# Make sure that SDL_VIDEODRIVER is set
if not os.getenv('SDL_VIDEODRIVER'):
os.putenv('SDL_VIDEODRIVER', driver)
try:
pygame.display.init()
except pygame.error:
print 'Driver: {0} failed.'.format(driver)
continue
found = True
print "using driver ",driver
break
if not found:
raise Exception('No suitable video driver found!')
size = (pygame.display.Info().current_w, pygame.display.Info().current_h)
print "Fullscreen Framebuffer size: %d x %d" % (size[0], size[1])
self.screen = pygame.display.set_mode(size, pygame.FULLSCREEN)
print "display init complete"
pygame.freetype.init()
pygame.mouse.set_visible(False)
# Clear the screen with black
self.screen.fill((0, 0, 0))
pygame.display.update()
self.percentage = True
self.cpustat = '/proc/stat'
self.sep = ' '
self.sleeptime = .5
self.font = pygame.freetype.SysFont('Verdana', 24, bold=True)
def getcputime(self):
'''
http://stackoverflow.com/questions/23367857/accurate-calculation-of-cpu-usage-given-in-percentage-in-linux
read in cpu information from file
The meanings of the columns are as follows, from left to right:
0cpuid: number of cpu
1user: normal processes executing in user mode
2nice: niced processes executing in user mode
3system: processes executing in kernel mode
4idle: twiddling thumbs
5iowait: waiting for I/O to complete
6irq: servicing interrupts
7softirq: servicing softirqs
#the formulas from htop
user nice system idle iowait irq softirq steal guest guest_nice
cpu 74608 2520 24433 1117073 6176 4054 0 0 0 0
Idle=idle+iowait
NonIdle=user+nice+system+irq+softirq+steal
Total=Idle+NonIdle # first line of file for all cpus
CPU_Percentage=((Total-PrevTotal)-(Idle-PrevIdle))/(Total-PrevTotal)
'''
cpu_infos = {} #collect here the information
with open(self.cpustat,'r') as f_stat:
lines = [line.split(self.sep) for content in f_stat.readlines() for line in content.split('\n') if line.startswith('cpu')]
#compute for every cpu
for cpu_line in lines:
if '' in cpu_line: cpu_line.remove('')#remove empty elements
cpu_line = [cpu_line[0]]+[float(i) for i in cpu_line[1:]]#type casting
cpu_id,user,nice,system,idle,iowait,irq,softrig,steal,guest,guest_nice = cpu_line
Idle=idle+iowait
NonIdle=user+nice+system+irq+softrig+steal
Total=Idle+NonIdle
#update dictionionary
cpu_infos.update({cpu_id:{'total':Total,'idle':Idle}})
return cpu_infos
def getcpuload(self):
'''
CPU_Percentage=((Total-PrevTotal)-(Idle-PrevIdle))/(Total-PrevTotal)
'''
start = self.getcputime()
#wait a second
sleep(self.sleeptime)
stop = self.getcputime()
cpu_load = {}
for cpu in start:
Total = stop[cpu]['total']
PrevTotal = start[cpu]['total']
Idle = stop[cpu]['idle']
PrevIdle = start[cpu]['idle']
TotalDelta = Total-PrevTotal
if TotalDelta == 0:
CPU_Percentage=0
else:
CPU_Percentage=((Total-PrevTotal)-(Idle-PrevIdle))/TotalDelta*100
cpu_load.update({cpu: CPU_Percentage})
cpu_all_cores_avg = (cpu_load["cpu0"]+cpu_load["cpu1"]+cpu_load["cpu2"]+cpu_load["cpu3"])/4
return str(round(cpu_all_cores_avg,1))
def __del__(self):
"Destructor to make sure pygame shuts down, etc."
def measure_temp(self):
temp = os.popen("vcgencmd measure_temp").readline()
return (temp.replace("temp=",""))
def sec2time(self, sec, n_msec=0):
''' Convert seconds to 'D days, HH:MM:SS.FFF' '''
if hasattr(sec,'__len__'):
return [sec2time(s) for s in sec]
m, s = divmod(sec, 60)
h, m = divmod(m, 60)
d, h = divmod(h, 24)
if n_msec > 0:
pattern = '%%02d:%%02d:%%0%d.%df' % (n_msec+3, n_msec)
else:
pattern = r'%02d:%02d:%02d'
if d == 0:
return pattern % (h, m, s)
return ('%d days, ' + pattern) % (d, h, m, s)
def getWifiStats(self):
cmd = "awk 'NR==3 {print $3,\"|\",$4}' /proc/net/wireless"
strQualityDbm = os.popen(cmd).read()
if strQualityDbm:
strQualityDbmSplit = strQualityDbm.split('|')
strQuality = strQualityDbmSplit[0].strip()
strDbm = strQualityDbmSplit[1].strip()
qualityInt = int(float(strQuality))
qualityPercent = qualityInt * 10/7
dbmInt = int(float(strDbm))
return "{0}% {1}dBm".format(qualityPercent, dbmInt)
else:
return "Not Found"
def drawText(self, text, x=0,y=0,clearScreen=True):
textsurface,rect = self.font.render(text, (255, 0, 0))
self.screen.blit(textsurface,(x,y))
def checkTimeDelta(self, last, interval):
now = datetime.datetime.now()
delta = now - last
secondsElapsed = delta.total_seconds()
#print "headlights delta ",headlightSecondsElapsed
if secondsElapsed > interval:
return True
else:
return False
def printDateTimeOutput(self, text):
print str(datetime.datetime.now()) , text
overlay = pythonvideooverlay()
#first time for uptime calculation
now = datetime.datetime.now()
startTime = now
StatsWifi = overlay.getWifiStats()
StatsWifiLastReading = now
StatsWifiInterval = 3
StatsTemp = overlay.measure_temp().strip()
StatsTempLastReading = now
StatsTempInterval = 4
StatsCpu = overlay.getcpuload()
StatsCpuLastReading = now
StatsCpuInterval = 2
overlay.printDateTimeOutput("starting video loop!")
while True:
try:
#clear the screen
overlay.screen.fill((0, 0, 0))
nowTime = datetime.datetime.now()
delta = nowTime - startTime
overlay.drawText("Uptime: "+overlay.sec2time(delta.total_seconds()), 10, 10, True)
if overlay.checkTimeDelta(StatsTempLastReading, StatsTempInterval):
StatsTemp = overlay.measure_temp().strip()
StatsTempLastReading = datetime.datetime.now()
#overlay.printDateTimeOutput("read temp!")
overlay.drawText("Temp: "+StatsTemp, 10, 40, False)
if overlay.checkTimeDelta(StatsWifiLastReading, StatsWifiInterval):
StatsWifi = overlay.getWifiStats()
StatsWifiLastReading = datetime.datetime.now()
#overlay.printDateTimeOutput("read wifi!")
overlay.drawText("Wifi: "+StatsWifi, 10, 68, False)
if overlay.checkTimeDelta(StatsCpuLastReading, StatsCpuInterval):
StatsCpu = overlay.getcpuload()
StatsCpuLastReading = datetime.datetime.now()
#overlay.printDateTimeOutput("read cpu!")
#this call waits 1 second to capture avg cpu usage
overlay.drawText("CPU: "+StatsCpu+"%", 10, 96, False)
#update the screen
pygame.display.update()
#overlay.printDateTimeOutput("update screen!")
# 500 ms delay so the uptime ticker doesnt jump 2s like it does with a 1 sec delay.
#This should be fixed by rewriting the cpu function
sleep(.5)
except KeyboardInterrupt:
overlay.printDateTimeOutput("quitting!")
sys.exit("KeyboardInterrupt")