1 from Screens.Satconfig import NimSelection
2 from Screens.Screen import Screen
3 from Screens.TextBox import TextBox
5 from Plugins.Plugin import PluginDescriptor
7 from Components.ActionMap import ActionMap, NumberActionMap
8 from Components.NimManager import nimmanager
9 from Components.ResourceManager import resourcemanager
10 from Components.Sources.FrontendStatus import FrontendStatus
11 from Components.TuneTest import TuneTest
12 from Components.Sources.List import List
13 from Components.Sources.Progress import Progress
14 from Components.Sources.StaticText import StaticText
15 from Components.ConfigList import ConfigListScreen
16 from Components.config import getConfigListEntry, ConfigSelection
22 # setResultParameter(parameter)
31 def setResultType(self, type):
34 def setResultParameter(self, parameter):
35 if self.type == self.TYPE_BYORBPOS:
36 self.orbpos = parameter
37 elif self.type == self.TYPE_BYINDEX:
38 self.index = parameter
40 def getTextualResultForIndex(self, index):
42 text += "%s:\n" % self.getTextualIndexRepresentation(index)
44 failed, successful = self.results[index]["failed"], self.results[index]["successful"]
45 countfailed = len(failed)
46 countsuccessful = len(successful)
47 countall = countfailed + countsuccessful
48 percentfailed = round(countfailed / float(countall + 0.0001) * 100)
49 percentsuccessful = round(countsuccessful / float(countall + 0.0001) * 100)
50 text += "Tested %d transponders\n%d (%d %%) transponders succeeded\n%d (%d %%) transponders failed\n" % (countall, countsuccessful, percentsuccessful, countfailed, percentfailed)
53 for transponder in failed:
54 reasons[transponder[2]] = reasons.get(transponder[2], [])
55 reasons[transponder[2]].append(transponder)
56 if transponder[2] == "pids_failed":
57 print transponder[2], "-", transponder[3]
59 text += "The %d unsuccessful tuning attempts failed for the following reasons:\n" % countfailed
61 for reason in reasons.keys():
62 text += "%s: %d transponders failed\n" % (reason, len(reasons[reason]))
64 for reason in reasons.keys():
66 text += "%s previous planes:\n" % reason
67 for transponder in reasons[reason]:
68 if transponder[1] is not None:
69 text += self.getTextualIndexRepresentation(self.getIndexForTransponder(transponder[1]))
71 text += "No transponder tuned"
72 text += " ==> " + self.getTextualIndexRepresentation(self.getIndexForTransponder(transponder[0]))
74 if countsuccessful > 0:
76 text += "Successfully tuned transponders' previous planes:\n"
77 for transponder in successful:
78 if transponder[1] is not None:
79 text += self.getTextualIndexRepresentation(self.getIndexForTransponder(transponder[1]))
81 text += "No transponder tuned"
82 text += " ==> " + self.getTextualIndexRepresentation(self.getIndexForTransponder(transponder[0]))
86 def getTextualResult(self):
88 if self.type == self.TYPE_BYINDEX:
89 text += self.getTextualResultForIndex(self.index)
90 elif self.type == self.TYPE_BYORBPOS:
91 for index in self.results.keys():
92 if index[2] == self.orbpos:
93 text += self.getTextualResultForIndex(index)
94 text += "\n-----------------------------------------------------\n"
98 class DiseqcTester(Screen, TuneTest, ResultParser):
100 <screen position="90,100" size="520,400" title="DiSEqC Tester" >
101 <!--ePixmap pixmap="skin_default/icons/dish_scan.png" position="5,25" zPosition="0" size="119,110" transparent="1" alphatest="on" />
102 <widget source="Frontend" render="Label" position="190,10" zPosition="2" size="260,20" font="Regular;19" halign="center" valign="center" transparent="1">
103 <convert type="FrontendInfo">SNRdB</convert>
105 <eLabel name="snr" text="SNR:" position="120,35" size="60,22" font="Regular;21" halign="right" transparent="1" />
106 <widget source="Frontend" render="Progress" position="190,35" size="260,20" pixmap="skin_default/bar_snr.png" borderWidth="2" borderColor="#cccccc">
107 <convert type="FrontendInfo">SNR</convert>
109 <widget source="Frontend" render="Label" position="460,35" size="60,22" font="Regular;21">
110 <convert type="FrontendInfo">SNR</convert>
112 <eLabel name="agc" text="AGC:" position="120,60" size="60,22" font="Regular;21" halign="right" transparent="1" />
113 <widget source="Frontend" render="Progress" position="190,60" size="260,20" pixmap="skin_default/bar_snr.png" borderWidth="2" borderColor="#cccccc">
114 <convert type="FrontendInfo">AGC</convert>
116 <widget source="Frontend" render="Label" position="460,60" size="60,22" font="Regular;21">
117 <convert type="FrontendInfo">AGC</convert>
119 <eLabel name="ber" text="BER:" position="120,85" size="60,22" font="Regular;21" halign="right" transparent="1" />
120 <widget source="Frontend" render="Progress" position="190,85" size="260,20" pixmap="skin_default/bar_ber.png" borderWidth="2" borderColor="#cccccc">
121 <convert type="FrontendInfo">BER</convert>
123 <widget source="Frontend" render="Label" position="460,85" size="60,22" font="Regular;21">
124 <convert type="FrontendInfo">BER</convert>
126 <eLabel name="lock" text="Lock:" position="120,115" size="60,22" font="Regular;21" halign="right" />
127 <widget source="Frontend" render="Pixmap" pixmap="skin_default/icons/lock_on.png" position="190,110" zPosition="1" size="38,31" alphatest="on">
128 <convert type="FrontendInfo">LOCK</convert>
129 <convert type="ConditionalShowHide" />
131 <widget source="Frontend" render="Pixmap" pixmap="skin_default/icons/lock_off.png" position="190,110" zPosition="1" size="38,31" alphatest="on">
132 <convert type="FrontendInfo">LOCK</convert>
133 <convert type="ConditionalShowHide">Invert</convert>
135 <widget source="progress_list" render="Listbox" position="0,0" size="510,150" scrollbarMode="showOnDemand">
136 <convert type="TemplatedMultiContent">
138 MultiContentEntryText(pos = (10, 0), size = (330, 25), flags = RT_HALIGN_LEFT, text = 1), # index 1 is the index name,
139 MultiContentEntryText(pos = (330, 0), size = (150, 25), flags = RT_HALIGN_RIGHT, text = 2) # index 2 is the status,
141 "fonts": [gFont("Regular", 20)],
146 <eLabel name="overall_progress" text="Overall progress:" position="20,162" size="480,22" font="Regular;21" halign="center" transparent="1" />
147 <widget source="overall_progress" render="Progress" position="20,192" size="480,20" borderWidth="2" backgroundColor="#254f7497" />
148 <eLabel name="overall_progress" text="Progress:" position="20,222" size="480,22" font="Regular;21" halign="center" transparent="1" />
149 <widget source="sub_progress" render="Progress" position="20,252" size="480,20" borderWidth="2" backgroundColor="#254f7497" />
151 <eLabel name="" text="Failed:" position="20,282" size="140,22" font="Regular;21" halign="left" transparent="1" />
152 <widget source="failed_counter" render="Label" position="160,282" size="100,20" font="Regular;21" />
154 <eLabel name="" text="Succeeded:" position="20,312" size="140,22" font="Regular;21" halign="left" transparent="1" />
155 <widget source="succeeded_counter" render="Label" position="160,312" size="100,20" font="Regular;21" />
157 <eLabel name="" text="With errors:" position="20,342" size="140,22" font="Regular;21" halign="left" transparent="1" />
158 <widget source="witherrors_counter" render="Label" position="160,342" size="100,20" font="Regular;21" />
160 <eLabel name="" text="Not tested:" position="20,372" size="140,22" font="Regular;21" halign="left" transparent="1" />
161 <widget source="untestable_counter" render="Label" position="160,372" size="100,20" font="Regular;21" />
163 <widget source="CmdText" render="Label" position="300,282" size="180,200" font="Regular;21" />
168 TEST_TYPE_COMPLETE = 2
169 def __init__(self, session, feid, test_type = TEST_TYPE_QUICK, loopsfailed = 3, loopssuccessful = 1):
170 Screen.__init__(self, session)
172 self.test_type = test_type
173 self.loopsfailed = loopsfailed
174 self.loopssuccessful = loopssuccessful
176 self["actions"] = NumberActionMap(["SetupActions"],
179 "cancel": self.keyCancel,
182 TuneTest.__init__(self, feid, stopOnSuccess = self.loopssuccessful, stopOnError = self.loopsfailed)
183 #self["Frontend"] = FrontendStatus(frontend_source = lambda : self.frontend, update_interval = 100)
184 self["overall_progress"] = Progress()
185 self["sub_progress"] = Progress()
187 self["failed_counter"] = StaticText("0")
188 self["succeeded_counter"] = StaticText("0")
189 self["witherrors_counter"] = StaticText("0")
190 self["untestable_counter"] = StaticText("0")
193 self["progress_list"] = List(self.list)
194 self["progress_list"].onSelectionChanged.append(self.selectionChanged)
196 self["CmdText"] = StaticText(_("Please wait while scanning is in progress..."))
199 self.readTransponderList()
204 self.resultsstatus = {}
206 self.onLayoutFinish.append(self.go)
208 def getProgressListComponent(self, index, status):
209 return (index, self.getTextualIndexRepresentation(index), status)
211 def clearProgressList(self):
213 self["progress_list"].list = self.list
215 def addProgressListItem(self, index):
216 if index in self.indexlist:
217 for entry in self.list:
218 if entry[0] == index:
219 self.changeProgressListStatus(index, "working")
221 self.list.append(self.getProgressListComponent(index, _("working")))
222 self["progress_list"].list = self.list
223 self["progress_list"].setIndex(len(self.list) - 1)
225 def changeProgressListStatus(self, index, status):
229 for entry in self.list:
230 if entry[0] == index:
231 self.newlist.append(self.getProgressListComponent(index, status))
234 self.newlist.append(entry)
236 self.list = self.newlist
237 self["progress_list"].list = self.list
238 self["progress_list"].setIndex(indexpos)
240 def readTransponderList(self):
241 for sat in nimmanager.getSatListForNim(self.feid):
242 for transponder in nimmanager.getTransponders(sat[0]):
244 mytransponder = (transponder[1] / 1000, transponder[2] / 1000, transponder[3], transponder[4], transponder[5], sat[0], None, None, transponder[10], transponder[11])
245 self.analyseTransponder(mytransponder)
247 def getIndexForTransponder(self, transponder):
249 if transponder[0] < 11700:
254 polarisation = transponder[2]
258 index = (band, polarisation, sat)
261 # sort the transponder into self.transponderlist
262 def analyseTransponder(self, transponder):
263 index = self.getIndexForTransponder(transponder)
264 if index not in self.indexlist:
265 self.indexlist[index] = []
266 self.indexlist[index].append(transponder)
267 #print "self.indexlist:", self.indexlist
269 # returns a string for the user representing a human readable output for index
270 def getTextualIndexRepresentation(self, index):
271 print "getTextualIndexRepresentation:", index
274 text += nimmanager.getSatDescription(index[2]) + ", "
279 text += "High Band, "
287 def fillTransponderList(self):
288 self.clearTransponder()
289 print "----------- fillTransponderList"
290 print "index:", self.currentlyTestedIndex
291 keys = self.indexlist.keys()
292 if self.getContinueScanning():
293 print "index:", self.getTextualIndexRepresentation(self.currentlyTestedIndex)
294 for transponder in self.indexlist[self.currentlyTestedIndex]:
295 self.addTransponder(transponder)
296 print "transponderList:", self.transponderlist
301 def progressCallback(self, progress):
302 if progress[0] != self["sub_progress"].getRange():
303 self["sub_progress"].setRange(progress[0])
304 self["sub_progress"].setValue(progress[1])
306 # logic for scanning order of transponders
307 # on go getFirstIndex is called
308 def getFirstIndex(self):
309 # TODO use other function to scan more randomly
310 if self.test_type == self.TEST_TYPE_QUICK:
312 keys = self.indexlist.keys()
313 keys.sort(key = lambda a: a[2]) # sort by orbpos
314 self["overall_progress"].setRange(len(keys))
315 self["overall_progress"].setValue(self.myindex)
317 elif self.test_type == self.TEST_TYPE_RANDOM:
318 self.randomkeys = self.indexlist.keys()
319 random.shuffle(self.randomkeys)
321 self["overall_progress"].setRange(len(self.randomkeys))
322 self["overall_progress"].setValue(self.myindex)
323 return self.randomkeys[0]
325 # after each index is finished, getNextIndex is called to get the next index to scan
326 def getNextIndex(self):
327 # TODO use other function to scan more randomly
328 if self.test_type == self.TEST_TYPE_QUICK:
330 keys = self.indexlist.keys()
331 keys.sort(key = lambda a: a[2]) # sort by orbpos
333 self["overall_progress"].setValue(self.myindex)
334 if self.myindex < len(keys):
335 return keys[self.myindex]
338 elif self.test_type == self.TEST_TYPE_RANDOM:
340 keys = self.randomkeys
342 self["overall_progress"].setValue(self.myindex)
343 if self.myindex < len(keys):
344 return keys[self.myindex]
348 # after each index is finished and the next index is returned by getNextIndex
349 # the algorithm checks, if we should continue scanning
350 def getContinueScanning(self):
351 if self.test_type == self.TEST_TYPE_QUICK or self.test_type == self.TEST_TYPE_RANDOM:
352 return (self.myindex < len(self.indexlist.keys()))
354 def addResult(self, index, status, failedTune, successfullyTune):
355 self.results[index] = self.results.get(index, {"failed": [], "successful": [], "status": None})
356 self.resultsstatus[status] = self.resultsstatus.get(status, [])
358 self.results[index]["status"] = status
359 self.results[index]["failed"] = failedTune
360 self.results[index]["successful"] = successfullyTune
362 self.resultsstatus[status].append(index)
364 def finishedChecking(self):
365 print "finishedChecking"
366 TuneTest.finishedChecking(self)
368 if not self.results.has_key(self.currentlyTestedIndex):
369 self.results[self.currentlyTestedIndex] = {"failed": [], "successful": [], "status": None}
371 if len(self.failedTune) > 0 and len(self.successfullyTune) > 0:
372 self.changeProgressListStatus(self.currentlyTestedIndex, "with errors")
373 self["witherrors_counter"].setText(str(int(self["witherrors_counter"].getText()) + 1))
374 self.addResult(self.currentlyTestedIndex, "with_errors", self.failedTune, self.successfullyTune)
375 elif len(self.failedTune) == 0 and len(self.successfullyTune) == 0:
376 self.changeProgressListStatus(self.currentlyTestedIndex, "not tested")
377 self["untestable_counter"].setText(str(int(self["untestable_counter"].getText()) + 1))
378 self.addResult(self.currentlyTestedIndex, "untestable", self.failedTune, self.successfullyTune)
379 elif len(self.failedTune) > 0:
380 self.changeProgressListStatus(self.currentlyTestedIndex, "failed")
381 self["failed_counter"].setText(str(int(self["failed_counter"].getText()) + len(self.failedTune)))
382 self.addResult(self.currentlyTestedIndex, "failed", self.failedTune, self.successfullyTune)
384 self.changeProgressListStatus(self.currentlyTestedIndex, "successful")
385 self["succeeded_counter"].setText(str(int(self["succeeded_counter"].getText()) + len(self.successfullyTune)))
386 self.addResult(self.currentlyTestedIndex, "successful", self.failedTune, self.successfullyTune)
389 #self["failed_counter"].setText(str(int(self["failed_counter"].getText()) + len(self.failedTune)))
390 #self["succeeded_counter"].setText(str(int(self["succeeded_counter"].getText()) + len(self.successfullyTune)))
391 #if len(self.failedTune) == 0 and len(self.successfullyTune) == 0:
392 #self["untestable_counter"].setText(str(int(self["untestable_counter"].getText()) + 1))
394 self.currentlyTestedIndex = self.getNextIndex()
395 self.addProgressListItem(self.currentlyTestedIndex)
397 if self.fillTransponderList():
398 self.run(checkPIDs = True)
401 self["progress_list"].setIndex(0)
402 print "results:", self.results
403 print "resultsstatus:", self.resultsstatus
407 self["failed_counter"].setText("0")
408 self["succeeded_counter"].setText("0")
409 self["untestable_counter"].setText("0")
410 self.currentlyTestedIndex = self.getFirstIndex()
412 self.clearProgressList()
413 self.addProgressListItem(self.currentlyTestedIndex)
415 if self.fillTransponderList():
422 print "selectedIndex:", self["progress_list"].getCurrent()[0]
424 index = self["progress_list"].getCurrent()[0]
425 #self.setResultType(ResultParser.TYPE_BYORBPOS)
426 #self.setResultParameter(index[2])
427 self.setResultType(ResultParser.TYPE_BYINDEX)
428 self.setResultParameter(index)
429 self.session.open(TextBox, self.getTextualResult())
431 def selectionChanged(self):
432 print "selection changed"
433 if len(self.list) > 0 and not self.running:
434 self["CmdText"].setText(_("Press OK to get further details for %s") % str(self["progress_list"].getCurrent()[1]))
436 class DiseqcTesterTestTypeSelection(Screen, ConfigListScreen):
437 skin = """<screen position="80,95" size="560,412" title="DiSEqC Tester Test Settings">
438 <widget name="config" position="10,10" size="540,402" scrollbarMode="showOnDemand" />
441 def __init__(self, session, feid):
442 Screen.__init__(self, session)
446 ConfigListScreen.__init__(self, self.list)
448 self["actions"] = ActionMap(["SetupActions"],
450 "cancel": self.keyCancel
455 def createSetup(self):
456 self.testtype = ConfigSelection(choices={"quick": _("Quick"), "random": _("Random")}, default = "quick")
457 self.testtypeEntry = getConfigListEntry(_("Test Type"), self.testtype)
458 self.list.append(self.testtypeEntry)
460 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")
461 self.loopsfailedEntry = getConfigListEntry(_("Stop testing plane after # failed transponders"), self.loopsfailed)
462 self.list.append(self.loopsfailedEntry)
464 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")
465 self.loopssuccessfulEntry = getConfigListEntry(_("Stop testing plane after # successful transponders"), self.loopssuccessful)
466 self.list.append(self.loopssuccessfulEntry)
468 self["config"].list = self.list
469 self["config"].l.setList(self.list)
472 print self.testtype.getValue()
473 testtype = DiseqcTester.TEST_TYPE_QUICK
474 if self.testtype.getValue() == "quick":
475 testtype = DiseqcTester.TEST_TYPE_QUICK
476 elif self.testtype.getValue() == "random":
477 testtype = DiseqcTester.TEST_TYPE_RANDOM
478 elif self.testtype.getValue() == "complete":
479 testtype = DiseqcTester.TEST_TYPE_COMPLETE
480 self.session.open(DiseqcTester, feid = self.feid, test_type = testtype, loopsfailed = int(self.loopsfailed.value), loopssuccessful = int(self.loopssuccessful.value))
485 class DiseqcTesterNimSelection(NimSelection):
487 <screen position="160,123" size="400,330" title="Choose Tuner">
488 <widget source="nimlist" render="Listbox" position="0,0" size="380,300" scrollbarMode="showOnDemand">
489 <convert type="TemplatedMultiContent">
491 MultiContentEntryText(pos = (10, 5), size = (360, 30), flags = RT_HALIGN_LEFT, text = 1), # index 1 is the nim name,
492 MultiContentEntryText(pos = (50, 30), size = (320, 30), font = 1, flags = RT_HALIGN_LEFT, text = 2), # index 2 is a description of the nim settings,
494 "fonts": [gFont("Regular", 20), gFont("Regular", 15)],
501 def __init__(self, session, args = None):
502 NimSelection.__init__(self, session)
504 def setResultClass(self):
505 #self.resultclass = DiseqcTester
506 self.resultclass = DiseqcTesterTestTypeSelection
508 def showNim(self, nim):
509 nimConfig = nimmanager.getNimConfig(nim.slot)
510 if nim.isCompatible("DVB-S"):
511 if nimConfig.configMode.value in ["loopthrough", "equal", "satposdepends", "nothing"]:
513 if nimConfig.configMode.value == "simple":
514 if nimConfig.diseqcMode.value == "positioner":
519 def DiseqcTesterMain(session, **kwargs):
520 session.open(DiseqcTesterNimSelection)
522 def autostart(reason, **kwargs):
523 resourcemanager.addResource("DiseqcTester", DiseqcTesterMain)
525 def Plugins(**kwargs):
526 return [ PluginDescriptor(name="DiSEqC Tester", description=_("Test DiSEqC settings"), where = PluginDescriptor.WHERE_PLUGINMENU, fnc=DiseqcTesterMain),
527 PluginDescriptor(where = PluginDescriptor.WHERE_AUTOSTART, fnc = autostart)]