-
Notifications
You must be signed in to change notification settings - Fork 15
/
Copy pathrpi_tempmon.py
executable file
·334 lines (282 loc) · 11.7 KB
/
rpi_tempmon.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
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
#!/usr/bin/env python3
"""
# ========================HEADER=======================================
# title :rpi_tempmon.py
# description :python script to display the CPU & GPU temp of RPi
# author :Gavin Lyons
# intial date :17/08/2017
# web url :https://github.com/gavinlyonsrepo/raspberrypi_tempmon
# mail :glyons66@hotmail.com
# python version : 3.7.3
# Functions:
(1) exit_handler_func: exit handler function
(2) stresstest_func: stresstest function
(3) process_cmd_arguments: process command line arguments
(4) print_title_func: prints title to console
(5) read_configfile_func: read in config file
(6) alarm_mode_check: checks for alarm condition
(7) cont_mode_check: checks for continuous mode
(8) main: main program loop
(9) set_paths_func: set and check the paths for config & cache
(10) led_toggle_func: function to toggle a GPIO
"""
# =========================IMPORTS======================
# Import the system modules needed to run rpi_tempmon.py.
import sys
import os
import datetime
import argparse
import configparser
import time
import socket # For hostname
from gpiozero import LED
# my modules
from rpiTempMod import RpiTempmonGraph
from rpiTempMod import RpiTempmonWork as Work
# Local testing, comment out next 3 lines for production
#sys.path.insert(0, '/home/gavin/Documents/tech/mytemp/rpiTempMod')
#import RpiTempmonWork as Work
#import RpiTempmonGraph
# =======================GLOBALS=========================
# metadata
__VERSION__ = "3.0"
__URL__ = "https://github.com/gavinlyonsrepo/raspberrypi_tempmon"
# set the path for logfile
DESTLOG = os.environ['HOME'] + "/.cache/rpi_tempmon"
# set the path for config file
DESTCONFIG = os.environ['HOME'] + "/.config/rpi_tempmon"
DESTCONFIGFILE = DESTCONFIG + "/" + "rpi_tempmon.cfg"
# ===================FUNCTION SECTION===============================
def exit_handler_func():
"""Handle the program exit"""
# Print exit message
print("\nGoodbye " + os.environ['USER'])
Work.msg_func("bold", "Endex")
quit()
def stresstest_func(testrun_count):
"""Call stresstest function and display stress test graph choice"""
print(DESTLOG)
yaxislist, cpulist, cpu_uselist, plotlabel1, \
plotlabel2, ylabel, title = Work.stresstest(DESTLOG, testrun_count)
mychoice = input("\nDo you want to view graph of stress test? [y/N]")
if (mychoice == "y") or (mychoice == "Y"):
mygraph = RpiTempmonGraph.MatplotGraph("RPi Tempmon :")
mygraph.draw_graph(yaxislist, cpulist, cpu_uselist,
plotlabel1, plotlabel2, ylabel, title)
def process_cmd_arguments():
"""Function for processing CL arguments
return tuple of 4 values to main"""
str_desc = "URL help at: {}".format(__URL__)
parser = argparse.ArgumentParser(description=str_desc)
parser.add_argument(
'-v', help='Print rpi_tempmon version and quit',
default=False, dest='version', action='store_true')
parser.add_argument(
'-l', help='Log file mode',
default=False, dest='logfile', action='store_true')
parser.add_argument(
'-s', help=' convert Log file to csv',
default=False, dest='csv_convert', action='store_true')
parser.add_argument(
'-L', help='Log folder mode',
default=False, dest='logfolder', action='store_true')
parser.add_argument(
'-m', help='Send email mode with ssmtp',
default=False, dest='mail', action='store_true')
parser.add_argument(
'-g', help='Draw a graph from log file data',
default=False, dest='graphlog', action='store_true')
parser.add_argument(
'-c', help='Continuous mode, + integer arg in secs for delay time',
type=int, dest='cont')
parser.add_argument(
'-a', help='Analysis the log file and report',
default=False, dest='data', action='store_true')
parser.add_argument('-n', help='notify mode +int arg, 2=notify always ,\
3=notify only on Cpu limit exceed', type=int, dest='notify')
parser.add_argument(
'-ST', help='Stress test mode, + integer arg for number of runs',
type=int, dest='stresstest')
args = parser.parse_args()
# read config file
config_file_data = read_configfile_func()
# unpack tuple with values
mailuser, mail_alert, alarm_mode, cpu_limit, led_mode, led_num = config_file_data
# pack a new tuple for main
config_file_data_main = config_file_data[2:6]
# check the args
if not len(sys.argv) > 1:
# no argument > back to main
return config_file_data_main
if args.cont:
# cont mode > back to main
return config_file_data_main
if args.stresstest:
stresstest_func(sys.argv[2])
if args.version:
Work.msg_func("bold", "\nVersion : rpi_tempmon " + __VERSION__)
if args.csv_convert:
Work.csv_convert(DESTLOG)
if args.logfolder:
# call log function pass L for folder
Work.logging_func("L", "0", "100", "X", DESTLOG, False)
if args.data:
# call the data analysis function
Work.data_func(DESTLOG, False)
if args.logfile:
# call log function pass l for file
Work.logging_func("l", mail_alert, cpu_limit, mailuser, DESTLOG, alarm_mode)
if args.notify:
Work.notify_func(sys.argv[2], cpu_limit)
if args.mail:
# mail mode
if mail_alert == "1":
Work.mail_func(" Mail mode ", mailuser, DESTLOG)
else:
Work.msg_func("yellow", "Mail Alert disabled in config file rpitempmon.cfg ::" + mail_alert)
if args.graphlog:
mygraph = RpiTempmonGraph.MatplotGraph("RPi Tempmon :")
mygraph.graph_log_data(DESTLOG)
exit_handler_func()
def print_title_func():
"""Function to print title in normal and cont mode"""
os.system('clear')
print()
Work.msg_func("line", "")
today = datetime.datetime.now().strftime("%y-%m-%d %H:%M:%S")
Work.msg_func("bold", "Raspberry pi CPU GPU temperature monitor program")
print(today)
print(socket.gethostname())
Work.msg_func("line", "")
Work.msg_func("green", "CPU temp => {}'C".format(Work.get_cpu_tempfunc()))
Work.msg_func("green", "GPU temp => {}".format(Work.get_gpu_tempfunc()))
Work.msg_func("green", "CPU usage => {}%".format(Work.get_cpu_use()))
Work.msg_func("green", "RAM usage => {}%".format(Work.get_ram_info()))
Work.msg_func("green", "Swap usage => {}% \n".format(Work.get_swap_info()))
def read_configfile_func():
"""Read in configfile, return 6 values in a tuple"""
try:
myconfigfile = configparser.ConfigParser()
myconfigfile.read(DESTCONFIGFILE)
mailuser = myconfigfile.get("MAIN", "RPI_AuthUser")
mail_alert = myconfigfile.get("MAIN", "MAIL_ALERT")
alarm_mode = myconfigfile.get("MAIN", "ALARM_MODE")
cpu_limit = myconfigfile.get("MAIN", "CPU_UPPERLIMIT")
led_mode = myconfigfile.get("MAIN", "LED_MODE")
led_num = myconfigfile.get("MAIN", "GPIO_LED")
if (int(cpu_limit) < 1) or (int(cpu_limit) > 99):
Work.msg_func("red", " ERROR : ")
print("CPU_UPPERLIMIT must be between 1 and 99")
quit()
config_file_data = (mailuser, mail_alert, alarm_mode, cpu_limit, led_mode, led_num)
except Exception as error:
Work.msg_func("red", " ERROR : ")
print("Problem with config file: {}".format(error))
print("Must have section header of [MAIN] and six parameters")
print("Help and example file at url")
print(__URL__)
exit_handler_func()
return config_file_data
def alarm_mode_check(config_file_data_main, my_led):
"""function to check alarm mode """
alarm_mode, cpu_limit, led_mode, led_num = config_file_data_main
if alarm_mode == "1":
Work.msg_func("bold", "Alarm mode is on: " + cpu_limit + "'C")
if Work.get_cpu_tempfunc() > cpu_limit:
# display led mode
Work.msg_func("red", "Warning : CPU over the temperature limit: " + cpu_limit + "'C")
if led_mode == "1":
Work.msg_func("bold", "LED mode is on, GPIO pin selected: " + led_num)
led_toggle_func("on", my_led)
def cont_mode_check(my_led):
"""check for continuous mode """
delay = 5
# is their an argument?
if len(sys.argv) > 1:
# Was it -c?
if sys.argv[1] == "-c":
val = int(sys.argv[2])
# if not a positive int print message and ask for input again
if val < 0:
print("Sorry, input to -c must be a positive integer.")
quit()
delay = sys.argv[2]
Work.msg_func("bold", "Continuous mode: On")
Work.msg_func("bold", "Sleep delay set to: " + str(delay) + " seconds.")
print("\nPress CTRL+c to quit.")
time.sleep(float(delay))
os.system('clear')
else: # normal mode prompt
if Work.msg_func("yesno", ""):
pass
else:
led_toggle_func("off", my_led)
exit_handler_func()
def set_paths_func():
"""set and check the paths for config file and cache/logging"""
if not os.path.exists(DESTLOG): # Check cache path is there
os.makedirs(DESTLOG)
if not os.path.exists(DESTCONFIG): # Check config path is there
os.makedirs(DESTCONFIG)
if os.path.isfile(DESTCONFIGFILE): # Check config file is there
pass
else:
try:
config = configparser.ConfigParser()
config.optionxform = lambda option: option # case sensitive option
config['MAIN'] = {'RPI_AuthUser': 'example@gmail.com',
'MAIL_ALERT': '1',
'ALARM_MODE': '1',
'CPU_UPPERLIMIT': '70',
'LED_MODE': '1',
'GPIO_LED': '26'}
with open(DESTCONFIGFILE, 'w') as configfile:
config.write(configfile)
except Exception as error:
Work.msg_func("red", " ERROR : ")
print("Config file is missing at {}".format(DESTCONFIGFILE))
print("Problem Creating default config file: {}".format(error))
print("Example config file and info can be found at:")
print(__URL__)
exit_handler_func()
else:
Work.msg_func("yellow", " INFO : ")
print("Config file was missing at {}".format(DESTCONFIGFILE))
print("Config file created with default values.")
input("Press <Enter> to continue")
def led_toggle_func(mode, my_led):
""" led_toggle_func , function
to toggle a GPIO LED, passed mode on/off
and GPIO pin of LED"""
time.sleep(.05) # gpio init
if mode == "off":
my_led.off()
else:
my_led.on()
def main(config_file_data_main):
"""Function to hold main program loop, param1 : config file data tuple"""
# unpack config file data main tuple
alarm_mode, cpu_limit, led_mode, led_num = config_file_data_main
my_led = LED(int(led_num))
scan_count = 0
# main loop
try:
while True:
print_title_func()
scan_count += 1
Work.msg_func("bold", "Number of scans: " + str(scan_count))
alarm_mode_check(config_file_data_main, my_led)
cont_mode_check(my_led)
led_toggle_func("off", my_led)
except KeyboardInterrupt:
led_toggle_func("off", my_led)
exit_handler_func()
# =====================MAIN===============================
if __name__ == "__main__":
try:
print("\nRPi temperature monitor:")
set_paths_func()
exit(main(process_cmd_arguments()))
except (KeyboardInterrupt, SystemExit):
pass
# ====================END===============================