@@ -147,6 +147,92 @@ def is_active(self):
147147 """
148148 return self .temperature > self .threshold
149149
150+ class LoadAverage (InternalDevice ):
151+ """
152+ Extends :class:`InternalDevice` to provide a device which is active when
153+ the CPU load average exceeds the *threshold* value.
154+
155+ The following example plots the load average on an LED bar graph::
156+
157+ from gpiozero import LEDBarGraph, LoadAverage
158+ from signal import pause
159+
160+ la = LoadAverage(min_load_average=0, max_load_average=2)
161+ graph = LEDBarGraph(5, 6, 13, 19, 25, pwm=True)
162+
163+ graph.source = la.values
164+
165+ pause()
166+
167+ :param str load_average_file:
168+ The file from which to read the load average. This defaults to the
169+ proc file :file:`/proc/loadavg`. Whatever file is specified is expected
170+ to contain three space-separated load averages at the beginning of the
171+ file, representing 1 minute, 5 minute and 15 minute averages
172+ respectively.
173+
174+ :param float min_load_average:
175+ The load average at which :attr:`value` will read 0.0. This defaults to
176+ 0.0.
177+
178+ :param float max_load_average:
179+ The load average at which :attr:`value` will read 1.0. This defaults to
180+ 1.0.
181+
182+ :param float threshold:
183+ The load average above which the device will be considered "active".
184+ This defaults to 0.8.
185+
186+ :param int minutes:
187+ The number of minutes over which to average the load. Must be 1, 5 or
188+ 15.
189+ """
190+ def __init__ (self , load_average_file = '/proc/loadavg' , min_load_average = 0.0 ,
191+ max_load_average = 1.0 , threshold = 0.8 , minutes = 1 ):
192+ self .load_average_file = load_average_file
193+ super (InternalDevice , self ).__init__ ()
194+ self .min_load_average = min_load_average
195+ self .max_load_average = max_load_average
196+ self .threshold = threshold
197+ if minutes not in (1 , 5 , 15 ):
198+ raise ValueError ('minutes must be 1, 5 or 15' )
199+ self ._load_average_file_column = {
200+ 1 : 0 ,
201+ 5 : 1 ,
202+ 15 : 2 ,
203+ }[minutes ]
204+ self ._fire_events ()
205+
206+ def __repr__ (self ):
207+ return '<gpiozero.LoadAverage load average=%.2f>' % self .load_average
208+
209+ @property
210+ def load_average (self ):
211+ """
212+ Returns the current load average
213+ """
214+ with io .open (self .load_average_file , 'r' ) as f :
215+ file_contents = f .readline ().strip ().split ()
216+ return float (file_contents [self ._load_average_file_column ])
217+
218+ @property
219+ def value (self ):
220+ """
221+ Returns the current load average as a value between 0.0 (representing
222+ the *min_load_average* value) and 1.0 (representing the
223+ *max_load_average* value). These default to 0.0 and 1.0 respectively.
224+ """
225+ load_average_range = self .max_load_average - self .min_load_average
226+ return (self .load_average - self .min_load_average ) / load_average_range
227+
228+ @property
229+ def is_active (self ):
230+ """
231+ Returns ``True`` when the :attr:`load_average` exceeds the
232+ :attr:`threshold`.
233+ """
234+ return self .load_average > self .threshold
235+
150236
151237class TimeOfDay (InternalDevice ):
152238 """
@@ -240,4 +326,3 @@ def value(self):
240326 return self .start_time <= datetime .utcnow ().time () <= self .end_time
241327 else :
242328 return self .start_time <= datetime .now ().time () <= self .end_time
243-
0 commit comments