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.addResult(self.currentlyTestedIndex, "failed", self.failedTune, self.successfullyTune)
408 self.changeProgressListStatus(self.currentlyTestedIndex, "successful")
409 self["succeeded_counter"].setText(str(int(self["succeeded_counter"].getText()) + len(self.successfullyTune)))
410 self.addResult(self.currentlyTestedIndex, "successful", self.failedTune, self.successfullyTune)
413 #self["failed_counter"].setText(str(int(self["failed_counter"].getText()) + len(self.failedTune)))
414 #self["succeeded_counter"].setText(str(int(self["succeeded_counter"].getText()) + len(self.successfullyTune)))
415 #if len(self.failedTune) == 0 and len(self.successfullyTune) == 0:
416 #self["untestable_counter"].setText(str(int(self["untestable_counter"].getText()) + 1))
418 self.currentlyTestedIndex = self.getNextIndex()
419 self.addProgressListItem(self.currentlyTestedIndex)
421 if self.fillTransponderList():
422 self.run(checkPIDs = True)
425 self["progress_list"].setIndex(0)
426 print "results:", self.results
427 print "resultsstatus:", self.resultsstatus
429 file = open("/media/hdd/diseqctester.log", "w")
430 self.setResultType(ResultParser.TYPE_ALL)
431 file.write(self.getTextualResult())
433 self.session.open(MessageBox, text=_("The results have been written to %s.") % "/media/hdd/diseqctester.log", type = MessageBox.TYPE_INFO)
437 self["failed_counter"].setText("0")
438 self["succeeded_counter"].setText("0")
439 self["untestable_counter"].setText("0")
440 self.currentlyTestedIndex = self.getFirstIndex()
442 self.clearProgressList()
443 self.addProgressListItem(self.currentlyTestedIndex)
445 if self.fillTransponderList():
452 print "selectedIndex:", self["progress_list"].getCurrent()[0]
454 index = self["progress_list"].getCurrent()[0]
455 #self.setResultType(ResultParser.TYPE_BYORBPOS)
456 #self.setResultParameter(index[2])
457 self.setResultType(ResultParser.TYPE_BYINDEX)
458 self.setResultParameter(index)
459 #self.setResultType(ResultParser.TYPE_ALL)
460 self.session.open(TextBox, self.getTextualResult())
462 def selectionChanged(self):
463 print "selection changed"
464 if len(self.list) > 0 and not self.running:
465 self["CmdText"].setText(_("Press OK to get further details for %s") % str(self["progress_list"].getCurrent()[1]))
467 class DiseqcTesterTestTypeSelection(Screen, ConfigListScreen):
468 skin = """<screen position="80,95" size="560,412" title="DiSEqC Tester Test Settings">
469 <widget name="config" position="10,10" size="540,402" scrollbarMode="showOnDemand" />
472 def __init__(self, session, feid):
473 Screen.__init__(self, session)
477 ConfigListScreen.__init__(self, self.list)
479 self["actions"] = ActionMap(["SetupActions"],
481 "cancel": self.keyCancel
486 def createSetup(self):
487 self.testtype = ConfigSelection(choices={"quick": _("Quick"), "random": _("Random")}, default = "quick")
488 self.testtypeEntry = getConfigListEntry(_("Test Type"), self.testtype)
489 self.list.append(self.testtypeEntry)
491 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")
492 self.loopsfailedEntry = getConfigListEntry(_("Stop testing plane after # failed transponders"), self.loopsfailed)
493 self.list.append(self.loopsfailedEntry)
495 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")
496 self.loopssuccessfulEntry = getConfigListEntry(_("Stop testing plane after # successful transponders"), self.loopssuccessful)
497 self.list.append(self.loopssuccessfulEntry)
499 self.log = ConfigYesNo(False)
500 if harddiskmanager.HDDCount() > 0:
501 self.logEntry = getConfigListEntry(_("Log results to harddisk"), self.log)
502 self.list.append(self.logEntry)
504 self["config"].list = self.list
505 self["config"].l.setList(self.list)
508 print self.testtype.getValue()
509 testtype = DiseqcTester.TEST_TYPE_QUICK
510 if self.testtype.getValue() == "quick":
511 testtype = DiseqcTester.TEST_TYPE_QUICK
512 elif self.testtype.getValue() == "random":
513 testtype = DiseqcTester.TEST_TYPE_RANDOM
514 elif self.testtype.getValue() == "complete":
515 testtype = DiseqcTester.TEST_TYPE_COMPLETE
516 self.session.open(DiseqcTester, feid = self.feid, test_type = testtype, loopsfailed = int(self.loopsfailed.value), loopssuccessful = int(self.loopssuccessful.value), log = self.log.value)
521 class DiseqcTesterNimSelection(NimSelection):
523 <screen position="160,123" size="400,330" title="Choose Tuner">
524 <widget source="nimlist" render="Listbox" position="0,0" size="380,300" scrollbarMode="showOnDemand">
525 <convert type="TemplatedMultiContent">
527 MultiContentEntryText(pos = (10, 5), size = (360, 30), flags = RT_HALIGN_LEFT, text = 1), # index 1 is the nim name,
528 MultiContentEntryText(pos = (50, 30), size = (320, 30), font = 1, flags = RT_HALIGN_LEFT, text = 2), # index 2 is a description of the nim settings,
530 "fonts": [gFont("Regular", 20), gFont("Regular", 15)],
537 def __init__(self, session, args = None):
538 NimSelection.__init__(self, session)
540 def setResultClass(self):
541 #self.resultclass = DiseqcTester
542 self.resultclass = DiseqcTesterTestTypeSelection
544 def showNim(self, nim):
545 nimConfig = nimmanager.getNimConfig(nim.slot)
546 if nim.isCompatible("DVB-S"):
547 if nimConfig.configMode.value in ["loopthrough", "equal", "satposdepends", "nothing"]:
549 if nimConfig.configMode.value == "simple":
550 if nimConfig.diseqcMode.value == "positioner":
555 def DiseqcTesterMain(session, **kwargs):
556 session.open(DiseqcTesterNimSelection)
558 def autostart(reason, **kwargs):
559 resourcemanager.addResource("DiseqcTester", DiseqcTesterMain)
561 def Plugins(**kwargs):
562 return [ PluginDescriptor(name="DiSEqC Tester", description=_("Test DiSEqC settings"), where = PluginDescriptor.WHERE_PLUGINMENU, fnc=DiseqcTesterMain),
563 PluginDescriptor(where = PluginDescriptor.WHERE_AUTOSTART, fnc = autostart)]