1 from Screens.Satconfig import NimSelection
2 from Screens.Screen import Screen
3 from Screens.TextBox import TextBox
4 from Screens.MessageBox import MessageBox
6 from Plugins.Plugin import PluginDescriptor
8 from Components.ActionMap import ActionMap, NumberActionMap
9 from Components.NimManager import nimmanager
10 from Components.ResourceManager import resourcemanager
11 from Components.Sources.FrontendStatus import FrontendStatus
12 from Components.TuneTest import TuneTest
13 from Components.Sources.List import List
14 from Components.Sources.Progress import Progress
15 from Components.Sources.StaticText import StaticText
16 from Components.ConfigList import ConfigListScreen
17 from Components.config import getConfigListEntry, ConfigSelection, ConfigYesNo
18 from Components.Harddisk import harddiskmanager
24 # setResultParameter(parameter)
33 def setResultType(self, type):
36 def setResultParameter(self, parameter):
37 if self.type == self.TYPE_BYORBPOS:
38 self.orbpos = parameter
39 elif self.type == self.TYPE_BYINDEX:
40 self.index = parameter
42 def getTextualResultForIndex(self, index, logfulltransponders = False):
44 text += "%s:\n" % self.getTextualIndexRepresentation(index)
46 failed, successful = self.results[index]["failed"], self.results[index]["successful"]
47 countfailed = len(failed)
48 countsuccessful = len(successful)
49 countall = countfailed + countsuccessful
50 percentfailed = round(countfailed / float(countall + 0.0001) * 100)
51 percentsuccessful = round(countsuccessful / float(countall + 0.0001) * 100)
52 text += "Tested %d transponders\n%d (%d %%) transponders succeeded\n%d (%d %%) transponders failed\n" % (countall, countsuccessful, percentsuccessful, countfailed, percentfailed)
55 for transponder in failed:
56 reasons[transponder[2]] = reasons.get(transponder[2], [])
57 reasons[transponder[2]].append(transponder)
58 if transponder[2] == "pids_failed":
59 print transponder[2], "-", transponder[3]
61 text += "The %d unsuccessful tuning attempts failed for the following reasons:\n" % countfailed
63 for reason in reasons.keys():
64 text += "%s: %d transponders failed\n" % (reason, len(reasons[reason]))
66 for reason in reasons.keys():
68 text += "%s previous planes:\n" % reason
69 for transponder in reasons[reason]:
70 if transponder[1] is not None:
71 text += self.getTextualIndexRepresentation(self.getIndexForTransponder(transponder[1]))
73 text += "No transponder tuned"
74 text += " ==> " + self.getTextualIndexRepresentation(self.getIndexForTransponder(transponder[0]))
76 if logfulltransponders:
77 text += str(transponder[1])
79 text += str(transponder[0])
81 if countsuccessful > 0:
83 text += "Successfully tuned transponders' previous planes:\n"
84 for transponder in successful:
85 if transponder[1] is not None:
86 text += self.getTextualIndexRepresentation(self.getIndexForTransponder(transponder[1]))
88 text += "No transponder tuned"
89 text += " ==> " + self.getTextualIndexRepresentation(self.getIndexForTransponder(transponder[0]))
93 def getTextualResult(self):
95 if self.type == self.TYPE_BYINDEX:
96 text += self.getTextualResultForIndex(self.index)
97 elif self.type == self.TYPE_BYORBPOS:
98 for index in self.results.keys():
99 if index[2] == self.orbpos:
100 text += self.getTextualResultForIndex(index)
101 text += "\n-----------------------------------------------------\n"
102 elif self.type == self.TYPE_ALL:
104 for index in self.results.keys():
106 orderedResults[orbpos] = orderedResults.get(orbpos, [])
107 orderedResults[orbpos].append(index)
108 ordered_orbpos = orderedResults.keys()
109 ordered_orbpos.sort()
110 for orbpos in ordered_orbpos:
111 text += "\n*****************************************\n"
112 text += "Orbital position %s:" % str(orbpos)
113 text += "\n*****************************************\n"
114 for index in orderedResults[orbpos]:
115 text += self.getTextualResultForIndex(index, logfulltransponders = True)
116 text += "\n-----------------------------------------------------\n"
121 class DiseqcTester(Screen, TuneTest, ResultParser):
123 <screen position="90,100" size="520,400" title="DiSEqC Tester" >
124 <!--ePixmap pixmap="skin_default/icons/dish_scan.png" position="5,25" zPosition="0" size="119,110" transparent="1" alphatest="on" />
125 <widget source="Frontend" render="Label" position="190,10" zPosition="2" size="260,20" font="Regular;19" halign="center" valign="center" transparent="1">
126 <convert type="FrontendInfo">SNRdB</convert>
128 <eLabel name="snr" text="SNR:" position="120,35" size="60,22" font="Regular;21" halign="right" transparent="1" />
129 <widget source="Frontend" render="Progress" position="190,35" size="260,20" pixmap="skin_default/bar_snr.png" borderWidth="2" borderColor="#cccccc">
130 <convert type="FrontendInfo">SNR</convert>
132 <widget source="Frontend" render="Label" position="460,35" size="60,22" font="Regular;21">
133 <convert type="FrontendInfo">SNR</convert>
135 <eLabel name="agc" text="AGC:" position="120,60" size="60,22" font="Regular;21" halign="right" transparent="1" />
136 <widget source="Frontend" render="Progress" position="190,60" size="260,20" pixmap="skin_default/bar_snr.png" borderWidth="2" borderColor="#cccccc">
137 <convert type="FrontendInfo">AGC</convert>
139 <widget source="Frontend" render="Label" position="460,60" size="60,22" font="Regular;21">
140 <convert type="FrontendInfo">AGC</convert>
142 <eLabel name="ber" text="BER:" position="120,85" size="60,22" font="Regular;21" halign="right" transparent="1" />
143 <widget source="Frontend" render="Progress" position="190,85" size="260,20" pixmap="skin_default/bar_ber.png" borderWidth="2" borderColor="#cccccc">
144 <convert type="FrontendInfo">BER</convert>
146 <widget source="Frontend" render="Label" position="460,85" size="60,22" font="Regular;21">
147 <convert type="FrontendInfo">BER</convert>
149 <eLabel name="lock" text="Lock:" position="120,115" size="60,22" font="Regular;21" halign="right" />
150 <widget source="Frontend" render="Pixmap" pixmap="skin_default/icons/lock_on.png" position="190,110" zPosition="1" size="38,31" alphatest="on">
151 <convert type="FrontendInfo">LOCK</convert>
152 <convert type="ConditionalShowHide" />
154 <widget source="Frontend" render="Pixmap" pixmap="skin_default/icons/lock_off.png" position="190,110" zPosition="1" size="38,31" alphatest="on">
155 <convert type="FrontendInfo">LOCK</convert>
156 <convert type="ConditionalShowHide">Invert</convert>
158 <widget source="progress_list" render="Listbox" position="0,0" size="510,150" scrollbarMode="showOnDemand">
159 <convert type="TemplatedMultiContent">
161 MultiContentEntryText(pos = (10, 0), size = (330, 25), flags = RT_HALIGN_LEFT, text = 1), # index 1 is the index name,
162 MultiContentEntryText(pos = (330, 0), size = (150, 25), flags = RT_HALIGN_RIGHT, text = 2) # index 2 is the status,
164 "fonts": [gFont("Regular", 20)],
169 <eLabel name="overall_progress" text="Overall progress:" position="20,162" size="480,22" font="Regular;21" halign="center" transparent="1" />
170 <widget source="overall_progress" render="Progress" position="20,192" size="480,20" borderWidth="2" backgroundColor="#254f7497" />
171 <eLabel name="overall_progress" text="Progress:" position="20,222" size="480,22" font="Regular;21" halign="center" transparent="1" />
172 <widget source="sub_progress" render="Progress" position="20,252" size="480,20" borderWidth="2" backgroundColor="#254f7497" />
174 <eLabel name="" text="Failed:" position="20,282" size="140,22" font="Regular;21" halign="left" transparent="1" />
175 <widget source="failed_counter" render="Label" position="160,282" size="100,20" font="Regular;21" />
177 <eLabel name="" text="Succeeded:" position="20,312" size="140,22" font="Regular;21" halign="left" transparent="1" />
178 <widget source="succeeded_counter" render="Label" position="160,312" size="100,20" font="Regular;21" />
180 <eLabel name="" text="With errors:" position="20,342" size="140,22" font="Regular;21" halign="left" transparent="1" />
181 <widget source="witherrors_counter" render="Label" position="160,342" size="100,20" font="Regular;21" />
183 <eLabel name="" text="Not tested:" position="20,372" size="140,22" font="Regular;21" halign="left" transparent="1" />
184 <widget source="untestable_counter" render="Label" position="160,372" size="100,20" font="Regular;21" />
186 <widget source="CmdText" render="Label" position="300,282" size="180,200" font="Regular;21" />
191 TEST_TYPE_COMPLETE = 2
192 def __init__(self, session, feid, test_type = TEST_TYPE_QUICK, loopsfailed = 3, loopssuccessful = 1, log = False):
193 Screen.__init__(self, session)
195 self.test_type = test_type
196 self.loopsfailed = loopsfailed
197 self.loopssuccessful = loopssuccessful
200 self["actions"] = NumberActionMap(["SetupActions"],
203 "cancel": self.keyCancel,
206 TuneTest.__init__(self, feid, stopOnSuccess = self.loopssuccessful, stopOnError = self.loopsfailed)
207 #self["Frontend"] = FrontendStatus(frontend_source = lambda : self.frontend, update_interval = 100)
208 self["overall_progress"] = Progress()
209 self["sub_progress"] = Progress()
211 self["failed_counter"] = StaticText("0")
212 self["succeeded_counter"] = StaticText("0")
213 self["witherrors_counter"] = StaticText("0")
214 self["untestable_counter"] = StaticText("0")
217 self["progress_list"] = List(self.list)
218 self["progress_list"].onSelectionChanged.append(self.selectionChanged)
220 self["CmdText"] = StaticText(_("Please wait while scanning is in progress..."))
223 self.readTransponderList()
228 self.resultsstatus = {}
230 self.onLayoutFinish.append(self.go)
232 def getProgressListComponent(self, index, status):
233 return (index, self.getTextualIndexRepresentation(index), status)
235 def clearProgressList(self):
237 self["progress_list"].list = self.list
239 def addProgressListItem(self, index):
240 if index in self.indexlist:
241 for entry in self.list:
242 if entry[0] == index:
243 self.changeProgressListStatus(index, "working")
245 self.list.append(self.getProgressListComponent(index, _("working")))
246 self["progress_list"].list = self.list
247 self["progress_list"].setIndex(len(self.list) - 1)
249 def changeProgressListStatus(self, index, status):
253 for entry in self.list:
254 if entry[0] == index:
255 self.newlist.append(self.getProgressListComponent(index, status))
258 self.newlist.append(entry)
260 self.list = self.newlist
261 self["progress_list"].list = self.list
262 self["progress_list"].setIndex(indexpos)
264 def readTransponderList(self):
265 for sat in nimmanager.getSatListForNim(self.feid):
266 for transponder in nimmanager.getTransponders(sat[0]):
268 mytransponder = (transponder[1] / 1000, transponder[2] / 1000, transponder[3], transponder[4], transponder[5], sat[0], None, None, transponder[10], transponder[11])
269 self.analyseTransponder(mytransponder)
271 def getIndexForTransponder(self, transponder):
273 if transponder[0] < 11700:
278 polarisation = transponder[2]
282 index = (band, polarisation, sat)
285 # sort the transponder into self.transponderlist
286 def analyseTransponder(self, transponder):
287 index = self.getIndexForTransponder(transponder)
288 if index not in self.indexlist:
289 self.indexlist[index] = []
290 self.indexlist[index].append(transponder)
291 #print "self.indexlist:", self.indexlist
293 # returns a string for the user representing a human readable output for index
294 def getTextualIndexRepresentation(self, index):
295 print "getTextualIndexRepresentation:", index
298 text += nimmanager.getSatDescription(index[2]) + ", "
303 text += "High Band, "
311 def fillTransponderList(self):
312 self.clearTransponder()
313 print "----------- fillTransponderList"
314 print "index:", self.currentlyTestedIndex
315 keys = self.indexlist.keys()
316 if self.getContinueScanning():
317 print "index:", self.getTextualIndexRepresentation(self.currentlyTestedIndex)
318 for transponder in self.indexlist[self.currentlyTestedIndex]:
319 self.addTransponder(transponder)
320 print "transponderList:", self.transponderlist
325 def progressCallback(self, progress):
326 if progress[0] != self["sub_progress"].getRange():
327 self["sub_progress"].setRange(progress[0])
328 self["sub_progress"].setValue(progress[1])
330 # logic for scanning order of transponders
331 # on go getFirstIndex is called
332 def getFirstIndex(self):
333 # TODO use other function to scan more randomly
334 if self.test_type == self.TEST_TYPE_QUICK:
336 keys = self.indexlist.keys()
337 keys.sort(key = lambda a: a[2]) # sort by orbpos
338 self["overall_progress"].setRange(len(keys))
339 self["overall_progress"].setValue(self.myindex)
341 elif self.test_type == self.TEST_TYPE_RANDOM:
342 self.randomkeys = self.indexlist.keys()
343 random.shuffle(self.randomkeys)
345 self["overall_progress"].setRange(len(self.randomkeys))
346 self["overall_progress"].setValue(self.myindex)
347 return self.randomkeys[0]
349 # after each index is finished, getNextIndex is called to get the next index to scan
350 def getNextIndex(self):
351 # TODO use other function to scan more randomly
352 if self.test_type == self.TEST_TYPE_QUICK:
354 keys = self.indexlist.keys()
355 keys.sort(key = lambda a: a[2]) # sort by orbpos
357 self["overall_progress"].setValue(self.myindex)
358 if self.myindex < len(keys):
359 return keys[self.myindex]
362 elif self.test_type == self.TEST_TYPE_RANDOM:
364 keys = self.randomkeys
366 self["overall_progress"].setValue(self.myindex)
367 if self.myindex < len(keys):
368 return keys[self.myindex]
372 # after each index is finished and the next index is returned by getNextIndex
373 # the algorithm checks, if we should continue scanning
374 def getContinueScanning(self):
375 if self.test_type == self.TEST_TYPE_QUICK or self.test_type == self.TEST_TYPE_RANDOM:
376 return (self.myindex < len(self.indexlist.keys()))
378 def addResult(self, index, status, failedTune, successfullyTune):
379 self.results[index] = self.results.get(index, {"failed": [], "successful": [], "status": None})
380 self.resultsstatus[status] = self.resultsstatus.get(status, [])
382 self.results[index]["status"] = status
383 self.results[index]["failed"] = failedTune
384 self.results[index]["successful"] = successfullyTune
386 self.resultsstatus[status].append(index)
388 def finishedChecking(self):
389 print "finishedChecking"
390 TuneTest.finishedChecking(self)
392 if not self.results.has_key(self.currentlyTestedIndex):
393 self.results[self.currentlyTestedIndex] = {"failed": [], "successful": [], "status": None}
395 if len(self.failedTune) > 0 and len(self.successfullyTune) > 0:
396 self.changeProgressListStatus(self.currentlyTestedIndex, "with errors")
397 self["witherrors_counter"].setText(str(int(self["witherrors_counter"].getText()) + 1))
398 self.addResult(self.currentlyTestedIndex, "with_errors", self.failedTune, self.successfullyTune)
399 elif len(self.failedTune) == 0 and len(self.successfullyTune) == 0:
400 self.changeProgressListStatus(self.currentlyTestedIndex, "not tested")
401 self["untestable_counter"].setText(str(int(self["untestable_counter"].getText()) + 1))
402 self.addResult(self.currentlyTestedIndex, "untestable", self.failedTune, self.successfullyTune)
403 elif len(self.failedTune) > 0:
404 self.changeProgressListStatus(self.currentlyTestedIndex, "failed")
405 #self["failed_counter"].setText(str(int(self["failed_counter"].getText()) + len(self.failedTune)))
406 self["failed_counter"].setText(str(int(self["failed_counter"].getText()) + 1))
407 self.addResult(self.currentlyTestedIndex, "failed", self.failedTune, self.successfullyTune)
409 self.changeProgressListStatus(self.currentlyTestedIndex, "successful")
410 #self["succeeded_counter"].setText(str(int(self["succeeded_counter"].getText()) + len(self.successfullyTune)))
411 self["succeeded_counter"].setText(str(int(self["succeeded_counter"].getText()) + 1))
412 self.addResult(self.currentlyTestedIndex, "successful", self.failedTune, self.successfullyTune)
415 #self["failed_counter"].setText(str(int(self["failed_counter"].getText()) + len(self.failedTune)))
416 #self["succeeded_counter"].setText(str(int(self["succeeded_counter"].getText()) + len(self.successfullyTune)))
417 #if len(self.failedTune) == 0 and len(self.successfullyTune) == 0:
418 #self["untestable_counter"].setText(str(int(self["untestable_counter"].getText()) + 1))
420 self.currentlyTestedIndex = self.getNextIndex()
421 self.addProgressListItem(self.currentlyTestedIndex)
423 if self.fillTransponderList():
424 self.run(checkPIDs = True)
427 self["progress_list"].setIndex(0)
428 print "results:", self.results
429 print "resultsstatus:", self.resultsstatus
431 file = open("/media/hdd/diseqctester.log", "w")
432 self.setResultType(ResultParser.TYPE_ALL)
433 file.write(self.getTextualResult())
435 self.session.open(MessageBox, text=_("The results have been written to %s.") % "/media/hdd/diseqctester.log", type = MessageBox.TYPE_INFO)
439 self["failed_counter"].setText("0")
440 self["succeeded_counter"].setText("0")
441 self["untestable_counter"].setText("0")
442 self.currentlyTestedIndex = self.getFirstIndex()
444 self.clearProgressList()
445 self.addProgressListItem(self.currentlyTestedIndex)
447 if self.fillTransponderList():
454 print "selectedIndex:", self["progress_list"].getCurrent()[0]
456 index = self["progress_list"].getCurrent()[0]
457 #self.setResultType(ResultParser.TYPE_BYORBPOS)
458 #self.setResultParameter(index[2])
459 self.setResultType(ResultParser.TYPE_BYINDEX)
460 self.setResultParameter(index)
461 #self.setResultType(ResultParser.TYPE_ALL)
462 self.session.open(TextBox, self.getTextualResult())
464 def selectionChanged(self):
465 print "selection changed"
466 if len(self.list) > 0 and not self.running:
467 self["CmdText"].setText(_("Press OK to get further details for %s") % str(self["progress_list"].getCurrent()[1]))
469 class DiseqcTesterTestTypeSelection(Screen, ConfigListScreen):
470 skin = """<screen position="80,95" size="560,412" title="DiSEqC Tester Test Settings">
471 <widget name="config" position="10,10" size="540,402" scrollbarMode="showOnDemand" />
474 def __init__(self, session, feid):
475 Screen.__init__(self, session)
479 ConfigListScreen.__init__(self, self.list)
481 self["actions"] = ActionMap(["SetupActions"],
483 "cancel": self.keyCancel
488 def createSetup(self):
489 self.testtype = ConfigSelection(choices={"quick": _("Quick"), "random": _("Random")}, default = "quick")
490 self.testtypeEntry = getConfigListEntry(_("Test Type"), self.testtype)
491 self.list.append(self.testtypeEntry)
493 self.loopsfailed = ConfigSelection(choices={"-1": "Every known", "1": "1", "2": "2", "3": "3", "4": "4", "5": "5", "6": "6", "7": "7", "8": "8"}, default = "3")
494 self.loopsfailedEntry = getConfigListEntry(_("Stop testing plane after # failed transponders"), self.loopsfailed)
495 self.list.append(self.loopsfailedEntry)
497 self.loopssuccessful = ConfigSelection(choices={"-1": "Every known", "1": "1", "2": "2", "3": "3", "4": "4", "5": "5", "6": "6", "7": "7", "8": "8"}, default = "1")
498 self.loopssuccessfulEntry = getConfigListEntry(_("Stop testing plane after # successful transponders"), self.loopssuccessful)
499 self.list.append(self.loopssuccessfulEntry)
501 self.log = ConfigYesNo(False)
502 if harddiskmanager.HDDCount() > 0:
503 self.logEntry = getConfigListEntry(_("Log results to harddisk"), self.log)
504 self.list.append(self.logEntry)
506 self["config"].list = self.list
507 self["config"].l.setList(self.list)
510 print self.testtype.getValue()
511 testtype = DiseqcTester.TEST_TYPE_QUICK
512 if self.testtype.getValue() == "quick":
513 testtype = DiseqcTester.TEST_TYPE_QUICK
514 elif self.testtype.getValue() == "random":
515 testtype = DiseqcTester.TEST_TYPE_RANDOM
516 elif self.testtype.getValue() == "complete":
517 testtype = DiseqcTester.TEST_TYPE_COMPLETE
518 self.session.open(DiseqcTester, feid = self.feid, test_type = testtype, loopsfailed = int(self.loopsfailed.value), loopssuccessful = int(self.loopssuccessful.value), log = self.log.value)
523 class DiseqcTesterNimSelection(NimSelection):
525 <screen position="160,123" size="400,330" title="Choose Tuner">
526 <widget source="nimlist" render="Listbox" position="0,0" size="380,300" scrollbarMode="showOnDemand">
527 <convert type="TemplatedMultiContent">
529 MultiContentEntryText(pos = (10, 5), size = (360, 30), flags = RT_HALIGN_LEFT, text = 1), # index 1 is the nim name,
530 MultiContentEntryText(pos = (50, 30), size = (320, 30), font = 1, flags = RT_HALIGN_LEFT, text = 2), # index 2 is a description of the nim settings,
532 "fonts": [gFont("Regular", 20), gFont("Regular", 15)],
539 def __init__(self, session, args = None):
540 NimSelection.__init__(self, session)
542 def setResultClass(self):
543 #self.resultclass = DiseqcTester
544 self.resultclass = DiseqcTesterTestTypeSelection
546 def showNim(self, nim):
547 nimConfig = nimmanager.getNimConfig(nim.slot)
548 if nim.isCompatible("DVB-S"):
549 if nimConfig.configMode.value in ["loopthrough", "equal", "satposdepends", "nothing"]:
551 if nimConfig.configMode.value == "simple":
552 if nimConfig.diseqcMode.value == "positioner":
557 def DiseqcTesterMain(session, **kwargs):
558 session.open(DiseqcTesterNimSelection)
560 def autostart(reason, **kwargs):
561 resourcemanager.addResource("DiseqcTester", DiseqcTesterMain)
563 def Plugins(**kwargs):
564 return [ PluginDescriptor(name="DiSEqC Tester", description=_("Test DiSEqC settings"), where = PluginDescriptor.WHERE_PLUGINMENU, fnc=DiseqcTesterMain),
565 PluginDescriptor(where = PluginDescriptor.WHERE_AUTOSTART, fnc = autostart)]