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