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