fix crash because of unneeded and "un__init__ed" ConfigListScreen in FanControl2Test
[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() or "0", 16)
119
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() or "0", 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.EnableConsoleLog = ConfigYesNo(default = False)
161 config.plugins.FanControl.EnableDataLog = ConfigYesNo(default = False)
162 config.plugins.FanControl.EnableEventLog = ConfigYesNo(default = False)
163 config.plugins.FanControl.CheckHDDTemp = ConfigSelection(choices = [("false", _("no")), ("true", _("yes")), ("auto", _("auto")), ("never", _("never"))], default="auto")
164 config.plugins.FanControl.MonitorInExtension = ConfigYesNo(default = True)
165 config.plugins.FanControl.FanControlInExtension = ConfigYesNo(default = True)
166 config.plugins.FanControl.Multi = ConfigSelection(choices = [("1", "RPM"), ("2", "RPM/2")], default = "2")
167 config.plugins.FanControl.EnableThread = ConfigYesNo(default = True)
168
169 def GetFanRPM():
170         global RPMread
171         f = open("/proc/stb/fp/fan_speed", "r")
172         value = int(f.readline().strip()[:-4] or "0")
173         f.close()
174         value = int(value / int(config.plugins.FanControl.Multi.value))
175         if value > 0 and value < 6000:
176                 RPMread = 0
177         else:
178                 RPMread += 1
179         return value
180
181 def GetBox():
182         B = Box
183         if os.path.exists("/proc/stb/info/model"):
184                 f = open("/proc/stb/info/model")
185                 B = f.readline()
186                 f.close()
187         return B
188
189 def isDMMdisabled():
190         value = False
191         if os.path.exists("/usr/lib/enigma2/python/Components/FanControl.py"):
192                 FCfile = open("/usr/lib/enigma2/python/Components/FanControl.py", "r")
193                 text=FCfile.read()
194                 FCfile.close()
195                 if text.find("#Disabled by FC2 config.misc.standbyCounter.addNotifier") is not -1:
196                         value = True
197         return value
198
199 def disableDMM():
200         if os.path.exists("/usr/lib/enigma2/python/Components/FanControl.py"):
201                 FCfile = open("/usr/lib/enigma2/python/Components/FanControl.py", "r")
202                 text=FCfile.read()
203                 FCfile.close()
204                 FCfile = open("/usr/lib/enigma2/python/Components/FanControl.py", "w")
205                 text=text.replace("config.misc.standbyCounter.addNotifier","#Disabled by FC2 config.misc.standbyCounter.addNotifier")
206                 text=FCfile.write(text)
207                 FCfile.close()
208                 FClog("DMM-fancontrol disabled - please restart E2")
209
210 def enableDMM():
211         if os.path.exists("/usr/lib/enigma2/python/Components/FanControl.py"):
212                 FCfile = open("/usr/lib/enigma2/python/Components/FanControl.py", "r")
213                 text=FCfile.read()
214                 FCfile.close()
215                 FCfile = open("/usr/lib/enigma2/python/Components/FanControl.py", "w")
216                 text=text.replace("#Disabled by FC2 config.misc.standbyCounter.addNotifier","config.misc.standbyCounter.addNotifier")
217                 text=FCfile.write(text)
218                 FCfile.close()
219
220 # the PI controller class
221 class ControllerPI:
222         name = "PI Controller"
223         looptime = 0.0
224         dt = 0.0
225         timer_delay = 0.0
226         inputMax = 0.0
227         inputError = 0.0
228         inputDeadband = 0.0
229         integratorOutput = 0.0
230         controlSignal = 0.0
231         coeffKp = 0.0
232         coeffKi = 0.0
233  
234         def __init__(self, givenName = "PI Controller"):
235                 self.name = givenName
236 #               FClogE("%s : creating object" % self.name)
237
238         def ReturnInputError(self):
239                 return self.inputError
240       
241         def ResetIntegrator(self):
242                 FClogE("%s : integrator output %3.2f" % (self.name, self.integratorOutput))
243                 self.integratorOutput = 0.0
244 #               FClog("%s : integrator output now 0" % self.name)
245
246
247         def ScaleCtlError(self,errval,inputMax):
248                 if errval == 0:
249                         return 0
250                 return skal(abs(errval), 0, inputMax , 0, 100) * (errval/abs(errval))
251
252         def DeadBand(self,errval):
253                 if abs(errval) < self.inputDeadband:
254                         FClogE("%s : error within bounds %3.2f %% < %3.2f %%, WON'T control" % (self.name, abs(errval), self.inputDeadband))
255                         return 0.0
256                 else:
257                         FClogE("%s : error EXCEEDS bounds %3.2f %% > %3.2f %%, will control" % (self.name, abs(errval), self.inputDeadband))
258                         return errval
259
260         def Integrate(self,errval):
261                 self.integratorOutput += errval*self.dt
262                 return self.integratorOutput
263
264         def ControlProcess(self,InputError, integratorOutput):
265                 return self.coeffKp*InputError + self.coeffKi*integratorOutput
266
267         def ControlLoop(self, ctlInput, ctlFeedback):
268                 if self.dt < self.timer_delay:
269                         FClogE("%s : WRONG SETTINGS! dt must be >= timer_delay! Adjusted to be same for now.")
270                         self.dt = self.timer_delay
271
272                 self.looptime += self.timer_delay
273                 if self.looptime < self.dt:
274                         FClogE("%s : NOT calling control, looptime %d < %d dt" % (self.name, self.looptime, self.dt))
275                         return Self.ControlSignal
276                 else:
277                         FClogE("%s : calling control, looptime %d = %d dt" % (self.name, self.looptime, self.dt))
278                         self.looptime = 0
279
280                 self.inputError = ctlInput - ctlFeedback
281                 FClogE("%s : made up Input Error %3.2f" % (self.name, self.inputError))
282                 self.inputError = self.ScaleCtlError(self.inputError, self.inputMax)
283                 FClogE("%s : after scale: Input Error %3.2f %%" % (self.name, self.inputError))
284                 self.inputError = self.DeadBand(self.inputError)
285                 FClogE("%s : after deadband: Input Error %3.2f %%" % (self.name, self.inputError))
286                 self.IntegratorOutput = self.Integrate(self.inputError)
287                 FClogE("%s : Integrator output %3.2f %%" % (self.name, self.IntegratorOutput))
288                 self.ControlSignal = self.ControlProcess(self.inputError,self.IntegratorOutput)
289                 FClogE("%s : Control Signal %3.2f %%" % (self.name, self.ControlSignal))
290                 return self.ControlSignal
291 # the PI controller class -end
292
293 class FanControl2Test(Screen):
294         skin = """
295                 <screen position="center,center" size="620,300" title="Fan Control 2 - Test" >
296                         <widget source="TextTest1" render="Label" position="5,20" size="610,30" zPosition="10" font="Regular;20" halign="left" valign="center" backgroundColor="#25062748" transparent="1" />
297                         <widget source="TextTest2" render="Label" position="5,50" size="610,30" zPosition="10" font="Regular;20" halign="left" valign="center" backgroundColor="#25062748" transparent="1" />
298                         <widget source="TextTest3" render="Label" position="5,80" size="610,30" zPosition="10" font="Regular;20" halign="left" valign="center" backgroundColor="#25062748" transparent="1" />
299                         <widget source="TextTest4" render="Label" position="5,130" size="610,30" zPosition="10" font="Regular;20" halign="left" valign="center" backgroundColor="#25062748" transparent="1" />
300                         <widget source="TextTest5" render="Label" position="5,160" size="610,30" zPosition="10" font="Regular;20" halign="left" valign="center" backgroundColor="#25062748" transparent="1" />
301                         <widget source="TextTest6" render="Label" position="5,190" size="610,30" zPosition="10" font="Regular;20" halign="left" valign="center" backgroundColor="#25062748" transparent="1" />
302                         <widget source="TextTest7" render="Label" position="5,220" size="610,30" zPosition="10" font="Regular;20" halign="left" valign="center" backgroundColor="#25062748" transparent="1" />
303                 </screen>"""
304
305
306         def __init__(self, session, args = 0):
307                 self.session = session
308                 Screen.__init__(self, session)
309
310                 self.timer = eTimer()
311                 self.timer_conn = self.timer.timeout.connect(self.DoTest)
312                 self.timer.start(1000, True)
313
314                 self["TextTest1"] = StaticText()
315                 self["TextTest2"] = StaticText()
316                 self["TextTest3"] = StaticText()
317                 self["TextTest4"] = StaticText()
318                 self["TextTest5"] = StaticText()
319                 self["TextTest6"] = StaticText()
320                 self["TextTest7"] = StaticText()
321
322                 self["TextTest1"].setText(_("please wait (until 3min)..."))
323
324                 self["actions"] = ActionMap(["OkCancelActions"], 
325                 {
326                         "ok": self.cancel,
327                         "cancel": self.cancel
328                 }, -1)
329
330         def VoltUp(self):
331                 while GetFanRPM() < 100 and self.i < 255:
332                         setVoltage(self.id,self.i)
333                         time.sleep(0.3)
334                         self.i += 1
335
336         def VoltDown(self):
337                 while GetFanRPM() > 100 and self.i > 0:
338                         setVoltage(self.id,self.i)
339                         time.sleep(1)
340                         self.i -= 1
341
342         def DoTest(self):
343                 self.id = 0
344                 self.i = 1
345                 self.last = 0
346                 self.rpm = 0
347                 SaveAktVLT = AktVLT
348                 SaveAktPWM = AktPWM
349                 SaveFan = config.plugins.FanControl.Fan.value
350                 config.plugins.FanControl.Fan.value = "aus"
351                 if SaveFan in ["4pin","4pinREG"]:
352                         setPWM(self.id,self.i)
353                         time.sleep(10)
354                         while GetFanRPM() < 100 and self.i < 255:
355                                 setPWM(self.id,self.i)
356                                 time.sleep(0.3)
357                                 self.i += 1
358                         time.sleep(2)
359                         self.last=GetFanRPM()
360                         self["TextTest1"].setText(_("Min Fan Start %d rpm at PWM=%d") % (self.last, self.i))
361                         while GetFanRPM() > 100 and self.i > 1:
362                                 setPWM(self.id,self.i)
363                                 time.sleep(1)
364                                 self.i -= 1
365                         ok = ("OK" if config.plugins.FanControl.minRPM.value >= self.last else (("!!>%d" % config.plugins.FanControl.minRPM.value)))
366                         self["TextTest2"].setText(_("Min Fan Stop %d rpm at PWM=%d (%s)") % (self.last, self.i, ok))
367
368                         setPWM(self.id,255)
369                         time.sleep(6)
370                         self.rpm = GetFanRPM()
371                         ok = ("OK" if config.plugins.FanControl.maxRPM.value <= self.rpm else ("!!<%d" % (config.plugins.FanControl.maxRPM.value)))
372                         self["TextTest3"].setText(_("Max Fan %d rpm at PWM=255 (%s)") % (self.rpm, ok))
373 # extended
374                         self["TextTest4"].setText(_("Extended Control Range"))
375                         setPWM(self.id,0)
376                         time.sleep(10)
377                         self.rpm = GetFanRPM()
378                         if self.rpm > 0:
379                                 setVoltage(self.id,0)
380                                 time.sleep(10)
381                                 self.VoltUp()
382                                 time.sleep(3)
383                                 self.last=GetFanRPM()
384                                 self["TextTest5"].setText(_("Min Fan Start %d rpm at VLT=%d and PWM=0") % (self.last, self.i))
385                                 self.VoltDown()
386                                 ok = ("OK" if config.plugins.FanControl.minRPM.value >= self.last else (("!!>%d" % config.plugins.FanControl.minRPM.value)))
387                                 self["TextTest6"].setText(_("Min Fan Stop %d rpm at VLT=%d and PWM=0 (%s)") % (self.last, self.i, ok))
388
389                         setPWM(self.id,255)
390                         setVoltage(self.id,255)
391                         time.sleep(6)
392                         self.rpm = GetFanRPM()
393                         ok = ("OK" if config.plugins.FanControl.maxRPM.value <= self.rpm else ("!!<%d" % (config.plugins.FanControl.maxRPM.value)))
394                         self["TextTest7"].setText(_("Max Fan %d rpm at PWM=255 and VLT=255 (%s)") % (self.rpm, ok))
395
396                 elif SaveFan == "3pin":
397                         setVoltage(self.id,0)
398                         time.sleep(10)
399                         self.VoltUp()
400                         time.sleep(3)
401                         self.last=GetFanRPM()
402                         self["TextTest1"].setText(_("Min Fan Start %d rpm at VLT=%d") % (self.last, self.i))
403                         self.VoltDown()
404                         ok = ("OK" if config.plugins.FanControl.minRPM.value >= self.last else ("!!>%d" % (config.plugins.FanControl.minRPM.value)))
405                         self["TextTest2"].setText(_("Min Fan Stop %d rpm at VLT=%d (%s)") % (self.last, self.i, ok))
406
407                         setVoltage(self.id,255)
408                         time.sleep(6)
409                         ok = ("OK" if config.plugins.FanControl.maxRPM.value <= GetFanRPM() else ("!!<%d" % (config.plugins.FanControl.maxRPM.value)))
410                         self["TextTest3"].setText(_("Max Fan %d rpm at VLT=255 (%s)") % (GetFanRPM(), ok))
411
412                 else:
413                         self["TextTest1"].setText(_("please set fan type (3Pin or 4Pin)"))
414
415                 setVoltage(self.id,SaveAktVLT)
416                 setPWM(self.id,SaveAktPWM)
417                 config.plugins.FanControl.Fan.value = SaveFan
418
419         def cancel(self):
420                 self.close(False,self.session)
421
422 class FanControl2Monitor(Screen):
423         skin = """
424                 <screen position="center,center" size="620,300" title="Fan Control 2 - Monitor">
425
426                         <widget source="TxtTemp0" render="Label" position="5,30" size="250,25" zPosition="1" font="Regular;17" halign="right" valign="center" backgroundColor="#25062748" transparent="1" />
427                         <widget source="TxtTemp1" render="Label" position="5,50" size="250,25" zPosition="1" font="Regular;17" halign="right" valign="center" backgroundColor="#25062748" transparent="1" />
428                         <widget source="TxtTemp2" render="Label" position="5,70" size="250,25" zPosition="1" font="Regular;17" halign="right" valign="center" backgroundColor="#25062748" transparent="1" />
429                         <widget source="TxtTemp3" render="Label" position="5,90" size="250,25" zPosition="1" font="Regular;17" halign="right" valign="center" backgroundColor="#25062748" transparent="1" />
430                         <widget source="TxtTemp4" render="Label" position="5,110" size="250,25" zPosition="1" font="Regular;17" halign="right" valign="center" backgroundColor="#25062748" transparent="1" />
431                         <widget source="TxtTemp5" render="Label" position="5,130" size="250,25" zPosition="1" font="Regular;17" halign="right" valign="center" backgroundColor="#25062748" transparent="1" />
432                         <widget source="TxtTemp6" render="Label" position="5,150" size="250,25" zPosition="1" font="Regular;17" halign="right" valign="center" backgroundColor="#25062748" transparent="1" />
433                         <widget source="TxtTemp7" render="Label" position="5,170" size="250,25" zPosition="1" font="Regular;17" halign="right" valign="center" backgroundColor="#25062748" transparent="1" />
434                         <widget source="TxtHDD" render="Label" position="5,190" size="250,25" zPosition="1" font="Regular;17" halign="right" valign="center" backgroundColor="#25062748" transparent="1" />
435                         <widget source="TxtFan" render="Label" position="5,210" size="250,25" zPosition="1" font="Regular;17" halign="right" valign="center" backgroundColor="#25062748" transparent="1" />
436                         <widget name="TxtMinTemp" position="260,20" size="50,12" zPosition="1" font="Regular;12" halign="left" valign="center" backgroundColor="#25062748" transparent="1" />
437                         <widget source="TxtFC2Temp" render="Label" position="398,20" size="50,12" zPosition="1" font="Regular;17" halign="center" valign="center" backgroundColor="#25062748" transparent="1" />
438                         <widget name="TxtMaxTemp" position="535,20" size="50,12" zPosition="1" font="Regular;12" halign="right" valign="center" backgroundColor="#25062748" transparent="1" />
439                         <widget source="ProTemp0" render="Progress" position="260,40" size="325,5" borderWidth="1" />
440                         <widget source="ProTemp1" render="Progress" position="260,60" size="325,5" borderWidth="1" />
441                         <widget source="ProTemp2" render="Progress" position="260,80" size="325,5" borderWidth="1" />
442                         <widget source="ProTemp3" render="Progress" position="260,100" size="325,5" borderWidth="1" />
443                         <widget source="ProTemp4" render="Progress" position="260,120" size="325,5" borderWidth="1" />
444                         <widget source="ProTemp5" render="Progress" position="260,140" size="325,5" borderWidth="1" />
445                         <widget source="ProTemp6" render="Progress" position="260,160" size="325,5" borderWidth="1" />
446                         <widget source="ProTemp7" render="Progress" position="260,180" size="325,5" borderWidth="1" />
447                         <widget source="ProHDD" render="Progress" position="260,200" size="325,5" borderWidth="1" />
448                         <widget source="ProFan" render="Progress" position="260,220" size="325,5" borderWidth="1" />
449
450                 </screen>"""
451         
452         def __init__(self, session, args = None):
453                 Screen.__init__(self, session)
454
455                 self.temp_timer = eTimer()
456                 self.temp_timer_conn = self.temp_timer.timeout.connect(self.updateTemp)
457
458                 for count in range(8):
459                         self["ProTemp%d" % count] = Progress()
460                         self["TxtTemp%d" % count] = StaticText("")
461                 self["ProHDD"] = Progress()
462                 self["TxtHDD"] = StaticText("")
463                 self["ProFan"] = Progress()
464                 self["TxtFan"] = StaticText("")
465                 self["TxtFC2Temp"] = StaticText("")
466                 self["TxtMinTemp"] = Label("30")
467                 self["TxtMaxTemp"] = Label("55")
468
469                 self["actions"] = ActionMap(["OkCancelActions", "EPGSelectActions"], 
470                 {
471                         "ok": self.cancel,
472                         "cancel": self.cancel,
473                         "info": self.getHDD
474                 }, -1)
475
476                 self.onLayoutFinish.append(self.updateTemp)
477
478         def updateTemp(self):
479                 templist = sensors.getSensorsList(sensors.TYPE_TEMPERATURE)
480                 tempcount = len(templist)
481                 for count in range(tempcount):
482                         tt = sensors.getSensorValue(count)
483                         self["ProTemp%d" % count].value = int((tt-30)*100/(55-30)) 
484                         if sensors.getSensorName(count) == "undefined":
485                                 self["TxtTemp%d" % count].setText(_("%s   %02d C") % (TempName[count], tt))
486                         else:
487                                 self["TxtTemp%d" % count].setText(_("%s   %02d C") % (sensors.getSensorName(count), tt))
488                 if harddiskmanager.HDDCount() > 0 and len(AktHDD) > 0:
489                         if max(AktHDD) > 0:
490                                 self["ProHDD"].value = int((max(AktHDD)-30)*100/(55-30)) 
491                                 self["TxtHDD"].setText(_("%s   %02d C") % ("HDD", max(AktHDD)))
492                         elif config.plugins.FanControl.CheckHDDTemp.value !="never":
493                                 self["TxtHDD"].setText(_("press Info for HDD-Temp"))
494                 self["TxtFan"].setText(_("Current rpm  %4d") % (AktRPM))
495                 self["ProFan"].value = int((AktRPM-config.plugins.FanControl.minRPM.value)*100/Test0(config.plugins.FanControl.maxRPM.value-config.plugins.FanControl.minRPM.value))
496                 if tempcount>1:
497                         self["TxtFC2Temp"].setText("%4.1f" % AktTemp)
498                 self.temp_timer.start(2000, True)
499         
500         def cancel(self):
501                 self.close(False,self.session)
502
503         def getHDD(self):
504                 if harddiskmanager.HDDCount() > 0 and config.plugins.FanControl.CheckHDDTemp.value !="never":
505                         GetHDDtemp(True)
506                         for hdd in harddiskmanager.HDDList():
507                                 if hdd[1].model().startswith("ATA"):
508                                         if hdd[1].isSleeping():
509                                                 (stat,wert)=getstatusoutput("hdparm -y %s" % hdd[1].getDeviceName())
510
511 class FanControl2SpezialSetup(Screen, ConfigListScreen):
512         skin = """
513                 <screen position="center,120" size="820,520" title="Fan Control 2 - Setup" >
514                         <widget name="config" position="10,10" size="800,450" enableWrapAround="1" scrollbarMode="showOnDemand" />
515                 </screen>"""
516
517         def __init__(self, session, args = None):
518                 Screen.__init__(self, session)
519
520                 config.plugins.FanControl.DisableDMM.value = isDMMdisabled()
521                 self.HDDmode = config.plugins.FanControl.CheckHDDTemp.value
522                 self.MonitorMode = config.plugins.FanControl.MonitorInExtension.value
523                 self.FanControlMode = config.plugins.FanControl.FanControlInExtension.value
524
525                 self.list = []
526                 self.list.append(getConfigListEntry(_("Action in case of Fan failure"), config.plugins.FanControl.ShowError))
527                 self.list.append(getConfigListEntry(_("Box shutdown at Temperature (C)"), config.plugins.FanControl.ShutdownTemp))
528                 self.list.append(getConfigListEntry(_("increases overheating protection to (C)"), config.plugins.FanControl.AddOverheat))
529                 self.list.append(getConfigListEntry(_("read HDD-Temperature in HDD-Standby-Mode"), config.plugins.FanControl.CheckHDDTemp))
530                 self.list.append(getConfigListEntry(_("disable DMM-FanControl"), config.plugins.FanControl.DisableDMM))
531                 self.list.append(getConfigListEntry(_("Show Fan Speed as"), config.plugins.FanControl.Multi))
532                 self.list.append(getConfigListEntry(_("Show Plugin in Extension-Menu"), config.plugins.FanControl.FanControlInExtension))
533                 self.list.append(getConfigListEntry(_("Show Monitor in Extension-Menu"), config.plugins.FanControl.MonitorInExtension))
534                 self.list.append(getConfigListEntry(_("Enable Console Logging"), config.plugins.FanControl.EnableConsoleLog))
535                 self.list.append(getConfigListEntry(_("Number of WebIF-Log-Entries"), config.plugins.FanControl.LogCount))
536                 self.list.append(getConfigListEntry(_("Logging path"), config.plugins.FanControl.LogPath))
537                 self.list.append(getConfigListEntry(_("Enable Data Logging"), config.plugins.FanControl.EnableDataLog))
538                 self.list.append(getConfigListEntry(_("Auto-Delete Data older than (Days)"), config.plugins.FanControl.DeleteData))
539                 self.list.append(getConfigListEntry(_("Enable Event Logging"), config.plugins.FanControl.EnableEventLog))
540                 self.list.append(getConfigListEntry(_("Enable Thread use"), config.plugins.FanControl.EnableThread))
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,120" size="820,520" title="Fan Control 2">
618                         <ePixmap pixmap="skin_default/buttons/red.png" position="10,5" size="200,40" alphatest="on" />
619                         <ePixmap pixmap="skin_default/buttons/green.png" position="210,5" size="200,40" alphatest="on" />
620                         <ePixmap pixmap="skin_default/buttons/yellow.png" position="410,5" size="200,40" alphatest="on" />
621                         <ePixmap pixmap="skin_default/buttons/blue.png" position="610,5" size="200,40" alphatest="on" />
622                         <widget source="red" render="Label" position="10,5" size="200,40" zPosition="1" font="Regular;20" halign="center" valign="center" backgroundColor="#9f1313" transparent="1" shadowColor="black" shadowOffset="-2,-2" />
623                         <widget source="green" render="Label" position="210,5" size="200,40" zPosition="1" font="Regular;20" halign="center" valign="center" backgroundColor="#1f771f" transparent="1" shadowColor="black" shadowOffset="-2,-2" />
624                         <widget source="yellow" render="Label" position="410,5" size="200,40" zPosition="1" font="Regular;20" halign="center" valign="center" backgroundColor="#a08500" transparent="1" shadowColor="black" shadowOffset="-2,-2" />
625                         <widget source="blue" render="Label" position="610,5" size="200,40" zPosition="1" font="Regular;20" halign="center" valign="center" backgroundColor="#18188b" transparent="1" shadowColor="black" shadowOffset="-2,-2" />
626                         <eLabel position="10,50" size="800,1" backgroundColor="grey" />
627                         <widget name="config" position="10,60" size="800,240" enableWrapAround="1" scrollbarMode="showOnDemand" />
628                         <eLabel position="10,310" size="800,1" backgroundColor="grey" />
629                         <widget source="introduction" render="Label" position="10,320" size="800,30" font="Regular;21" halign="center"/>
630                         <widget source="TxtTemp" render="Label" position="20,360" size="200,25" font="Regular;17" halign="right" valign="center" />
631                         <widget source="TxtZielRPM" render="Label" position="20,380" size="200,25" font="Regular;17" halign="right" valign="center" />
632                         <widget source="TxtRPM" render="Label" position="20,400" size="200,25" font="Regular;17" halign="right" valign="center" />
633                         <widget source="TxtVLT" render="Label" position="20,420" size="200,25" font="Regular;17" halign="right" valign="center" />
634                         <widget source="TxtPWM" render="Label" position="20,440" size="200,25" font="Regular;17" halign="right" valign="center" />
635                         <widget source="PixTemp" render="Progress" position="230,370" size="400,5" borderWidth="1" />
636                         <widget source="PixZielRPM" render="Progress" position="230,390" size="400,5" borderWidth="1" />
637                         <widget source="PixRPM" render="Progress" position="230,410" size="400,5" borderWidth="1" />
638                         <widget source="PixVLT" render="Progress" position="230,430" size="400,5" borderWidth="1" />
639                         <widget source="PixPWM" render="Progress" position="230,450" size="400,5" borderWidth="1" />
640                         <widget source="TxtERR" render="Label" position="20,460" size="200,25" font="Regular;17" halign="right" valign="center" />
641                         <widget source="PixERR" render="Progress" position="230,470" size="400,5" borderWidth="1" />
642                         <widget source="T10ERR" render="Label" position="650,472" size="40,20" font="Regular;11" halign="left" valign="center" />
643                         <widget source="Version" render="Label" position="10,490" size="100,22" font="Regular;18" />
644                         <ePixmap pixmap="skin_default/buttons/key_info.png" position="720,490" size="40,20" alphatest="on" />
645                         <ePixmap pixmap="skin_default/buttons/key_menu.png" position="770,490" size="40,20" alphatest="on" />
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                 self.timer_conn = self.timer.timeout.connect(self.query)
970                 self.timer.startLongTimer(10)
971                 config.misc.standbyCounter.addNotifier(self.standbyQuery, initial_call = False)
972
973         def FC2AskShutdown(self):
974                 if not self.dontshutdown:
975                         self.dontshutdown = True
976                         self.session.openWithCallback(self.FC2DoShutdown, MessageBox, _("FanControl2 emergency, Box Shutdown now?"),type = MessageBox.TYPE_YESNO,timeout = 60)
977
978         def FC2DoShutdown(self,retval):
979                 if (retval):
980                         if Standby.inTryQuitMainloop == False:
981                                 self.session.open(Standby.TryQuitMainloop, 1)
982
983         def stop(self):
984                 FClog("Stop")
985                 self.timer_conn = None
986                 self.timer.stop()
987
988         def CurrTemp(self):
989                 m1 = 0.1
990                 m2 = 0.1
991                 ti = [0,0,0,0,0,0,0,0,0,0]
992                 templist = sensors.getSensorsList(sensors.TYPE_TEMPERATURE)
993                 tempcount = len(templist)
994                 for count in range(tempcount):
995                         tt = sensors.getSensorValue(count)
996                         ti[count] = tt
997                         if m1 < tt:
998                                 mi = count
999                                 m1 = tt
1000                 for count in range(tempcount):
1001                         if m2 < ti[count] and count != mi:
1002                                 m2 = ti[count]
1003                 if m2 == 0.1:
1004                         m2 = m1
1005                 return (m1 + m2) / 2.0
1006                 
1007         def cycle(self):
1008                 self.Range = self.maxTemp - self.targetTemp
1009                 x = AktTemp - self.targetTemp
1010                 rpm = skal(x, 0, self.Range, self.FanMin, self.FanMax)
1011                 return rpm
1012
1013         def standbyQuery(self, configElement):
1014                 Standby.inStandby.onClose.append(self.query)
1015                 self.query()
1016
1017         def query(self):
1018                 global FanFehler
1019                 self.timer.stop()
1020                 if config.plugins.FanControl.Fan.value != "disabled":
1021                         self.Recording = self.session.nav.RecordTimer.isRecording()
1022                         self.inStandby = Standby.inStandby
1023                         if harddiskmanager.HDDCount() > 0 and int(strftime("%S")) < 10:
1024                                 self.HDDidle = HDDsSleeping()
1025                                 if strftime("%M")[-1:] == "0":
1026                                         GetHDDtemp(False)
1027                         if config.plugins.FanControl.EnableThread.value == True:
1028                                 if Briefkasten.qsize()<=3:
1029                                         Briefkasten.put(1) 
1030                                 else:
1031                                         FClog("Queue full, Thread hanging?")
1032                         else:
1033                                 self.queryRun()
1034                         if ZielRPM > 0 and AktRPM == 0:
1035                                 FanFehler += 1
1036                                 if FanFehler > 90:
1037                                         FanFehler -= 18
1038                                         FClog("Fan Error")
1039                                         if config.plugins.FanControl.ShowError.value == "true" and not self.inStandby:
1040                                                 Notifications.AddNotification(MessageBox, _("Fan is not working!"), type=MessageBox.TYPE_INFO, timeout=5)
1041                                         if config.plugins.FanControl.ShowError.value == "shutdown":
1042                                                 self.FC2AskShutdown()
1043                         else:
1044                                 FanFehler = 0
1045                         if AktTemp >= config.plugins.FanControl.ShutdownTemp.value:
1046                                 FClog("Emergency Shutdown %dC" % AktTemp)
1047                                 self.FC2AskShutdown()
1048                 self.timer.startLongTimer(10)
1049                 
1050         def queryRun(self):
1051                 global FirstStart
1052                 global istStandbySave
1053                 global Overheat
1054                 global OverheatTimer
1055                 global FanOffWait
1056                 global RPMread
1057                 global RPMdiff
1058                 global FanFehler            
1059                 global ZielRPM
1060                 global AktRPM
1061                 global AktTemp
1062                 global AktVLT
1063                 global AktPWM
1064
1065                 global AktPWMCTL
1066                 global IntegralRPM      
1067                 global ErrRPM
1068                 tt = time.time()
1069                 try:
1070                         if self.targetTemp != config.plugins.FanControl.temp.value:
1071                                 self.RPMController.ResetIntegrator() 
1072                         self.targetTemp = config.plugins.FanControl.temp.value
1073                         self.maxTemp    = config.plugins.FanControl.tempmax.value
1074                         self.Fan        = config.plugins.FanControl.Fan.value
1075                         self.Vlt        = config.plugins.FanControl.vlt.value
1076                         id = 0
1077                         AktRPMtmp = 0
1078                         sleeptime = 0
1079                         AktTemp = self.CurrTemp()
1080                         if int(strftime("%S")) < 10 and strftime("%H:%M") == "00:00":
1081                                 DeleteData()
1082                         S=0
1083                         if not self.inStandby:
1084                                 S+=1
1085                         if not self.HDDidle:
1086                                 S+=2
1087                         if self.Recording:
1088                                 S+=4
1089                         FC2werte[5]=str(S)
1090
1091                         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))):
1092                                 FClog("Fan Off Temp: %d %s" % (AktTemp,FC2systemStatus()))
1093                                 setVoltage(id,0)
1094                                 setPWM(id,0)
1095                                 FC2werte[0] = AktTemp
1096                                 FC2werte[1] = 0
1097                                 FC2werte[2] = 0
1098                                 FC2werte[3] = 0
1099 #                               FC2werte[4] = str(AktHDD)[1:-1].replace(",","")
1100                                 FC2werte[4] = max(AktHDD) if len(AktHDD) > 0 else 0
1101                                 FCdata()
1102                                 FirstStart = True
1103                                 OverheatTemp = self.maxTemp + config.plugins.FanControl.AddOverheat.value
1104                                 OverheatTimer = 0
1105                                 FanOffWait = True
1106                                 if OverheatTemp > 65:
1107                                         OverheatTemp = 65
1108                                 if AktTemp > OverheatTemp:
1109                                         Overheat = True
1110                                         FClog("Overheat")
1111                         else:
1112                                 if (Overheat and AktTemp < self.maxTemp-3) or not self.inStandby:
1113                                         Overheat = False
1114                                 AktVLTtmp = getVoltage(id)
1115                                 AktPWMtmp = getPWM(id)
1116                                 if self.inStandby and self.inStandby == istStandbySave and RPMdiff == 1 and not self.Recording:
1117                                         tmp = GetFanRPM()
1118                                         RPMdiff = AktRPM-tmp
1119                                         if RPMdiff < 150 or tmp < 300 or self.Fan == "3pin":
1120                                                 RPMdiff = 0
1121                                         else:
1122                                                 if config.plugins.FanControl.minRPM.value - RPMdiff < 300:
1123                                                         RPMdiff = config.plugins.FanControl.minRPM.value - 300
1124                                                 FClog("RPM-Range shifted -%drpm" % RPMdiff)
1125                                 if not self.inStandby:
1126                                         RPMdiff = 0
1127                                 self.FanMin = config.plugins.FanControl.minRPM.value - RPMdiff
1128                                 self.FanMax = config.plugins.FanControl.maxRPM.value - RPMdiff
1129                                 if self.inStandby != istStandbySave or AktVLT != AktVLTtmp or AktPWM != AktPWMtmp:
1130                                         istStandbySave = self.inStandby
1131                                         if istStandbySave == True:
1132                                                 Standby.inStandby.onClose.append(FC2fanReset)
1133                                         FC2fanReset()
1134                                         AktVLTtmp = AktVLT
1135                                         RPMdiff = 1
1136                                         AktVLTtmp = getVoltage(id)
1137                                         AktPWMtmp = getPWM(id)
1138                                         if AktVLT != AktVLTtmp or AktPWM != AktPWMtmp:
1139                                                 time.sleep(2)
1140                                                 FC2fanReset()
1141                                 if (AktVLT + AktPWM) == 0:
1142                                         FirstStart = True
1143                                 if FirstStart == True:
1144                                         FirstStart = False
1145                                         AktVLTtmp = self.Vlt
1146                                         setVoltage(id,self.Vlt)
1147                                         setPWM(id,config.plugins.FanControl.pwm.value)
1148                                 AktRPMtmp = GetFanRPM()
1149                                 if RPMread>0 and RPMread<3:
1150                                         FClog("Reread")
1151                                         if config.plugins.FanControl.EnableThread.value == True:
1152                                                 if Briefkasten.qsize()<=2:
1153                                                         time.sleep(0.4)
1154                                                         Briefkasten.put(1) 
1155                                         else:
1156                                                 self.timer.start(400, True)
1157                                         return
1158                                 RPMread = 0
1159                                 if AktRPMtmp > 6000:
1160                                         FClog("ignore high RPM")
1161                                         return
1162                                 AktRPM = AktRPMtmp
1163                                 AktVLT = AktVLTtmp
1164                                 AktPWM = getPWM(id)
1165                                 if AktVLT > 255:
1166                                         AktVLT = 255
1167                                 FClog("Vlt:%d Pwm:%d Fan:%s Pid:%.2f%%  %s" % (AktVLT,AktPWM,self.Fan,ErrRPM,FC2systemStatus()))
1168                                 FC2werte[0] = AktTemp
1169                                 FC2werte[1] = AktRPM
1170                                 FC2werte[2] = AktVLT
1171                                 FC2werte[3] = AktPWM
1172                                 FC2werte[4] = max(AktHDD) if len(AktHDD) > 0 else 0
1173                                 FCdata()
1174                                 if int(strftime("%M")) == 0:
1175                                         FC2stunde[int(strftime("%H"))] = "%4.1f<BR>%d" % (AktTemp,AktRPM)
1176                                 ZielRPM = self.cycle()
1177                                 if (FanOffWait and OverheatTimer < 30) or (Overheat and OverheatTimer < 60):
1178                                         ZielRPM = self.FanMin
1179                                         OverheatTimer += 1
1180                                         FClog("FanStartTimeout set MinRPM (%d)" % (OverheatTimer)) 
1181                                 else:
1182                                         FanOffWait = False
1183                                 FClog(_("currentRPM:%d targetRPM:%d Temp:%4.1f") % (AktRPM,ZielRPM,AktTemp))
1184                                 if self.Fan == "4pin":
1185                                         if AktPWM < 255 and AktPWM > 0 and AktVLT != self.Vlt:
1186                                                 AktVLT = (AktVLT-1 if AktVLT > self.Vlt else AktVLT+1)
1187                                                 setVoltage(id,AktVLT)
1188                                         if AktRPM+29 < ZielRPM:
1189                                                 AktPWM = (AktPWM+5 if ZielRPM-AktRPM > 100 else AktPWM+1)
1190                                                 setPWM(id,AktPWM)
1191                                                 if AktPWM >= 255 and AktVLT < 255:
1192                                                         AktVLT += 1
1193                                                         setVoltage(id,AktVLT)
1194                                         elif AktRPM-19 > ZielRPM:
1195                                                 AktPWM = (AktPWM-5 if AktRPM-ZielRPM > 100 else AktPWM-1)
1196                                                 setPWM(id,AktPWM)
1197 # 4
1198                                                 if AktPWM < 0 and AktVLT > 5:
1199                                                         AktVLT -= 1
1200                                                         setVoltage(id,AktVLT)
1201                                         if AktVLT > self.Vlt:
1202                                                 AktPWM = 256
1203                                         if AktPWM < 0:
1204                                                 AktPWM = 0
1205                                 elif self.Fan == "4pinREG":
1206                                         AktPWM = self.RPMController.ControlLoop(ZielRPM, AktRPM)
1207                                         ErrRPM = self.RPMController.inputError
1208                                         if AktPWM > 255.0:
1209                                                 AktVLT = 0.12*(AktPWM - 255.0) + int(config.plugins.FanControl.vlt.value)
1210                                         else:
1211                                                 AktVLT = int(config.plugins.FanControl.vlt.value)       # this will set voltage to initial value
1212                                         if AktVLT > 255:
1213                                                 AktVLT = 255
1214                                         if AktVLT < 0:
1215                                                 AktVLT = 0
1216                                         if AktPWM > 255:
1217                                                 AktPWM = 255
1218                                         if AktPWM < 0:
1219                                                 AktPWM = 0
1220                                         setVoltage(id,int(AktVLT))
1221                                         setPWM(id,int(AktPWM))
1222                                 elif self.Fan == "3pin":
1223                                         if AktRPM+29 < ZielRPM:
1224                                                 AktVLT = (AktVLT+5 if ZielRPM-AktRPM > 100 else AktVLT+1)
1225                                                 setVoltage(id,AktVLT)
1226                                         elif AktRPM-19 > ZielRPM:
1227                                                 AktVLT = (AktVLT-5 if AktRPM-ZielRPM > 100 else AktVLT-1)
1228                                                 setVoltage(id,AktVLT)
1229
1230                 except Exception:
1231                         from traceback import format_exc
1232                         FClog("Control Error:\n" + format_exc() )
1233                 FClogE("Runtime: %.3f" % (time.time() - tt) )
1234
1235 def autostart(reason, **kwargs):
1236         global session
1237         if reason == 0 and kwargs.has_key("session"):
1238                 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"):
1239                         from Plugins.Extensions.WebInterface.WebChilds.Toplevel import addExternalChild
1240                         from FC2webSite import FC2web, FC2webLog, FC2webChart
1241                         from twisted.web import static
1242                         root = static.File("/usr/lib/enigma2/python/Plugins/Extensions/FanControl2/data")
1243 #                       root = FC2web()
1244                         root.putChild("", FC2web())
1245                         root.putChild("log", FC2webLog())
1246                         root.putChild("chart", FC2webChart())
1247                         if os.path.exists("/usr/lib/enigma2/python/Plugins/Extensions/WebInterface/web/external.xml"):
1248                                 try:
1249                                         addExternalChild( ("fancontrol", root, "Fan Control 2", Version, True) )
1250                                         FClog("use new WebIF")
1251                                 except:
1252                                         addExternalChild( ("fancontrol", root) )
1253                                         FClog("use old WebIF")
1254                         if os.path.exists("/usr/lib/enigma2/python/Plugins/Extensions/OpenWebif/pluginshook.src"):
1255                                 try:
1256                                         addExternalChild( ("fancontrol", root, "Fan Control 2", Version) )
1257                                         FClog("use new OpenWebIF")
1258                                 except:
1259                                         pass
1260                 if not os.path.exists("/proc/stb/fp/fan_vlt"):
1261                         Notifications.AddNotification(MessageBox, _("Box has no fancontrol hardware -> FC2 deactivated"), type=MessageBox.TYPE_INFO, timeout=10)
1262                         FClog("not supported, exit")
1263                         return
1264                 session = kwargs["session"]
1265                 session.open(FanControl2)
1266           
1267 def Plugins(**kwargs):
1268         list = [
1269         PluginDescriptor(name="Fan Control", 
1270         description="Fan Control 2", 
1271         where = [PluginDescriptor.WHERE_SESSIONSTART, 
1272         PluginDescriptor.WHERE_AUTOSTART], 
1273         fnc = autostart)]
1274         if os.path.exists("/proc/stb/fp/fan_vlt"):
1275                 list.append(PluginDescriptor(name="Fan Control 2", 
1276                 description="Fan Control", 
1277                 where = PluginDescriptor.WHERE_PLUGINMENU,
1278                 icon = "plugin.png",
1279                 fnc = main))
1280                 if config.plugins.FanControl.FanControlInExtension.value:
1281                         list.append(PluginDescriptor(name="Fan Control 2", 
1282                         description="Fan Control", 
1283                         where = PluginDescriptor.WHERE_EXTENSIONSMENU,
1284                         icon = "plugin.png",
1285                         fnc = main))
1286                 if config.plugins.FanControl.MonitorInExtension.value:
1287                         list.append(PluginDescriptor(
1288                         name="Fan Control 2 - Monitor", 
1289                         description="Fan Control", 
1290                         where = PluginDescriptor.WHERE_EXTENSIONSMENU,
1291                         icon = "plugin.png",
1292                         fnc = mainMonitor))
1293         return list