[FanControl2] Incorrect use of threads
[enigma2-plugins.git] / fancontrol2 / src / plugin.py
1 # FanControl2
2 # joergm6 IHAD
3 # PID-controller by Lukasz S.
4
5 import time
6 import os
7 from __init__ import _
8
9 from globals import *
10
11 from enigma import eTimer, eSize
12
13 # Config
14 from Components.config import configfile, config, ConfigSubsection, ConfigNumber, ConfigInteger, ConfigSlider, ConfigSelection, ConfigYesNo, ConfigText
15 from Components.config import getConfigListEntry
16 from Components.Label import Label
17 from Components.Sources.StaticText import StaticText
18 from Components.Sources.Progress import Progress
19
20 # Startup/shutdown notification
21 from Tools import Notifications
22 from Sensors import sensors
23 from time import gmtime, strftime
24 import datetime
25
26 # Plugin
27 from Plugins.Plugin import PluginDescriptor
28
29 # GUI (Screens)
30 from Screens.Screen import Screen
31 from Components.ConfigList import ConfigListScreen
32 from Screens.MessageBox import MessageBox
33 from Screens.Console import Console
34 from Screens import Standby 
35 from Screens.Standby import TryQuitMainloop
36
37 # GUI (Components)
38 from Components.ActionMap import ActionMap
39 from Components.ActionMap import NumberActionMap
40 from Components.Harddisk import harddiskmanager
41
42 from threading import Thread, Lock
43 import Queue
44 Briefkasten = Queue.Queue()
45
46 FC2doThread = True
47
48 def main(session,**kwargs):
49         try:
50                 session.open(FanControl2Plugin)
51         except:
52                 FClog("Pluginexecution failed")
53
54 def mainMonitor(session,**kwargs):
55         try:
56                 session.open(FanControl2Monitor)
57         except:
58                 FClog("Pluginexecution failed")
59
60 def Test0(wert):
61         return (1 if wert<=0 else wert)
62
63 def skal(x, x1, x2, y1, y2):
64         if x > x2: return y2
65         if x < x1: return y1
66         m = (y2 - y1) / Test0(x2 - x1)
67         y = m * x + y1
68         return y
69
70 def FClog(wert):
71         print "[FanControl2]",wert
72         while len(FC2Log) > config.plugins.FanControl.LogCount.value:
73                 del FC2Log[5]
74         FC2Log.append(strftime("%H:%M:%S ") + wert)
75         if config.plugins.FanControl.EnableEventLog.value:
76                 if Free(config.plugins.FanControl.LogPath.value):
77                         try:
78                                 f = open(config.plugins.FanControl.LogPath.value + "FC2events.txt","a")
79                                 try:
80                                         f.write(strftime("%H:%M:%S ") + wert + "\r\n")
81                                 finally:
82                                         f.close()
83                         except IOError:
84                                 FC2Log.append(strftime("%H:%M:%S ") + "Event-Log-Error")
85                                 
86 def FClogE(wert):
87         if config.plugins.FanControl.EnableEventLog.value:
88                 FClog(wert)
89
90 def FCdata():
91         global DataMinute
92         if strftime("%M")!=DataMinute and config.plugins.FanControl.EnableDataLog.value:
93                 DataMinute = strftime("%M")
94                 if Free(config.plugins.FanControl.LogPath.value):
95                         try:
96                                 f = open(config.plugins.FanControl.LogPath.value + "FC2data.csv","a")
97                                 try:
98                                         f.write(strftime("%Y.%m.%d %H:%M"))
99                                         for count in range(6):
100                                                 f.write(";" + str(FC2werte[count]).replace(".",_(".")))
101                                         templist = sensors.getSensorsList(sensors.TYPE_TEMPERATURE)
102                                         tempcount = len(templist)
103                                         for count in range(tempcount):
104                                                 f.write(";" + str(sensors.getSensorValue(count)))
105                                         f.write("\r\n")
106                                 finally:
107                                         f.close()
108                         except IOError:
109                                 FC2Log.append(strftime("%H:%M:%S ") + "Event-Log-Error")
110
111 def Free(dir):
112         if not os.path.exists(dir):
113                 return False
114         s = os.statvfs(dir)
115         return (s.f_bsize * s.f_bavail / 1024 / 1024) > 10
116
117 def getVoltage(fanid):
118         f = open("/proc/stb/fp/fan_vlt", "r")
119         value = int(f.readline().strip(), 16)
120         f.close()
121         return value
122
123 def setVoltage(fanid, value):
124         if value > 255:
125                 return
126         f = open("/proc/stb/fp/fan_vlt", "w")
127         f.write("%x" % value)
128         f.close()
129
130 def getPWM(fanid):
131         f = open("/proc/stb/fp/fan_pwm", "r")
132         value = int(f.readline().strip(), 16)
133         f.close()
134         return value
135
136 def setPWM(fanid, value):
137         if value > 255:
138                 return
139         f = open("/proc/stb/fp/fan_pwm", "w")
140         f.write("%x" % value)
141         f.close()
142
143 #Configuration
144 config.plugins.FanControl = ConfigSubsection()
145 config.plugins.FanControl.Fan = ConfigSelection(choices = [("disabled", _("disabled")), ("aus", _("Control disabled")), ("3pin", _("3Pin")), ("4pin", _("4Pin")), ("4pinREG", _("4Pin (PID)"))], default = "disabled")
146 config.plugins.FanControl.StandbyOff = ConfigSelection(choices = [("false", _("no")), ("true", _("yes")), ("trueRec", _("yes, Except for Recording or HDD"))], default="false")
147 config.plugins.FanControl.minRPM = ConfigSlider(default = 600, increment = 50, limits = (0, 1500))
148 config.plugins.FanControl.maxRPM = ConfigSlider(default = 3000, increment = 50, limits = (500, 6000))
149 config.plugins.FanControl.temp = ConfigSlider(default = 40, increment = 1, limits = (30, 50))
150 config.plugins.FanControl.tempmax = ConfigSlider(default = 50, increment = 1, limits = (35, 55))
151 config.plugins.FanControl.pwm = ConfigSlider(default = 130, increment = 5, limits = (0, 255))
152 config.plugins.FanControl.vlt = ConfigSlider(default = 255, increment = 5, limits = (0, 255))
153 config.plugins.FanControl.ShowError = ConfigSelection(choices = [("false", _("do nothing")), ("true", _("display Info")), ("shutdown", _("Box Shutdown"))], default="true")
154 config.plugins.FanControl.ShutdownTemp = ConfigInteger(default = 65,limits = (50, 80))
155 config.plugins.FanControl.AddOverheat = ConfigInteger(default = 0,limits = (0, 9))
156 config.plugins.FanControl.DisableDMM = ConfigYesNo(default = False)
157 config.plugins.FanControl.LogCount = ConfigInteger(default = 40,limits = (40, 999))
158 config.plugins.FanControl.LogPath = ConfigText(default="/tmp/", fixed_size=False)
159 config.plugins.FanControl.DeleteData = ConfigSelection(choices = [("0", _("no")), ("2", "2"), ("3", "3"), ("7", "7"), ("14", "14"), ("30", "30")], default="14")
160 config.plugins.FanControl.EnableDataLog = ConfigYesNo(default = False)
161 config.plugins.FanControl.EnableEventLog = ConfigYesNo(default = False)
162 config.plugins.FanControl.CheckHDDTemp = ConfigSelection(choices = [("false", _("no")), ("true", _("yes")), ("auto", _("auto")), ("never", _("never"))], default="auto")
163 config.plugins.FanControl.MonitorInExtension = ConfigYesNo(default = True)
164 config.plugins.FanControl.FanControlInExtension = ConfigYesNo(default = True)
165 config.plugins.FanControl.Multi = ConfigSelection(choices = [("1", "RPM"), ("2", "RPM/2")], default = "2")
166
167 def GetFanRPM():
168         global RPMread
169         f = open("/proc/stb/fp/fan_speed", "r")
170         value = int(f.readline().strip()[:-4])
171         f.close()
172         value = int(value / int(config.plugins.FanControl.Multi.value))
173         if value > 0 and value < 6000:
174                 RPMread = 0
175         else:
176                 RPMread += 1
177         return value
178
179 def GetBox():
180         B = Box
181         if os.path.exists("/proc/stb/info/model"):
182                 f = open("/proc/stb/info/model")
183                 B = f.readline()
184                 f.close()
185         return B
186
187 def isDMMdisabled():
188         value = False
189         if os.path.exists("/usr/lib/enigma2/python/Components/FanControl.py"):
190                 FCfile = open("/usr/lib/enigma2/python/Components/FanControl.py", "r")
191                 text=FCfile.read()
192                 FCfile.close()
193                 if text.find("#Disabled by FC2 config.misc.standbyCounter.addNotifier") is not -1:
194                         value = True
195         return value
196
197 def disableDMM():
198         if os.path.exists("/usr/lib/enigma2/python/Components/FanControl.py"):
199                 FCfile = open("/usr/lib/enigma2/python/Components/FanControl.py", "r")
200                 text=FCfile.read()
201                 FCfile.close()
202                 FCfile = open("/usr/lib/enigma2/python/Components/FanControl.py", "w")
203                 text=text.replace("config.misc.standbyCounter.addNotifier","#Disabled by FC2 config.misc.standbyCounter.addNotifier")
204                 text=FCfile.write(text)
205                 FCfile.close()
206                 FClog("DMM-fancontrol disabled - please restart E2")
207
208 def enableDMM():
209         if os.path.exists("/usr/lib/enigma2/python/Components/FanControl.py"):
210                 FCfile = open("/usr/lib/enigma2/python/Components/FanControl.py", "r")
211                 text=FCfile.read()
212                 FCfile.close()
213                 FCfile = open("/usr/lib/enigma2/python/Components/FanControl.py", "w")
214                 text=text.replace("#Disabled by FC2 config.misc.standbyCounter.addNotifier","config.misc.standbyCounter.addNotifier")
215                 text=FCfile.write(text)
216                 FCfile.close()
217
218 # the PI controller class
219 class ControllerPI:
220         name = "PI Controller"
221         looptime = 0.0
222         dt = 0.0
223         timer_delay = 0.0
224         inputMax = 0.0
225         inputError = 0.0
226         inputDeadband = 0.0
227         integratorOutput = 0.0
228         controlSignal = 0.0
229         coeffKp = 0.0
230         coeffKi = 0.0
231  
232         def __init__(self, givenName = "PI Controller"):
233                 self.name = givenName
234 #               FClogE("%s : creating object" % self.name)
235
236         def ReturnInputError(self):
237                 return self.inputError
238       
239         def ResetIntegrator(self):
240                 FClogE("%s : integrator output %3.2f" % (self.name, self.integratorOutput))
241                 self.integratorOutput = 0.0
242 #               FClog("%s : integrator output now 0" % self.name)
243
244
245         def ScaleCtlError(self,errval,inputMax):
246                 if errval == 0:
247                         return 0
248                 return skal(abs(errval), 0, inputMax , 0, 100) * (errval/abs(errval))
249
250         def DeadBand(self,errval):
251                 if abs(errval) < self.inputDeadband:
252                         FClogE("%s : error within bounds %3.2f %% < %3.2f %%, WON'T control" % (self.name, abs(errval), self.inputDeadband))
253                         return 0.0
254                 else:
255                         FClogE("%s : error EXCEEDS bounds %3.2f %% > %3.2f %%, will control" % (self.name, abs(errval), self.inputDeadband))
256                         return errval
257
258         def Integrate(self,errval):
259                 self.integratorOutput += errval*self.dt
260                 return self.integratorOutput
261
262         def ControlProcess(self,InputError, integratorOutput):
263                 return self.coeffKp*InputError + self.coeffKi*integratorOutput
264
265         def ControlLoop(self, ctlInput, ctlFeedback):
266                 if self.dt < self.timer_delay:
267                         FClogE("%s : WRONG SETTINGS! dt must be >= timer_delay! Adjusted to be same for now.")
268                         self.dt = self.timer_delay
269
270                 self.looptime += self.timer_delay
271                 if self.looptime < self.dt:
272                         FClogE("%s : NOT calling control, looptime %d < %d dt" % (self.name, self.looptime, self.dt))
273                         return Self.ControlSignal
274                 else:
275                         FClogE("%s : calling control, looptime %d = %d dt" % (self.name, self.looptime, self.dt))
276                         self.looptime = 0
277
278                 self.inputError = ctlInput - ctlFeedback
279                 FClogE("%s : made up Input Error %3.2f" % (self.name, self.inputError))
280                 self.inputError = self.ScaleCtlError(self.inputError, self.inputMax)
281                 FClogE("%s : after scale: Input Error %3.2f %%" % (self.name, self.inputError))
282                 self.inputError = self.DeadBand(self.inputError)
283                 FClogE("%s : after deadband: Input Error %3.2f %%" % (self.name, self.inputError))
284                 self.IntegratorOutput = self.Integrate(self.inputError)
285                 FClogE("%s : Integrator output %3.2f %%" % (self.name, self.IntegratorOutput))
286                 self.ControlSignal = self.ControlProcess(self.inputError,self.IntegratorOutput)
287                 FClogE("%s : Control Signal %3.2f %%" % (self.name, self.ControlSignal))
288                 return self.ControlSignal
289 # the PI controller class -end
290
291 class FanControl2Test(ConfigListScreen,Screen):
292         skin = """
293                 <screen position="center,center" size="630,300" title="Fan Control 2 - Test" >
294                         <widget source="TextTest1" render="Label" position="5,20" size="620,30" zPosition="10" font="Regular;20" halign="left" valign="center" backgroundColor="#25062748" transparent="1" />
295                         <widget source="TextTest2" render="Label" position="5,50" size="620,30" zPosition="10" font="Regular;20" halign="left" valign="center" backgroundColor="#25062748" transparent="1" />
296                         <widget source="TextTest3" render="Label" position="5,80" size="620,30" zPosition="10" font="Regular;20" halign="left" valign="center" backgroundColor="#25062748" transparent="1" />
297                         <widget source="TextTest4" render="Label" position="5,130" size="620,30" zPosition="10" font="Regular;20" halign="left" valign="center" backgroundColor="#25062748" transparent="1" />
298                         <widget source="TextTest5" render="Label" position="5,160" size="620,30" zPosition="10" font="Regular;20" halign="left" valign="center" backgroundColor="#25062748" transparent="1" />
299                         <widget source="TextTest6" render="Label" position="5,190" size="620,30" zPosition="10" font="Regular;20" halign="left" valign="center" backgroundColor="#25062748" transparent="1" />
300                         <widget source="TextTest7" render="Label" position="5,220" size="620,30" zPosition="10" font="Regular;20" halign="left" valign="center" backgroundColor="#25062748" transparent="1" />
301                 </screen>"""
302
303
304         def __init__(self, session, args = 0):
305                 self.session = session
306                 Screen.__init__(self, session)
307
308                 self.timer = eTimer()
309                 self.timer.callback.append(self.DoTest)
310                 self.timer.start(1000, True)
311
312                 self["TextTest1"] = StaticText()
313                 self["TextTest2"] = StaticText()
314                 self["TextTest3"] = StaticText()
315                 self["TextTest4"] = StaticText()
316                 self["TextTest5"] = StaticText()
317                 self["TextTest6"] = StaticText()
318                 self["TextTest7"] = StaticText()
319
320                 self["TextTest1"].setText(_("please wait (until 3min)..."))
321
322                 self["actions"] = ActionMap(["OkCancelActions"], 
323                 {
324                         "ok": self.cancel,
325                         "cancel": self.cancel
326                 }, -1)
327
328         def VoltUp(self):
329                 while GetFanRPM() < 100 and self.i < 255:
330                         setVoltage(self.id,self.i)
331                         time.sleep(0.3)
332                         self.i += 1
333
334         def VoltDown(self):
335                 while GetFanRPM() > 100 and self.i > 0:
336                         setVoltage(self.id,self.i)
337                         time.sleep(1)
338                         self.i -= 1
339
340         def DoTest(self):
341                 self.id = 0
342                 self.i = 0
343                 self.last = 0
344                 self.rpm = 0
345                 SaveAktVLT = AktVLT
346                 SaveAktPWM = AktPWM
347                 SaveFan = config.plugins.FanControl.Fan.value
348                 config.plugins.FanControl.Fan.value = "aus"
349                 if SaveFan in ["4pin","4pinREG"]:
350                         setPWM(self.id,0)
351                         time.sleep(10)
352                         while GetFanRPM() < 100 and self.i < 255:
353                                 setPWM(self.id,self.i)
354                                 time.sleep(0.3)
355                                 self.i += 1
356                         time.sleep(2)
357                         self.last=GetFanRPM()
358                         self["TextTest1"].setText(_("Min Fan Start %d rpm at PWM=%d") % (self.last, self.i))
359                         while GetFanRPM() > 100 and self.i > 1:
360                                 setPWM(self.id,self.i)
361                                 time.sleep(1)
362                                 self.i -= 1
363                         ok = ("OK" if config.plugins.FanControl.minRPM.value >= self.last else (("!!>%d" % config.plugins.FanControl.minRPM.value)))
364                         self["TextTest2"].setText(_("Min Fan Stop %d rpm at PWM=%d (%s)") % (self.last, self.i, ok))
365
366                         setPWM(self.id,255)
367                         time.sleep(6)
368                         self.rpm = GetFanRPM()
369                         ok = ("OK" if config.plugins.FanControl.maxRPM.value <= self.rpm else ("!!<%d" % (config.plugins.FanControl.maxRPM.value)))
370                         self["TextTest3"].setText(_("Max Fan %d rpm at PWM=255 (%s)") % (self.rpm, ok))
371 # extended
372                         self["TextTest4"].setText(_("Extended Control Range"))
373                         setPWM(self.id,0)
374                         time.sleep(10)
375                         self.rpm = GetFanRPM()
376                         if self.rpm > 0:
377                                 setVoltage(self.id,0)
378                                 time.sleep(10)
379                                 self.VoltUp()
380                                 time.sleep(3)
381                                 self.last=GetFanRPM()
382                                 self["TextTest5"].setText(_("Min Fan Start %d rpm at VLT=%d and PWM=0") % (self.last, self.i))
383                                 self.VoltDown()
384                                 ok = ("OK" if config.plugins.FanControl.minRPM.value >= self.last else (("!!>%d" % config.plugins.FanControl.minRPM.value)))
385                                 self["TextTest6"].setText(_("Min Fan Stop %d rpm at VLT=%d and PWM=0 (%s)") % (self.last, self.i, ok))
386
387                         setPWM(self.id,255)
388                         setVoltage(self.id,255)
389                         time.sleep(6)
390                         self.rpm = GetFanRPM()
391                         ok = ("OK" if config.plugins.FanControl.maxRPM.value <= self.rpm else ("!!<%d" % (config.plugins.FanControl.maxRPM.value)))
392                         self["TextTest7"].setText(_("Max Fan %d rpm at PWM=255 and VLT=255 (%s)") % (self.rpm, ok))
393
394                 elif SaveFan == "3pin":
395                         setVoltage(self.id,0)
396                         time.sleep(10)
397                         self.VoltUp()
398                         time.sleep(3)
399                         self.last=GetFanRPM()
400                         self["TextTest1"].setText(_("Min Fan Start %d rpm at VLT=%d") % (self.last, self.i))
401                         self.VoltDown()
402                         ok = ("OK" if config.plugins.FanControl.minRPM.value >= self.last else ("!!>%d" % (config.plugins.FanControl.minRPM.value)))
403                         self["TextTest2"].setText(_("Min Fan Stop %d rpm at VLT=%d (%s)") % (self.last, self.i, ok))
404
405                         setVoltage(self.id,255)
406                         time.sleep(6)
407                         ok = ("OK" if config.plugins.FanControl.maxRPM.value <= GetFanRPM() else ("!!<%d" % (config.plugins.FanControl.maxRPM.value)))
408                         self["TextTest3"].setText(_("Max Fan %d rpm at VLT=255 (%s)") % (GetFanRPM(), ok))
409
410                 else:
411                         self["TextTest1"].setText(_("please set fan type (3Pin or 4Pin)"))
412
413                 setVoltage(self.id,SaveAktVLT)
414                 setPWM(self.id,SaveAktPWM)
415                 config.plugins.FanControl.Fan.value = SaveFan
416
417         def cancel(self):
418                 self.close(False,self.session)
419
420 class FanControl2Monitor(Screen, ConfigListScreen):
421         skin = """
422                 <screen position="center,center" size="600,260" title="Fan Control 2 - Monitor">
423
424                         <widget source="TxtTemp0" render="Label" position="5,30" size="250,25" zPosition="1" font="Regular;17" halign="right" valign="center" backgroundColor="#25062748" transparent="1" />
425                         <widget source="TxtTemp1" render="Label" position="5,50" size="250,25" zPosition="1" font="Regular;17" halign="right" valign="center" backgroundColor="#25062748" transparent="1" />
426                         <widget source="TxtTemp2" render="Label" position="5,70" size="250,25" zPosition="1" font="Regular;17" halign="right" valign="center" backgroundColor="#25062748" transparent="1" />
427                         <widget source="TxtTemp3" render="Label" position="5,90" size="250,25" zPosition="1" font="Regular;17" halign="right" valign="center" backgroundColor="#25062748" transparent="1" />
428                         <widget source="TxtTemp4" render="Label" position="5,110" size="250,25" zPosition="1" font="Regular;17" halign="right" valign="center" backgroundColor="#25062748" transparent="1" />
429                         <widget source="TxtTemp5" render="Label" position="5,130" size="250,25" zPosition="1" font="Regular;17" halign="right" valign="center" backgroundColor="#25062748" transparent="1" />
430                         <widget source="TxtTemp6" render="Label" position="5,150" size="250,25" zPosition="1" font="Regular;17" halign="right" valign="center" backgroundColor="#25062748" transparent="1" />
431                         <widget source="TxtTemp7" render="Label" position="5,170" size="250,25" zPosition="1" font="Regular;17" halign="right" valign="center" backgroundColor="#25062748" transparent="1" />
432                         <widget source="TxtHDD" render="Label" position="5,190" size="250,25" zPosition="1" font="Regular;17" halign="right" valign="center" backgroundColor="#25062748" transparent="1" />
433                         <widget source="TxtFan" render="Label" position="5,210" size="250,25" zPosition="1" font="Regular;17" halign="right" valign="center" backgroundColor="#25062748" transparent="1" />
434                         <widget name="TxtMinTemp" position="260,20" size="50,12" zPosition="1" font="Regular;12" halign="left" valign="center" backgroundColor="#25062748" transparent="1" />
435                         <widget source="TxtFC2Temp" render="Label" position="398,20" size="50,12" zPosition="1" font="Regular;17" halign="center" valign="center" backgroundColor="#25062748" transparent="1" />
436                         <widget name="TxtMaxTemp" position="535,20" size="50,12" zPosition="1" font="Regular;12" halign="right" valign="center" backgroundColor="#25062748" transparent="1" />
437                         <widget source="ProTemp0" render="Progress" position="260,40" size="325,5" borderWidth="1" />
438                         <widget source="ProTemp1" render="Progress" position="260,60" size="325,5" borderWidth="1" />
439                         <widget source="ProTemp2" render="Progress" position="260,80" size="325,5" borderWidth="1" />
440                         <widget source="ProTemp3" render="Progress" position="260,100" size="325,5" borderWidth="1" />
441                         <widget source="ProTemp4" render="Progress" position="260,120" size="325,5" borderWidth="1" />
442                         <widget source="ProTemp5" render="Progress" position="260,140" size="325,5" borderWidth="1" />
443                         <widget source="ProTemp6" render="Progress" position="260,160" size="325,5" borderWidth="1" />
444                         <widget source="ProTemp7" render="Progress" position="260,180" size="325,5" borderWidth="1" />
445                         <widget source="ProHDD" render="Progress" position="260,200" size="325,5" borderWidth="1" />
446                         <widget source="ProFan" render="Progress" position="260,220" size="325,5" borderWidth="1" />
447
448                 </screen>"""
449         
450         def __init__(self, session, args = None):
451                 Screen.__init__(self, session)
452
453                 self.temp_timer = eTimer()
454                 self.temp_timer.callback.append(self.updateTemp)
455
456                 for count in range(8):
457                         self["ProTemp%d" % count] = Progress()
458                         self["TxtTemp%d" % count] = StaticText("")
459                 self["ProHDD"] = Progress()
460                 self["TxtHDD"] = StaticText("")
461                 self["ProFan"] = Progress()
462                 self["TxtFan"] = StaticText("")
463                 self["TxtFC2Temp"] = StaticText("")
464                 self["TxtMinTemp"] = Label("30")
465                 self["TxtMaxTemp"] = Label("55")
466
467                 self["actions"] = ActionMap(["OkCancelActions", "EPGSelectActions"], 
468                 {
469                         "ok": self.cancel,
470                         "cancel": self.cancel,
471                         "info": self.getHDD
472                 }, -1)
473
474                 self.onLayoutFinish.append(self.updateTemp)
475
476         def updateTemp(self):
477                 templist = sensors.getSensorsList(sensors.TYPE_TEMPERATURE)
478                 tempcount = len(templist)
479                 for count in range(tempcount):
480                         tt = sensors.getSensorValue(count)
481                         self["ProTemp%d" % count].value = int((tt-30)*100/(55-30)) 
482                         if sensors.getSensorName(count) == "undefined":
483                                 self["TxtTemp%d" % count].setText(_("%s   %02d C") % (TempName[count], tt))
484                         else:
485                                 self["TxtTemp%d" % count].setText(_("%s   %02d C") % (sensors.getSensorName(count), tt))
486                 if harddiskmanager.HDDCount() > 0 and len(AktHDD) > 0:
487                         if max(AktHDD) > 0:
488                                 self["ProHDD"].value = int((max(AktHDD)-30)*100/(55-30)) 
489                                 self["TxtHDD"].setText(_("%s   %02d C") % ("HDD", max(AktHDD)))
490                         elif config.plugins.FanControl.CheckHDDTemp.value !="never":
491                                 self["TxtHDD"].setText(_("press Info for HDD-Temp"))
492                 self["TxtFan"].setText(_("Current rpm  %4d") % (AktRPM))
493                 self["ProFan"].value = int((AktRPM-config.plugins.FanControl.minRPM.value)*100/Test0(config.plugins.FanControl.maxRPM.value-config.plugins.FanControl.minRPM.value))
494                 if tempcount>1:
495                         self["TxtFC2Temp"].setText("%4.1f" % AktTemp)
496                 self.temp_timer.start(2000, True)
497         
498         def cancel(self):
499                 self.close(False,self.session)
500
501         def getHDD(self):
502                 if harddiskmanager.HDDCount() > 0 and config.plugins.FanControl.CheckHDDTemp.value !="never":
503                         GetHDDtemp(True)
504                         for hdd in harddiskmanager.HDDList():
505                                 if hdd[1].model().startswith("ATA"):
506                                         if hdd[1].isSleeping():
507                                                 (stat,wert)=getstatusoutput("hdparm -y %s" % hdd[1].getDeviceName())
508
509 class FanControl2SpezialSetup(Screen, ConfigListScreen):
510         skin = """
511                 <screen position="center,center" size="600,380" title="Fan Control 2 - Setup" >
512                         <widget name="config" position="10,20" size="580,350" scrollbarMode="showOnDemand" />
513                 </screen>"""
514
515         def __init__(self, session, args = None):
516                 Screen.__init__(self, session)
517
518                 config.plugins.FanControl.DisableDMM.value = isDMMdisabled()
519                 self.HDDmode = config.plugins.FanControl.CheckHDDTemp.value
520                 self.MonitorMode = config.plugins.FanControl.MonitorInExtension.value
521                 self.FanControlMode = config.plugins.FanControl.FanControlInExtension.value
522
523                 self.list = []
524                 self.list.append(getConfigListEntry(_("Action in case of Fan failure"), config.plugins.FanControl.ShowError))
525                 self.list.append(getConfigListEntry(_("Box shutdown at Temperature (C)"), config.plugins.FanControl.ShutdownTemp))
526                 self.list.append(getConfigListEntry(_("increases overheating protection to (C)"), config.plugins.FanControl.AddOverheat))
527                 self.list.append(getConfigListEntry(_("read HDD-Temperature in HDD-Standby-Mode"), config.plugins.FanControl.CheckHDDTemp))
528                 self.list.append(getConfigListEntry(_("disable DMM-FanControl"), config.plugins.FanControl.DisableDMM))
529                 self.list.append(getConfigListEntry(_("Show Fan Speed as"), config.plugins.FanControl.Multi))
530                 self.list.append(getConfigListEntry(_("Show Plugin in Extension-Menu"), config.plugins.FanControl.FanControlInExtension))
531                 self.list.append(getConfigListEntry(_("Show Monitor in Extension-Menu"), config.plugins.FanControl.MonitorInExtension))
532                 self.list.append(getConfigListEntry(_("Number of WebIF-Log-Entries"), config.plugins.FanControl.LogCount))
533                 self.list.append(getConfigListEntry(_("Logging path"), config.plugins.FanControl.LogPath))
534                 self.list.append(getConfigListEntry(_("Enable Data Logging"), config.plugins.FanControl.EnableDataLog))
535                 self.list.append(getConfigListEntry(_("Auto-Delete Data older than (Days)"), config.plugins.FanControl.DeleteData))
536                 self.list.append(getConfigListEntry(_("Enable Event Logging"), config.plugins.FanControl.EnableEventLog))
537                 ConfigListScreen.__init__(self, self.list, session = self.session, on_change = self.selectionChanged)
538
539                 self["actions"] = ActionMap(["OkCancelActions"], 
540                 {
541                         "ok": self.keyOK,
542                         "cancel": self.cancel
543                 }, -1)
544
545         def keyOK(self):
546                 ConfigListScreen.keyOK(self)
547                 try:
548                         from Screens.LocationBox import LocationBox
549                         sel = self["config"].getCurrent()[1]
550                         if sel == config.plugins.FanControl.LogPath:
551                                 self.session.openWithCallback(self.dirSelected, LocationBox, text = _("Choose path"), filename = "", currDir = self["config"].getCurrent()[1].value, minFree = 50)
552                 except Exception, e:
553                         self.session.open(MessageBox, "Error:\n" + str(e), MessageBox.TYPE_ERROR)
554
555         def dirSelected(self, dir):
556                 if dir is not None and dir != "?":
557                         if dir[-1:] != "/":
558                                 dir += "/"
559                         config.plugins.FanControl.LogPath.value = dir
560         
561         def cancel(self):
562                 global disableHDDread
563                 if config.plugins.FanControl.LogPath.value[-1:] != "/":
564                         config.plugins.FanControl.LogPath.value += "/"
565                 NeuStart = False
566                 if os.path.exists("/usr/lib/enigma2/python/Components/FanControl.py"):
567                         if not isDMMdisabled() and config.plugins.FanControl.DisableDMM.value:
568                                 disableDMM()
569                                 NeuStart = True
570                         if isDMMdisabled() and not config.plugins.FanControl.DisableDMM.value:
571                                 enableDMM()
572                                 NeuStart = True
573                 if config.plugins.FanControl.CheckHDDTemp.value == "auto" and config.plugins.FanControl.CheckHDDTemp.value != self.HDDmode:
574                         disableHDDread = True
575                 if config.plugins.FanControl.MonitorInExtension.value != self.MonitorMode:
576                         NeuStart = True
577                 if config.plugins.FanControl.FanControlInExtension.value != self.FanControlMode:
578                         NeuStart = True
579
580                 for x in self["config"].list:
581                         x[1].save()
582
583                 if NeuStart:
584                         configfile.save()
585                         restartbox = self.session.openWithCallback(self.restartGUI,MessageBox,_("GUI needs a restart to apply the changes.\nDo you want to Restart the GUI now?"), MessageBox.TYPE_YESNO)
586                         restartbox.setTitle(_("Restart GUI now?"))
587                 else:
588                         self.close(False,self.session)
589
590         def selectionChanged(self):
591                 if not config.plugins.FanControl.EnableDataLog.value:
592                         return
593                 if config.plugins.FanControl.LogPath.value[-1:] != "/":
594                         config.plugins.FanControl.LogPath.value += "/"
595                 if not os.path.exists(config.plugins.FanControl.LogPath.value + "FC2data.csv") and Free(config.plugins.FanControl.LogPath.value):
596                         try:
597                                 f = open(config.plugins.FanControl.LogPath.value + "FC2data.csv","w")
598                                 try:
599                                         f.write(HeadLine)
600                                 except:
601                                         f.close()
602                         except IOError:
603                                 FClog("Data-Log-Error")
604
605         def restartGUI(self, answer):
606                 if answer is True:
607                         self.session.open(TryQuitMainloop, 3)
608                 else:
609                         self.close()
610
611 class FanControl2Plugin(ConfigListScreen,Screen):
612         skin = """
613                 <screen position="center,center" size="600,450" title="Fan Control 2">
614                         <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" alphatest="on" />
615                         <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" size="140,40" alphatest="on" />
616                         <ePixmap pixmap="skin_default/buttons/yellow.png" position="280,0" size="140,40" alphatest="on" />
617                         <ePixmap pixmap="skin_default/buttons/blue.png" position="420,0" size="140,40" alphatest="on" />
618                         <ePixmap pixmap="skin_default/buttons/key_info.png" position="560,0" zPosition="4" size="35,25"  transparent="1" alphatest="on" />
619                         <ePixmap pixmap="skin_default/buttons/key_menu.png" position="560,20" zPosition="4" size="35,25"  transparent="1" alphatest="on" />
620                         <widget source="red" render="Label" position="0,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#9f1313" transparent="1" />
621                         <widget source="green" render="Label" position="140,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#1f771f" transparent="1" />
622                         <widget source="yellow" render="Label" position="280,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#a08500" transparent="1" />
623                         <widget source="blue" render="Label" position="420,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#18188b" transparent="1" />
624                         <widget source="Version" render="Label" position="5,430" size="60,20" zPosition="1" font="Regular;11" halign="left" valign="center" backgroundColor="#25062748" transparent="1" />
625
626                         <widget name="config" position="10,50" size="580,200" scrollbarMode="showOnDemand" />
627                         <ePixmap position="20,260" size="560,3" pixmap="skin_default/div-h.png" transparent="1" alphatest="on" />
628                         <widget source="introduction" render="Label" position="5,262" size="580,30" zPosition="10" font="Regular;21" halign="center" valign="center" backgroundColor="#25062748" transparent="1" />
629                         <ePixmap position="20,290" size="560,3" pixmap="skin_default/div-h.png" transparent="1" alphatest="on" />
630                         <widget source="TxtTemp" render="Label" position="5,310" size="200,25" zPosition="1" font="Regular;17" halign="right" valign="center" backgroundColor="#25062748" transparent="1" />
631                         <widget source="TxtZielRPM" render="Label" position="5,330" size="200,25" zPosition="1" font="Regular;17" halign="right" valign="center" backgroundColor="#25062748" transparent="1" />
632                         <widget source="TxtRPM" render="Label" position="5,350" size="200,25" zPosition="1" font="Regular;17" halign="right" valign="center" backgroundColor="#25062748" transparent="1" />
633                         <widget source="TxtVLT" render="Label" position="5,370" size="200,25" zPosition="1" font="Regular;17" halign="right" valign="center" backgroundColor="#25062748" transparent="1" />
634                         <widget source="TxtPWM" render="Label" position="5,390" size="200,25" zPosition="1" font="Regular;17" halign="right" valign="center" backgroundColor="#25062748" transparent="1" />
635                         <widget source="PixTemp" render="Progress" position="210,320" size="375,5" borderWidth="1" />
636                         <widget source="PixZielRPM" render="Progress" position="210,340" size="375,5" borderWidth="1" />
637                         <widget source="PixRPM" render="Progress" position="210,360" size="375,5" borderWidth="1" />
638                         <widget source="PixVLT" render="Progress" position="210,380" size="375,5" borderWidth="1" />
639                         <widget source="PixPWM" render="Progress" position="210,400" size="375,5" borderWidth="1" />
640                         <widget source="TxtERR" render="Label" position="5,410" size="200,25" zPosition="1" font="Regular;17" halign="right" valign="center" backgroundColor="#25062748" transparent="1" />
641                         <widget source="PixERR" render="Progress" position="210,420" size="375,5" borderWidth="1" />
642                         <widget source="T10ERR" render="Label" position="570,422" size="40,20" zPosition="1" font="Regular;11" halign="left" valign="center" backgroundColor="#25062748" transparent="1" />
643                 </screen>"""
644
645         def __init__(self, session, args = 0):
646                 global LastVLT
647                 global LastPWM
648                 self.session = session
649                 Screen.__init__(self, session)
650
651                 self.fan_timer = eTimer()
652                 self.fan_timer.callback.append(self.updateFanStatus)
653
654                 self.list = []
655                 self.list.append(getConfigListEntry(_("Fan type"), config.plugins.FanControl.Fan))
656                 self.list.append(getConfigListEntry(_("Fan off in Idle Mode"), config.plugins.FanControl.StandbyOff))
657                 self.list.append(getConfigListEntry(_("min Speed rpm"), config.plugins.FanControl.minRPM))
658                 self.list.append(getConfigListEntry(_("max Speed rpm"), config.plugins.FanControl.maxRPM))
659                 self.list.append(getConfigListEntry(_("Static temp C"), config.plugins.FanControl.temp))
660                 self.list.append(getConfigListEntry(_("End temperature C"), config.plugins.FanControl.tempmax))
661                 self.list.append(getConfigListEntry(_("Initial Voltage"), config.plugins.FanControl.vlt))
662                 self.list.append(getConfigListEntry(_("Initial PWM"), config.plugins.FanControl.pwm))
663                 ConfigListScreen.__init__(self, self.list, session = self.session, on_change = self.selectionChanged)
664                 LastVLT = config.plugins.FanControl.vlt.value
665                 LastPWM = config.plugins.FanControl.pwm.value
666
667                 self["red"] = StaticText(_("Cancel"))
668                 self["green"] = StaticText(_("Save"))
669                 self["yellow"] = StaticText(_("Check"))
670                 self["blue"] = StaticText(_("Help"))
671                 self["introduction"] = StaticText()
672                 self["Version"] = StaticText(Version)
673                 self["TxtTemp"] = StaticText()
674                 self["TxtZielRPM"] = StaticText()
675                 self["TxtRPM"] = StaticText()
676                 self["TxtVLT"] = StaticText()
677                 self["TxtPWM"] = StaticText()
678                 self["PixTemp"] = Progress()
679                 self["PixZielRPM"] = Progress()
680                 self["PixRPM"] = Progress()
681                 self["PixVLT"] = Progress()
682                 self["PixPWM"] = Progress()
683                 self["PixERR"] = Progress()
684                 self["TxtERR"] = StaticText()
685                 self["T10ERR"] = StaticText()
686                 
687                 self["actions"] = ActionMap(["OkCancelActions", "ColorActions", "MenuActions", "EPGSelectActions"], 
688                 {
689                         "ok": self.save,
690                         "cancel": self.cancel,
691                         "red": self.cancel,
692                         "green": self.save,
693                         "yellow": self.pruefen,
694                         "blue": self.help,
695                         "menu": self.SetupMenu,
696                         "info": self.monitor
697                 }, -1)
698
699                 if not self.selectionChanged in self["config"].onSelectionChanged:
700                         self["config"].onSelectionChanged.append(self.selectionChanged)
701                 self.selectionChanged()
702                 self.onLayoutFinish.append(self.updateFanStatus)
703
704         def selectionChanged(self):
705                 global LastVLT
706                 global LastPWM
707                 global AktPWM
708                 global AktVLT
709                 global AktRPM
710                 self["introduction"].setText(_("Current value: %s") % (self.getCurrentValue()))
711                 if self["config"].getCurrentIndex() > 4:
712                         if LastVLT != config.plugins.FanControl.vlt.value or LastPWM !=config.plugins.FanControl.pwm.value:
713                                 LastVLT = config.plugins.FanControl.vlt.value
714                                 LastPWM = config.plugins.FanControl.pwm.value
715                                 AktVLT = LastVLT
716                                 AktPWM = LastPWM
717                                 id = 0
718                                 setVoltage(id,LastVLT)
719                                 setPWM(id,LastPWM)
720                                 AktRPM = GetFanRPM()
721                 d = config.plugins.FanControl.tempmax.value - config.plugins.FanControl.temp.value
722                 if d < 5:
723                         if config.plugins.FanControl.temp.value + d < 55:
724                                 config.plugins.FanControl.tempmax.value=config.plugins.FanControl.temp.value+5
725                         else:
726                                 config.plugins.FanControl.temp.value=config.plugins.FanControl.tempmax.value-5
727
728         def getCurrentValue(self):
729                 return str(self["config"].getCurrent()[1].getText())
730
731         def updateFanStatus(self):
732                 global ZielRPM
733                 global AktTemp
734                 global AktVLT
735                 global AktPWM
736                 global AktRPM
737                 if config.plugins.FanControl.Fan.value == "disabled":
738                         AktTemp = 0
739                         AktVLT = 0
740                         AktPWM = 0
741                         ZielRPM = 0
742                         AktRPM = 0
743                 self["TxtTemp"].setText(_("Temperature C  %4.1f") % (AktTemp))
744                 self["TxtZielRPM"].setText(_("Target rpm  %4d") % (ZielRPM))
745                 self["TxtRPM"].setText(_("Current rpm  %4d") % (AktRPM))
746                 self["TxtVLT"].setText(_("Voltage  %03d") % (AktVLT))
747                 self["TxtPWM"].setText(_("PWM  %03d") % (AktPWM))
748                 self["PixTemp"].value = int((AktTemp-config.plugins.FanControl.temp.value)*100/Test0(config.plugins.FanControl.tempmax.value-config.plugins.FanControl.temp.value))
749                 self["PixZielRPM"].value = int((ZielRPM-config.plugins.FanControl.minRPM.value)*100/Test0(config.plugins.FanControl.maxRPM.value-config.plugins.FanControl.minRPM.value))
750                 self["PixRPM"].value = int((AktRPM-config.plugins.FanControl.minRPM.value)*100/Test0(config.plugins.FanControl.maxRPM.value-config.plugins.FanControl.minRPM.value))
751                 self["PixVLT"].value = int(AktVLT/2.55)
752                 self["PixPWM"].value = int(AktPWM/2.55)
753                 if config.plugins.FanControl.Fan.value == "4pinREG":
754                         if int(abs(ErrRPM)) <= 10 and ErrRPM != 0:
755                                 self["PixERR"].value = int(abs(ErrRPM)*10)
756                                 self["T10ERR"].setText("10%")
757                         else:   
758                                 self["PixERR"].value = int(abs(ErrRPM))
759                                 self["T10ERR"].setText("")
760                         self["TxtERR"].setText(_("PID Ctl Err %03.2f %%") % ErrRPM)
761                 else:
762                         self["TxtERR"].setText("")
763                 self.fan_timer.start(2000, True)
764
765         def save(self):
766                 for x in self["config"].list:
767                         x[1].save()
768                 self.close(True,self.session)
769
770         def cancel(self):
771                 for x in self["config"].list:
772                         x[1].cancel()
773                 self.close(False,self.session)
774
775         def pruefen(self):
776                 self.session.open(FanControl2Test)
777
778         def monitor(self):
779                 self.session.open(FanControl2Monitor)
780
781         def help(self):
782                 self.session.open(Console,_("Information"),["cat /usr/lib/enigma2/python/Plugins/Extensions/FanControl2/%s" % _("readme.txt")])
783
784         def SetupMenu(self):
785                 self.session.open(FanControl2SpezialSetup)
786
787 def DeleteData():
788         if config.plugins.FanControl.DeleteData.value == "0" or config.plugins.FanControl.EnableDataLog.value == False:
789                 return
790         try:
791                 FClog("Auto-Delete Data")
792                 f = open(config.plugins.FanControl.LogPath.value + "FC2data.csv","a")
793                 s = f.tell()
794                 f.close()
795                 if s < 150:
796                         return
797                 f = open(config.plugins.FanControl.LogPath.value + "FC2data.csv","r")
798                 f.seek(s-100)
799                 line = f.readline()
800                 line = f.readline()
801                 DT = line.split(";")
802                 DT = DT[0].split(" ")
803                 DD = DT[0].split(".")
804                 DD48h = datetime.date(int(DD[0]),int(DD[1]),int(DD[2])) - datetime.timedelta(int(config.plugins.FanControl.DeleteData.value))
805                 Dfind = "%04d.%02d.%02d %s" % (DD48h.year,DD48h.month,DD48h.day,DT[1])
806                 f.seek(0)
807                 line = f.readline()
808                 fw = open(config.plugins.FanControl.LogPath.value + "FC2data.csv.tmp","w")
809                 fw.write(HeadLine)
810                 for line in f.readlines():
811                         DT = line.split(";")
812                         if DT[0] > Dfind:
813                                 fw.write(line)
814                 f.close()
815                 fw.close()
816                 if os.path.exists(config.plugins.FanControl.LogPath.value + "FC2data.csv"):
817                         os.remove(config.plugins.FanControl.LogPath.value + "FC2data.csv")
818                 os.rename(config.plugins.FanControl.LogPath.value + "FC2data.csv.tmp",config.plugins.FanControl.LogPath.value + "FC2data.csv")
819         except Exception:
820                 FClog("Error Delete Data")
821
822 def getstatusoutput(cmd):
823         try:
824                 pipe = os.popen('{ ' + cmd + '; } 2>&1', 'r')
825                 text = pipe.read()
826                 sts = pipe.close()
827                 if sts is None: sts = 0
828                 if text[-1:] == '\n': text = text[:-1]
829         except:
830                 sts = 1
831                 text = ""
832                 FClog("Error on call OS program (smartctl/hdparm)")
833         finally:
834                 return sts, text
835
836 def HDDtestTemp():
837         global disableHDDread
838         if harddiskmanager.HDDCount() > 0 and config.plugins.FanControl.CheckHDDTemp.value !="never":
839                 disableHDDread = False
840                 for hdd in harddiskmanager.HDDList():
841                         if hdd[1].model().startswith("ATA"):
842                                 FClog("%s %s Mode:%s" % (hdd[1].model(), hdd[1].getDeviceName(), config.plugins.FanControl.CheckHDDTemp.value))
843                                 if config.plugins.FanControl.CheckHDDTemp.value == "auto":
844                                         (stat,wert)=getstatusoutput("hdparm -y %s" % hdd[1].getDeviceName())
845                                         time.sleep(0.5)
846                                         (stat,wert)=ReadHDDtemp(hdd[1].getDeviceName())
847                                         if stat != 0:
848                                                 (stat,wert)=getstatusoutput("smartctl --smart=on %s" % hdd[1].getDeviceName())
849                                                 FClog("HDD Temperature not readable -> Ignore")
850                                                 FC2HDDignore.append(hdd[1].getDeviceName())
851                                         time.sleep(0.5)
852                                         (stat,wert)=getstatusoutput("hdparm -C %s" % hdd[1].getDeviceName())
853                                         if wert.find("standby")>0:
854                                                 FClog("HDD supports Temp reading without Spinup")
855                                         else:
856                                                 if hdd[1].isSleeping():
857                                                         (stat,wert)=getstatusoutput("hdparm -y %s" % hdd[1].getDeviceName())
858                                                 FClog("HDD not supports Temp reading without Spinup -> Ignore")
859                                                 FC2HDDignore.append(hdd[1].getDeviceName())
860
861 def ReadHDDtemp(D):
862         return getstatusoutput("smartctl -A %s | grep \"194 Temp\" | grep Always" % D)
863
864 def GetHDDtemp(OneTime):
865         global AktHDD
866         AktHDD = []
867         if harddiskmanager.HDDCount() > 0 and config.plugins.FanControl.CheckHDDTemp.value != "never" or OneTime == True:
868                 for hdd in harddiskmanager.HDDList():
869                         if hdd[1].model().startswith("ATA") and hdd[1].getDeviceName() not in FC2HDDignore:
870                                 sleeptime = int((time.time() - hdd[1].last_access))
871 #                               FClog("HDD Temp reading %s %s %ds %s" % (config.plugins.FanControl.CheckHDDTemp.value, disableHDDread, sleeptime, hdd[1].isSleeping()))
872                                 if config.plugins.FanControl.CheckHDDTemp.value == "true" or (config.plugins.FanControl.CheckHDDTemp.value == "auto" and not disableHDDread) or ((not hdd[1].isSleeping()) and sleeptime < 120) or OneTime == True:
873                                         (stat,wert)=ReadHDDtemp(hdd[1].getDeviceName())
874                                         if stat == 0:
875                                                 try:
876                                                         AktHDD.append(int(wert[wert.find("Always")+6:].replace(" ","").replace("-","")[:2]))
877                                                 except:
878                                                         AktHDD.append(0)
879                                         if len(AktHDD) == 0:
880                                                 AktHDD = [0]
881                                         FClog("HDD Temp %dC" % (AktHDD[-1]))
882         if len(AktHDD) == 0:
883                 AktHDD = [0]
884         return
885
886 def HDDsSleeping(): 
887         for hdd in harddiskmanager.HDDList():
888                 if hdd[1].model().startswith("ATA"):
889                         if not hdd[1].isSleeping():
890                                 return False
891         return True
892
893 def FC2systemStatus():
894         S = int(FC2werte[5])
895         R = " -" if S>0 else " "
896         if (S & 1)>0 :
897                 R += " BoxOn"
898         if (S & 2)>0 :
899                 R += " HDDon"
900         if (S & 4)>0 :
901                 R += " REC"
902         return R
903
904 class FC2Worker(Thread): 
905         def __init__(self,index,s,session):
906                 Thread.__init__(self)
907                 self.index = index
908                 self.session = session
909                 self.s = s
910  
911         def run(self): 
912                 global FritzTime
913                 while True:
914 #                       print "worker a", self.index
915                         zahl = Briefkasten.get()
916                         if zahl == 1:
917                                 self.s.queryRun()
918  
919                         Briefkasten.task_done() 
920
921 class FanControl2(Screen):
922         skin = """ <screen position="100,100" size="300,300" title="FanControl2" > </screen>"""
923
924         RPMController = ControllerPI("RPMController")
925
926         def __init__(self,session):
927                 global Box
928                 Screen.__init__(self,session)
929                 self.session = session
930                 self.FanMin     = 500
931                 self.FanMax     = 1500
932                 self.targetTemp = 50.0
933                 self.maxTemp    = 55.0
934                 self.Range      = 5
935                 self.Fan        = "aus"
936                 self.dontshutdown = False
937                 # RPM PI controller initialization - later
938                 self.RPMController.timer_delay = 10.0
939                 self.RPMController.dt = 10.0
940                 self.RPMController.inputMax = 4000.0
941                 self.RPMController.inputDeadband = 1.0
942                 self.RPMController.coeffKp = 0.1
943                 self.RPMController.coeffKi = 0.25
944                 FClog("Starting up")
945                 if os.path.exists("/usr/lib/enigma2/python/Plugins/Extensions/FanControl2/data/diagram.class.org"):
946                         os.rename("/usr/lib/enigma2/python/Plugins/Extensions/FanControl2/data/diagram.class.org","/usr/lib/enigma2/python/Plugins/Extensions/FanControl2/data/diagram.class")
947                 if not isDMMdisabled() and config.plugins.FanControl.DisableDMM.value:
948                         disableDMM()
949                 Box = GetBox()
950                 HDDtestTemp()
951                 GetHDDtemp(False)
952                 DeleteData()
953                 FC2threads = [FC2Worker(i,self,session) for i in range(3)] 
954                 for thread in FC2threads: 
955                         thread.setDaemon(True) 
956                         thread.start() 
957                 self.timer = eTimer()
958                 if self.query not in self.timer.callback:
959                         self.timer.callback.append(self.query)
960                 self.timer.startLongTimer(10)
961                 config.misc.standbyCounter.addNotifier(self.standbyQuery, initial_call = False)
962
963         def FC2AskShutdown(self):
964                 if not self.dontshutdown:
965                         self.dontshutdown = True
966                         self.session.openWithCallback(self.FC2DoShutdown, MessageBox, _("FanControl2 emergency, Box Shutdown now?"),type = MessageBox.TYPE_YESNO,timeout = 60)
967
968         def FC2DoShutdown(self,retval):
969                 if (retval):
970                         if Standby.inTryQuitMainloop == False:
971                                 self.session.open(Standby.TryQuitMainloop, 1)
972
973         def stop(self):
974                 FClog("Stop")
975                 if self.query in self.timer.callback:
976                         self.timer.callback.remove(self.query)
977                 self.timer.stop()
978
979         def CurrTemp(self):
980                 m1 = 0.1
981                 m2 = 0.1
982                 ti = [0,0,0,0,0,0,0,0,0,0]
983                 templist = sensors.getSensorsList(sensors.TYPE_TEMPERATURE)
984                 tempcount = len(templist)
985                 for count in range(tempcount):
986                         tt = sensors.getSensorValue(count)
987                         ti[count] = tt
988                         if m1 < tt:
989                                 mi = count
990                                 m1 = tt
991                 for count in range(tempcount):
992                         if m2 < ti[count] and count != mi:
993                                 m2 = ti[count]
994                 if m2 == 0.1:
995                         m2 = m1
996                 return (m1 + m2) / 2.0
997                 
998         def cycle(self):
999                 self.Range = self.maxTemp - self.targetTemp
1000                 x = AktTemp - self.targetTemp
1001                 rpm = skal(x, 0, self.Range, self.FanMin, self.FanMax)
1002                 return rpm
1003
1004         def standbyQuery(self, configElement):
1005                 Standby.inStandby.onClose.append(self.query)
1006                 self.query()
1007
1008         def query(self):
1009                 self.timer.stop()
1010                 if config.plugins.FanControl.Fan.value != "disabled":
1011                         if FC2doThread == True:
1012                                 if Briefkasten.qsize()<=3:
1013                                         Briefkasten.put(1) 
1014                                 else:
1015                                         FClog("Queue full, Thread hanging?")
1016                         else:
1017                                 self.queryRun()
1018                 self.timer.startLongTimer(10)
1019                 
1020         def queryRun(self):
1021                 global FirstStart
1022                 global istStandbySave
1023                 global Overheat
1024                 global OverheatTimer
1025                 global FanOffWait
1026                 global RPMread
1027                 global RPMdiff
1028                 global FanFehler            
1029                 global ZielRPM
1030                 global AktRPM
1031                 global AktTemp
1032                 global AktVLT
1033                 global AktPWM
1034         
1035                 global AktPWMCTL
1036                 global IntegralRPM      
1037                 global ErrRPM
1038                 global Recording
1039                 tt = time.time()
1040                 try:
1041                         if self.targetTemp != config.plugins.FanControl.temp.value:
1042                                 self.RPMController.ResetIntegrator() 
1043                         self.targetTemp = config.plugins.FanControl.temp.value
1044                         self.maxTemp    = config.plugins.FanControl.tempmax.value
1045                         self.Fan        = config.plugins.FanControl.Fan.value
1046                         self.Vlt        = config.plugins.FanControl.vlt.value
1047                         self.HDDidle    = True
1048                         id = 0
1049                         AktRPMtmp = 0
1050                         sleeptime = 0
1051                         AktTemp = self.CurrTemp()
1052                         Recording = self.session.nav.RecordTimer.isRecording()
1053                         if AktTemp >= config.plugins.FanControl.ShutdownTemp.value:
1054                                 FClog("Emergency Shutdown")
1055                                 self.FC2AskShutdown()
1056                         if harddiskmanager.HDDCount() > 0:
1057                                 self.HDDidle = HDDsSleeping()
1058                                 if int(strftime("%S")) < 10 and strftime("%M")[-1:] == "0":
1059                                         GetHDDtemp(False)
1060                                         if strftime("%H:%M") == "00:00":
1061                                                 DeleteData()
1062                         S=0
1063                         if not Standby.inStandby:
1064                                 S+=1
1065                         if not self.HDDidle:
1066                                 S+=2
1067                         if Recording:
1068                                 S+=4
1069                         FC2werte[5]=str(S)
1070
1071                         if (Standby.inStandby) and (not Overheat) and ((config.plugins.FanControl.StandbyOff.value == "true") or ((config.plugins.FanControl.StandbyOff.value == "trueRec") and (not Recording and self.HDDidle))):
1072                                 FClog("Fan Off Temp: %d %s" % (AktTemp,FC2systemStatus()))
1073                                 setVoltage(id,0)
1074                                 setPWM(id,0)
1075                                 FC2werte[0] = AktTemp
1076                                 FC2werte[1] = 0
1077                                 FC2werte[2] = 0
1078                                 FC2werte[3] = 0
1079 #                               FC2werte[4] = str(AktHDD)[1:-1].replace(",","")
1080                                 FC2werte[4] = max(AktHDD) if len(AktHDD) > 0 else 0
1081                                 FCdata()
1082                                 FirstStart = True
1083                                 OverheatTemp = self.maxTemp + config.plugins.FanControl.AddOverheat.value
1084                                 OverheatTimer = 0
1085                                 FanOffWait = True
1086                                 if OverheatTemp > 65:
1087                                         OverheatTemp = 65
1088                                 if AktTemp > OverheatTemp:
1089                                         Overheat = True
1090                                         FClog("Overheat")
1091                         else:
1092                                 if (Overheat and AktTemp < self.maxTemp-3) or not Standby.inStandby:
1093                                         Overheat = False
1094                                 AktVLTtmp = getVoltage(id)
1095                                 if Standby.inStandby and Standby.inStandby == istStandbySave and RPMdiff == 1 and not Recording:
1096                                         tmp = GetFanRPM()
1097                                         RPMdiff = AktRPM-tmp
1098                                         if RPMdiff < 150 or tmp < 300 or self.Fan == "3pin":
1099                                                 RPMdiff = 0
1100                                         else:
1101                                                 if config.plugins.FanControl.minRPM.value - RPMdiff < 300:
1102                                                         RPMdiff = config.plugins.FanControl.minRPM.value - 300
1103                                                 FClog("RPM-Range shifted -%drpm" % RPMdiff)
1104                                 if not Standby.inStandby:
1105                                         RPMdiff = 0
1106                                 self.FanMin = config.plugins.FanControl.minRPM.value - RPMdiff
1107                                 self.FanMax = config.plugins.FanControl.maxRPM.value - RPMdiff
1108                                 if Standby.inStandby != istStandbySave or AktVLT != AktVLTtmp:
1109                                         istStandbySave = Standby.inStandby
1110                                         AktVLTtmp = AktVLT
1111                                         setVoltage(id,AktVLT)
1112                                         setPWM(id,AktPWM)
1113                                         RPMdiff = 1
1114                                         FClog("Fan Reset")
1115                                 if (AktVLT + AktPWM) == 0:
1116                                         FirstStart = True
1117                                 if FirstStart == True:
1118                                         FirstStart = False
1119                                         AktVLTtmp = self.Vlt
1120                                         setVoltage(id,self.Vlt)
1121                                         setPWM(id,config.plugins.FanControl.pwm.value)
1122                                 AktRPMtmp = GetFanRPM()
1123                                 if RPMread>0 and RPMread<3:
1124                                         FClog("Reread")
1125                                         if FC2doThread == True:
1126                                                 if Briefkasten.qsize()<=2:
1127                                                         time.sleep(0.4)
1128                                                         Briefkasten.put(1) 
1129                                         else:
1130                                                 self.timer.start(400, True)
1131                                         return
1132                                 RPMread = 0
1133                                 if AktRPMtmp > 6000:
1134                                         FClog("ignore high RPM")
1135                                         return
1136                                 AktRPM = AktRPMtmp
1137                                 AktVLT = AktVLTtmp
1138                                 AktPWM = getPWM(id)
1139                                 if AktVLT > 255:
1140                                         AktVLT = 255
1141                                 FClog("Vlt:%d Pwm:%d Fan:%s Pid:%.2f%%  %s" % (AktVLT,AktPWM,self.Fan,ErrRPM,FC2systemStatus()))
1142                                 FC2werte[0] = AktTemp
1143                                 FC2werte[1] = AktRPM
1144                                 FC2werte[2] = AktVLT
1145                                 FC2werte[3] = AktPWM
1146                                 FC2werte[4] = max(AktHDD) if len(AktHDD) > 0 else 0
1147                                 FCdata()
1148                                 if int(strftime("%M")) == 0:
1149                                         FC2stunde[int(strftime("%H"))] = "%4.1f<BR>%d" % (AktTemp,AktRPM)
1150                                 ZielRPM = self.cycle()
1151                                 if (FanOffWait and OverheatTimer < 30) or (Overheat and OverheatTimer < 60):
1152                                         ZielRPM = self.FanMin
1153                                         OverheatTimer += 1
1154                                         FClog("FanStartTimeout set MinRPM (%d)" % (OverheatTimer)) 
1155                                 else:
1156                                         FanOffWait = False
1157                                 FClog(_("currentRPM:%d targetRPM:%d Temp:%4.1f") % (AktRPM,ZielRPM,AktTemp))
1158                                 if ZielRPM > 0 and AktRPM == 0:
1159                                         FanFehler += 1
1160                                         if FanFehler > 90:
1161                                                 FanFehler -= 18
1162                                                 FClog("Fan Error")
1163                                                 if config.plugins.FanControl.ShowError.value == "true" and not Standby.inStandby:
1164                                                         Notifications.AddNotification(MessageBox, _("Fan is not working!"), type=MessageBox.TYPE_INFO, timeout=5)
1165                                                 if config.plugins.FanControl.ShowError.value == "shutdown":
1166                                                         self.FC2AskShutdown()
1167                                 else:
1168                                         FanFehler = 0
1169                                 if self.Fan == "4pin":
1170                                         if AktPWM < 255 and AktPWM > 0 and AktVLT != self.Vlt:
1171                                                 AktVLT = (AktVLT-1 if AktVLT > self.Vlt else AktVLT+1)
1172                                                 setVoltage(id,AktVLT)
1173                                         if AktRPM+29 < ZielRPM:
1174                                                 AktPWM = (AktPWM+5 if ZielRPM-AktRPM > 100 else AktPWM+1)
1175                                                 setPWM(id,AktPWM)
1176                                                 if AktPWM >= 255 and AktVLT < 255:
1177                                                         AktVLT += 1
1178                                                         setVoltage(id,AktVLT)
1179                                         elif AktRPM-19 > ZielRPM:
1180                                                 AktPWM = (AktPWM-5 if AktRPM-ZielRPM > 100 else AktPWM-1)
1181                                                 setPWM(id,AktPWM)
1182 # 4
1183                                                 if AktPWM < 0 and AktVLT > 5:
1184                                                         AktVLT -= 1
1185                                                         setVoltage(id,AktVLT)
1186                                         if AktVLT > self.Vlt:
1187                                                 AktPWM = 256
1188                                         if AktPWM < 0:
1189                                                 AktPWM = 0
1190                                 elif self.Fan == "4pinREG":
1191                                         AktPWM = self.RPMController.ControlLoop(ZielRPM, AktRPM)
1192                                         ErrRPM = self.RPMController.inputError
1193                                         if AktPWM > 255.0:
1194                                                 AktVLT = 0.12*(AktPWM - 255.0) + int(config.plugins.FanControl.vlt.value)
1195                                         else:
1196                                                 AktVLT = int(config.plugins.FanControl.vlt.value)       # this will set voltage to initial value
1197                                         if AktVLT > 255:
1198                                                 AktVLT = 255
1199                                         if AktVLT < 0:
1200                                                 AktVLT = 0
1201                                         if AktPWM > 255:
1202                                                 AktPWM = 255
1203                                         if AktPWM < 0:
1204                                                 AktPWM = 0
1205                                         setVoltage(id,int(AktVLT))
1206                                         setPWM(id,int(AktPWM))
1207                                 elif self.Fan == "3pin":
1208                                         if AktRPM+29 < ZielRPM:
1209                                                 AktVLT = (AktVLT+5 if ZielRPM-AktRPM > 100 else AktVLT+1)
1210                                                 setVoltage(id,AktVLT)
1211                                         elif AktRPM-19 > ZielRPM:
1212                                                 AktVLT = (AktVLT-5 if AktRPM-ZielRPM > 100 else AktVLT-1)
1213                                                 setVoltage(id,AktVLT)
1214
1215                 except Exception:
1216 #                       FClog("Control Error")
1217 #                       import traceback, sys
1218 #                       traceback.print_exc(file=sys.stdout)
1219                         from traceback import format_exc
1220                         FClog("Control Error:\n" + format_exc() )
1221 ##                      import traceback, sys
1222 ##                      traceback.print_exc(file=sys.stdout)
1223                 FClogE("Runtime: %.3f" % (time.time() - tt) )
1224
1225 def autostart(reason, **kwargs):
1226         global session
1227         if reason == 0 and kwargs.has_key("session"):
1228                 if os.path.exists("/usr/lib/enigma2/python/Plugins/Extensions/WebInterface/__init__.pyc") or os.path.exists("/usr/lib/enigma2/python/Plugins/Extensions/WebInterface/__init__.pyo"):
1229                         from Plugins.Extensions.WebInterface.WebChilds.Toplevel import addExternalChild
1230                         from FC2webSite import FC2web, FC2webLog, FC2webChart
1231                         from twisted.web import static
1232                         root = static.File("/usr/lib/enigma2/python/Plugins/Extensions/FanControl2/data")
1233 #                       root = FC2web()
1234                         root.putChild("", FC2web())
1235                         root.putChild("log", FC2webLog())
1236                         root.putChild("chart", FC2webChart())
1237                         if os.path.exists("/usr/lib/enigma2/python/Plugins/Extensions/WebInterface/web/external.xml"):
1238                                 try:
1239                                         addExternalChild( ("fancontrol", root, "Fan Control 2", Version, True) )
1240                                         FClog("use new WebIF")
1241                                 except:
1242                                         addExternalChild( ("fancontrol", root) )
1243                                         FClog("use old WebIF")
1244                         if os.path.exists("/usr/lib/enigma2/python/Plugins/Extensions/OpenWebif/pluginshook.src"):
1245                                 try:
1246                                         addExternalChild( ("fancontrol", root, "Fan Control 2", Version) )
1247                                         FClog("use new OpenWebIF")
1248                                 except:
1249                                         pass
1250                 if not os.path.exists("/proc/stb/fp/fan_vlt"):
1251                         Notifications.AddNotification(MessageBox, _("Box has no fancontrol hardware -> FC2 deactivated"), type=MessageBox.TYPE_INFO, timeout=10)
1252                         FClog("not supported, exit")
1253                         return
1254                 session = kwargs["session"]
1255                 session.open(FanControl2)
1256           
1257 def Plugins(**kwargs):
1258         list = [
1259         PluginDescriptor(name="Fan Control", 
1260         description="Fan Control 2", 
1261         where = [PluginDescriptor.WHERE_SESSIONSTART, 
1262         PluginDescriptor.WHERE_AUTOSTART], 
1263         fnc = autostart)]
1264         if os.path.exists("/proc/stb/fp/fan_vlt"):
1265                 list.append(PluginDescriptor(name="Fan Control 2", 
1266                 description="Fan Control", 
1267                 where = PluginDescriptor.WHERE_PLUGINMENU,
1268                 icon = "plugin.png",
1269                 fnc = main))
1270                 if config.plugins.FanControl.FanControlInExtension.value:
1271                         list.append(PluginDescriptor(name="Fan Control 2", 
1272                         description="Fan Control", 
1273                         where = PluginDescriptor.WHERE_EXTENSIONSMENU,
1274                         icon = "plugin.png",
1275                         fnc = main))
1276                 if config.plugins.FanControl.MonitorInExtension.value:
1277                         list.append(PluginDescriptor(
1278                         name="Fan Control 2 - Monitor", 
1279                         description="Fan Control", 
1280                         where = PluginDescriptor.WHERE_EXTENSIONSMENU,
1281                         icon = "plugin.png",
1282                         fnc = mainMonitor))
1283         return list