1 from enigma import eTimer, eDVBSatelliteEquipmentControl, eDVBResourceManager, \
2 eDVBDiseqcCommand, eDVBFrontendParametersSatellite, eDVBFrontendParameters,\
5 from Screens.Screen import Screen
6 from Screens.MessageBox import MessageBox
7 from Screens.ChoiceBox import ChoiceBox
8 from Plugins.Plugin import PluginDescriptor
9 from Screens.Satconfig import NimSetup
10 from Screens.InfoBar import InfoBar
11 from Components.Label import Label
12 from Components.Button import Button
13 from Components.ConfigList import ConfigList
14 from Components.ConfigList import ConfigListScreen
15 from Components.TunerInfo import TunerInfo
16 from Components.ActionMap import NumberActionMap, ActionMap
17 from Components.NimManager import nimmanager
18 from Components.MenuList import MenuList
19 from Components.ScrollLabel import ScrollLabel
20 from Components.config import config, ConfigSatlist, ConfigNothing, ConfigSelection, \
21 ConfigSubsection, ConfigInteger, ConfigFloat, KEY_LEFT, KEY_RIGHT, KEY_0, getConfigListEntry
22 from Components.TuneTest import Tuner
23 from Components.Pixmap import Pixmap
24 from Tools.Transponder import ConvertToHumanReadable
26 from time import sleep
27 from operator import mul as mul
28 from random import SystemRandom as SystemRandom
29 from threading import Thread as Thread
30 from threading import Event as Event
35 class PositionerSetup(Screen):
38 def satposition2metric(position):
40 position = 3600 - position
44 return (position, orientation)
47 def orbital2metric(position, orientation):
48 if orientation == "west":
49 position = 360 - position
50 if orientation == "south":
55 def longitude2orbital(position):
57 return 360 - position, "west"
59 return position, "east"
62 def latitude2orbital(position):
64 return position, "north"
66 return -position, "south"
68 FIRST_UPDATE_INTERVAL = 500 # milliseconds
69 UPDATE_INTERVAL = 50 # milliseconds
70 STATUS_MSG_TIMEOUT = 2 # seconds
71 LOG_SIZE = 16 * 1024 # log buffer size
73 def __init__(self, session, feid):
74 self.session = session
75 Screen.__init__(self, session)
76 self.setTitle(_("Positioner setup"))
78 self.oldref = self.session.nav.getCurrentlyPlayingServiceOrGroup()
79 self.oldref_stop = False
80 self.rotor_diseqc = True
82 self.rotor_pos = config.usage.showdish.value and config.misc.lastrotorposition.value != 9999
84 getCurrentTuner = None
86 self.availablesats = []
87 log.open(self.LOG_SIZE)
88 if config.Nims[self.feid].configMode.value == 'advanced':
90 self.advancedconfig = config.Nims[self.feid].advanced
91 self.advancedsats = self.advancedconfig.sat
92 self.availablesats = map(lambda x: x[0], nimmanager.getRotorSatListForNim(self.feid))
95 self.availablesats = map(lambda x: x[0], nimmanager.getRotorSatListForNim(self.feid))
98 if not self.openFrontend():
99 service = self.session.nav.getCurrentService()
100 feInfo = service and service.frontendInfo()
102 cur_info = feInfo.getTransponderData(True)
103 frontendData = feInfo.getAll(True)
104 getCurrentTuner = frontendData and frontendData.get("tuner_number", None)
105 getCurrentSat = cur_info.get('orbital_position', None)
108 if self.oldref and getCurrentTuner is not None:
109 if getCurrentTuner < 4 and self.feid == getCurrentTuner:
110 self.oldref_stop = True
112 self.session.nav.stopService() # try to disable foreground service
113 if getCurrentSat is not None and getCurrentSat in self.availablesats:
116 self.rotor_diseqc = False
117 getCurrentTuner = None
119 if not self.openFrontend():
120 if hasattr(session, 'pipshown') and session.pipshown: # try to disable pip
121 service = self.session.pip.pipservice
122 feInfo = service and service.frontendInfo()
124 cur_pip_info = feInfo.getTransponderData(True)
125 frontendData = feInfo.getAll(True)
126 getCurrentTuner = frontendData and frontendData.get("tuner_number", None)
127 getCurrentSat = cur_pip_info.get('orbital_position', None)
128 if getCurrentTuner is not None and getCurrentTuner < 4 and self.feid == getCurrentTuner:
129 if getCurrentSat is not None and getCurrentSat in self.availablesats:
132 self.rotor_diseqc = False
135 InfoBar.instance and hasattr(InfoBar.instance, "showPiP") and InfoBar.instance.showPiP()
136 if hasattr(session, 'pip'): # try to disable pip again
138 session.pipshown = False
139 if not self.openFrontend():
140 self.frontend = None # in normal case this should not happen
141 if hasattr(self, 'raw_channel'):
143 if self.frontend is None:
144 self.messageTimer = eTimer()
145 self.messageTimer.callback.append(self.showMessageBox)
146 self.messageTimer.start(2000, True)
147 self.frontendStatus = { }
148 self.diseqc = Diseqc(self.frontend)
149 # True means we dont like that the normal sec stuff sends commands to the rotor!
150 self.tuner = Tuner(self.frontend, ignore_rotor = True)
152 tp = ( cur.get("frequency", 0) / 1000,
153 cur.get("symbol_rate", 0) / 1000,
154 cur.get("polarization", eDVBFrontendParametersSatellite.Polarisation_Horizontal),
155 cur.get("fec_inner", eDVBFrontendParametersSatellite.FEC_Auto),
156 cur.get("inversion", eDVBFrontendParametersSatellite.Inversion_Unknown),
157 cur.get("orbital_position", 0),
158 cur.get("system", eDVBFrontendParametersSatellite.System_DVB_S),
159 cur.get("modulation", eDVBFrontendParametersSatellite.Modulation_QPSK),
160 cur.get("rolloff", eDVBFrontendParametersSatellite.RollOff_alpha_0_35),
161 cur.get("pilot", eDVBFrontendParametersSatellite.Pilot_Unknown))
164 self.isMoving = False
165 self.stopOnLock = False
167 self.red = Button("")
168 self["key_red"] = self.red
169 self.green = Button("")
170 self["key_green"] = self.green
171 self.yellow = Button("")
172 self["key_yellow"] = self.yellow
173 self.blue = Button("")
174 self["key_blue"] = self.blue
177 self["list"] = ConfigList(self.list)
179 self["snr_db"] = TunerInfo(TunerInfo.SNR_DB, statusDict = self.frontendStatus)
180 self["snr_bar"] = TunerInfo(TunerInfo.SNR_BAR, statusDict = self.frontendStatus)
181 self["snr_percentage"] = TunerInfo(TunerInfo.SNR_PERCENTAGE, statusDict = self.frontendStatus)
182 self["agc_percentage"] = TunerInfo(TunerInfo.AGC_PERCENTAGE, statusDict = self.frontendStatus)
183 self["agc_bar"] = TunerInfo(TunerInfo.AGC_BAR, statusDict = self.frontendStatus)
184 self["ber_value"] = TunerInfo(TunerInfo.BER_VALUE, statusDict = self.frontendStatus)
185 self["ber_bar"] = TunerInfo(TunerInfo.BER_BAR, statusDict = self.frontendStatus)
186 self["lock_state"] = TunerInfo(TunerInfo.LOCK_STATE, statusDict = self.frontendStatus)
188 self["rotorstatus"] = Label("")
189 self["frequency_value"] = Label("")
190 self["symbolrate_value"] = Label("")
191 self["fec_value"] = Label("")
192 self["status_bar"] = Label("")
193 self["SNR"] = Label(_("SNR:"))
194 self["BER"] = Label(_("BER:"))
195 self["AGC"] = Label(_("AGC:"))
196 self["Frequency"] = Label(_("Frequency:"))
197 self["Symbolrate"] = Label (_("Symbol rate:"))
198 self["FEC"] = Label (_("FEC:"))
199 self["Lock"] = Label(_("Lock:"))
200 self["lock_off"] = Pixmap()
201 self["lock_on"] = Pixmap()
202 self["lock_on"].hide()
204 if hasattr(eDVBSatelliteEquipmentControl.getInstance(), "getTargetOrbitalPosition"):
205 current_pos = eDVBSatelliteEquipmentControl.getInstance().getTargetOrbitalPosition()
206 if current_pos != 0 and current_pos != config.misc.lastrotorposition.value:
207 config.misc.lastrotorposition.value = current_pos
208 config.misc.lastrotorposition.save()
209 text = _("Current rotor position: ") + self.OrbToStr(config.misc.lastrotorposition.value)
210 self["rotorstatus"].setText(text)
211 self.statusMsgTimeoutTicks = 0
212 self.statusMsgBlinking = False
213 self.statusMsgBlinkCount = 0
214 self.statusMsgBlinkRate = 500 / self.UPDATE_INTERVAL # milliseconds
215 self.tuningChangedTo(tp)
217 self["actions"] = NumberActionMap(["DirectionActions", "OkCancelActions", "ColorActions", "TimerEditActions", "InputActions", "InfobarMenuActions"],
220 "cancel": self.keyCancel,
222 "down": self.keyDown,
223 "left": self.keyLeft,
224 "right": self.keyRight,
226 "green": self.greenKey,
227 "yellow": self.yellowKey,
228 "blue": self.blueKey,
230 "mainMenu": self.furtherOptions,
231 "1": self.keyNumberGlobal,
232 "2": self.keyNumberGlobal,
233 "3": self.keyNumberGlobal,
234 "4": self.keyNumberGlobal,
235 "5": self.keyNumberGlobal,
236 "6": self.keyNumberGlobal,
237 "7": self.keyNumberGlobal,
238 "8": self.keyNumberGlobal,
239 "9": self.keyNumberGlobal,
240 "0": self.keyNumberGlobal
243 self.updateColors("tune")
244 self.statusTimer = eTimer()
245 self.rotorStatusTimer = eTimer()
246 self.statusTimer.callback.append(self.updateStatus)
247 self.rotorStatusTimer.callback.append(self.startStatusTimer)
248 self.collectingStatistics = False
249 self.statusTimer.start(self.FIRST_UPDATE_INTERVAL, True)
250 self.dataAvailable = Event()
251 self.onClose.append(self.__onClose)
256 self.statusTimer.stop()
258 self.session.nav.playService(self.oldref)
260 def OrbToStr(self, orbpos):
262 orbpos = 3600 - orbpos
263 return "%d.%d\xc2\xb0 W" % (orbpos/10, orbpos%10)
264 return "%d.%d\xc2\xb0 E" % (orbpos/10, orbpos%10)
266 def setDishOrbosValue(self):
267 if self.getRotorMovingState():
268 if self.orb_pos != 0 and self.orb_pos != config.misc.lastrotorposition.value:
269 config.misc.lastrotorposition.value = self.orb_pos
270 config.misc.lastrotorposition.save()
271 text = _("Moving to position") + " " + self.OrbToStr(self.orb_pos)
272 self.startStatusTimer()
274 text = _("Current rotor position: ") + self.OrbToStr(config.misc.lastrotorposition.value)
275 self["rotorstatus"].setText(text)
277 def startStatusTimer(self):
278 self.rotorStatusTimer.start(1000, True)
280 def getRotorMovingState(self):
281 return eDVBSatelliteEquipmentControl.getInstance().isRotorMoving()
283 def showMessageBox(self):
284 text = _("Sorry, this tuner is in use.")
285 if self.session.nav.getRecordings():
287 text += _("Maybe the reason that recording is currently running. Please stop the recording before trying to configure the positioner.")
288 self.session.open(MessageBox, text, MessageBox.TYPE_ERROR)
290 def restartPrevService(self, yesno):
294 if hasattr(self, 'raw_channel'):
301 if self.oldref is not None:
303 self.session.openWithCallback(self.restartPrevService, MessageBox, _("Zap back to service before positioner setup?"), MessageBox.TYPE_YESNO)
305 self.restartPrevService(True)
307 self.restartPrevService(False)
309 def openFrontend(self):
311 if hasattr(self, 'raw_channel'):
313 res_mgr = eDVBResourceManager.getInstance()
315 self.raw_channel = res_mgr.allocateRawChannel(self.feid)
317 self.frontend = self.raw_channel.getFrontend()
321 print "getFrontend failed"
323 print "getRawChannel failed"
325 print "getResourceManager instance failed"
328 def setLNB(self, lnb):
330 self.sitelon = lnb.longitude.float
331 self.longitudeOrientation = lnb.longitudeOrientation.value
332 self.sitelat = lnb.latitude.float
333 self.latitudeOrientation = lnb.latitudeOrientation.value
334 self.tuningstepsize = lnb.tuningstepsize.float
335 self.rotorPositions = lnb.rotorPositions.value
336 self.turningspeedH = lnb.turningspeedH.float
337 self.turningspeedV = lnb.turningspeedV.float
338 except: # some reasonable defaults from NimManager
340 self.longitudeOrientation = 'east'
341 self.sitelat = 50.767
342 self.latitudeOrientation = 'north'
343 self.tuningstepsize = 0.36
344 self.rotorPositions = 99
345 self.turningspeedH = 2.3
346 self.turningspeedV = 1.7
347 self.sitelat = PositionerSetup.orbital2metric(self.sitelat, self.latitudeOrientation)
348 self.sitelon = PositionerSetup.orbital2metric(self.sitelon, self.longitudeOrientation)
350 def createConfig(self):
353 self.printMsg(_("Using tuner %s") % chr(0x41 + self.feid))
354 if not self.advanced:
355 self.printMsg(_("Configuration mode: %s") % _("simple"))
356 nim = config.Nims[self.feid]
357 self.sitelon = nim.longitude.float
358 self.longitudeOrientation = nim.longitudeOrientation.value
359 self.sitelat = nim.latitude.float
360 self.latitudeOrientation = nim.latitudeOrientation.value
361 self.sitelat = PositionerSetup.orbital2metric(self.sitelat, self.latitudeOrientation)
362 self.sitelon = PositionerSetup.orbital2metric(self.sitelon, self.longitudeOrientation)
363 self.tuningstepsize = nim.tuningstepsize.float
364 self.rotorPositions = nim.rotorPositions.value
365 self.turningspeedH = nim.turningspeedH.float
366 self.turningspeedV = nim.turningspeedV.float
367 else: # it is advanced
369 self.printMsg(_("Configuration mode: %s") % _("advanced"))
372 self.frontend.getFrontendData(fe_data)
373 self.frontend.getTransponderData(fe_data, True)
374 orb_pos = fe_data.get("orbital_position", None)
375 if orb_pos is not None and orb_pos in self.availablesats:
376 rotorposition = int(self.advancedsats[orb_pos].rotorposition.value)
377 lnb = self.getLNBfromConfig(orb_pos)
379 self.positioner_tune = ConfigNothing()
380 self.positioner_move = ConfigNothing()
381 self.positioner_finemove = ConfigNothing()
382 self.positioner_limits = ConfigNothing()
383 self.positioner_storage = ConfigInteger(default = rotorposition, limits = (1, self.rotorPositions))
384 self.allocatedIndices = []
385 m = PositionerSetup.satposition2metric(orb_pos)
386 self.orbitalposition = ConfigFloat(default = [int(m[0] / 10), m[0] % 10], limits = [(0,180),(0,9)])
387 self.orientation = ConfigSelection([("east", _("East")), ("west", _("West"))], default = m[1])
388 for x in (self.positioner_tune, self.positioner_storage, self.orbitalposition):
389 x.addNotifier(self.retune, initial_call = False)
391 def retune(self, configElement):
396 if self.frontend is not None:
399 self.frontend.getFrontendData(fe_data)
400 self.frontend.getTransponderData(fe_data, True)
401 orb_pos = fe_data.get("orbital_position", -9999)
403 pos = str(PositionerSetup.orbital2metric(self.orbitalposition.float, self.orientation.value))
404 orb_val = int(pos.replace('.', ''))
408 if orb_val == orb_pos:
410 elif orb_val != -9999 and orb_val in self.availablesats:
412 if sat != -9999 and sat in self.availablesats:
413 usals = self.advancedsats[sat].usals.value
414 self.rotor_diseqc = True
417 self.rotor_diseqc = True
421 def getLNBfromConfig(self, orb_pos):
422 if orb_pos is None or orb_pos == 0:
425 if orb_pos in self.availablesats:
426 lnbnum = int(self.advancedsats[orb_pos].lnb.value)
428 for allsats in range(3601, 3607):
429 lnbnum = int(self.advancedsats[allsats].lnb.value)
433 self.printMsg(_("Using LNB %d") % lnbnum)
434 lnb = self.advancedconfig.lnb[lnbnum]
436 self.logMsg(_("Warning: no LNB; using factory defaults."), timeout = 8)
439 def createSetup(self):
441 self.list.append((_("Tune and focus"), self.positioner_tune, "tune"))
442 self.list.append((_("Movement"), self.positioner_move, "move"))
443 self.list.append((_("Fine movement"), self.positioner_finemove, "finemove"))
444 self.list.append((_("Set limits"), self.positioner_limits, "limits"))
445 self.list.append((_("Memory index") + (self.getUsals() and " (USALS)" or ""), self.positioner_storage, "storage"))
446 self.list.append((_("Goto"), self.orbitalposition, "goto"))
447 self.list.append((" ", self.orientation, "goto"))
448 self["list"].l.setList(self.list)
453 def getCurrentConfigPath(self):
454 return self["list"].getCurrent()[2]
457 if not self.isMoving:
458 self["list"].instance.moveSelection(self["list"].instance.moveUp)
459 self.updateColors(self.getCurrentConfigPath())
462 if not self.isMoving:
463 self["list"].instance.moveSelection(self["list"].instance.moveDown)
464 self.updateColors(self.getCurrentConfigPath())
466 def keyNumberGlobal(self, number):
467 if self.frontend is None:
469 self["list"].handleKey(KEY_0 + number)
472 if self.frontend is None:
474 self["list"].handleKey(KEY_LEFT)
477 if self.frontend is None:
479 self["list"].handleKey(KEY_RIGHT)
481 def updateColors(self, entry):
482 if self.frontend is None:
485 self.red.setText(_("Tune"))
486 self.green.setText(_("Auto focus"))
487 self.yellow.setText(_("Calibrate"))
488 self.blue.setText(_("Calculate"))
489 elif entry == "move":
491 self.red.setText(_("Stop"))
492 self.green.setText(_("Stop"))
493 self.yellow.setText(_("Stop"))
494 self.blue.setText(_("Stop"))
496 self.red.setText(_("Move west"))
497 self.green.setText(_("Search west"))
498 self.yellow.setText(_("Search east"))
499 self.blue.setText(_("Move east"))
500 elif entry == "finemove":
502 self.green.setText(_("Step west"))
503 self.yellow.setText(_("Step east"))
504 self.blue.setText("")
505 elif entry == "limits":
506 self.red.setText(_("Limits off"))
507 self.green.setText(_("Limit west"))
508 self.yellow.setText(_("Limit east"))
509 self.blue.setText(_("Limits on"))
510 elif entry == "storage":
512 if self.getUsals() is False:
513 self.green.setText(_("Store position"))
514 self.yellow.setText(_("Goto position"))
516 self.green.setText("")
517 self.yellow.setText("")
518 if self.advanced and self.getUsals() is False:
519 self.blue.setText(_("Allocate"))
521 self.blue.setText("")
522 elif entry == "goto":
524 self.green.setText(_("Goto 0"))
525 self.yellow.setText(_("Goto X"))
526 self.blue.setText("")
529 self.green.setText("")
530 self.yellow.setText("")
531 self.blue.setText("")
533 def printMsg(self, msg):
537 def stopMoving(self):
538 self.printMsg(_("Stop"))
539 self.diseqccommand("stop")
540 self.isMoving = False
541 self.stopOnLock = False
542 self.statusMsg(_("Stopped"), timeout = self.STATUS_MSG_TIMEOUT)
545 if self.frontend is None:
547 entry = self.getCurrentConfigPath()
552 self.printMsg(_("Move west"))
553 self.diseqccommand("moveWest", 0)
555 self.statusMsg(_("Moving west ..."), blinking = True)
556 self.updateColors("move")
557 elif entry == "limits":
558 self.printMsg(_("Limits off"))
559 self.diseqccommand("limitOff")
560 self.statusMsg(_("Limits cancelled"), timeout = self.STATUS_MSG_TIMEOUT)
561 elif entry == "tune":
563 self.frontend.getFrontendData(fe_data)
564 self.frontend.getTransponderData(fe_data, True)
565 feparm = self.tuner.lastparm.getDVBS()
566 fe_data["orbital_position"] = feparm.orbital_position
567 self.statusTimer.stop()
568 self.session.openWithCallback(self.tune, TunerScreen, self.feid, fe_data)
571 if self.frontend is None:
573 entry = self.getCurrentConfigPath()
576 self.printMsg(_("Auto focus"))
577 print>>log, (_("Site latitude") + " : %5.1f %s") % PositionerSetup.latitude2orbital(self.sitelat)
578 print>>log, (_("Site longitude") + " : %5.1f %s") % PositionerSetup.longitude2orbital(self.sitelon)
579 Thread(target = self.autofocus).start()
580 elif entry == "move":
584 self.printMsg(_("Search west"))
586 self.stopOnLock = True
587 self.diseqccommand("moveWest", 0)
588 self.statusMsg(_("Searching west ..."), blinking = True)
589 self.updateColors("move")
590 elif entry == "finemove":
591 self.printMsg(_("Step west"))
592 self.diseqccommand("moveWest", 0xFF) # one step
593 self.statusMsg(_("Stepped west"), timeout = self.STATUS_MSG_TIMEOUT)
594 elif entry == "storage":
595 if self.getUsals() is False:
596 menu = [(_("Yes"), "yes"), (_("No"), "no")]
597 available_orbos = False
601 orb_pos = str(PositionerSetup.orbital2metric(self.orbitalposition.float, self.orientation.value))
602 orbos = int(orb_pos.replace('.', ''))
605 if orbos is not None and orbos in self.availablesats:
606 available_orbos = True
607 menu.append((_("Yes (save index in setup tuner)"), "save"))
608 index = int(self.positioner_storage.value)
609 text = _("Really store at index %2d for current position?") % index
610 def saveAction(choice):
612 if choice[1] in ("yes", "save"):
613 self.printMsg(_("Store at index"))
614 self.diseqccommand("store", index)
615 self.statusMsg((_("Position stored at index") + " %2d") % index, timeout = self.STATUS_MSG_TIMEOUT)
616 if choice[1] == "save" and available_orbos:
617 self.advancedsats[orbos].rotorposition.value = index
618 self.advancedsats[orbos].rotorposition.save()
619 self.session.openWithCallback(saveAction, ChoiceBox, title=text, list=menu)
620 elif entry == "limits":
621 self.printMsg(_("Limit west"))
622 self.diseqccommand("limitWest")
623 self.statusMsg(_("West limit set"), timeout = self.STATUS_MSG_TIMEOUT)
624 elif entry == "goto":
625 self.printMsg(_("Goto 0"))
626 self.diseqccommand("moveTo", 0)
627 self.statusMsg(_("Moved to position 0"), timeout = self.STATUS_MSG_TIMEOUT)
630 if self.frontend is None:
632 entry = self.getCurrentConfigPath()
637 self.printMsg(_("Move east"))
639 self.stopOnLock = True
640 self.diseqccommand("moveEast", 0)
641 self.statusMsg(_("Searching east ..."), blinking = True)
642 self.updateColors("move")
643 elif entry == "finemove":
644 self.printMsg(_("Step east"))
645 self.diseqccommand("moveEast", 0xFF) # one step
646 self.statusMsg(_("Stepped east"), timeout = self.STATUS_MSG_TIMEOUT)
647 elif entry == "storage":
648 if self.getUsals() is False:
649 self.printMsg(_("Goto index position"))
650 index = int(self.positioner_storage.value)
651 self.diseqccommand("moveTo", index)
652 self.statusMsg((_("Moved to position at index") + " %2d") % index, timeout = self.STATUS_MSG_TIMEOUT)
653 elif entry == "limits":
654 self.printMsg(_("Limit east"))
655 self.diseqccommand("limitEast")
656 self.statusMsg(_("East limit set"), timeout = self.STATUS_MSG_TIMEOUT)
657 elif entry == "goto":
658 self.printMsg(_("Move to position X"))
659 satlon = self.orbitalposition.float
660 position = ("%5.1f %s") % (satlon, self.orientation.value)
661 print>>log, (_("Satellite longitude:") + " %s") % position
662 satlon = PositionerSetup.orbital2metric(satlon, self.orientation.value)
663 self.statusMsg((_("Moving to position") + " %s") % position, timeout = self.STATUS_MSG_TIMEOUT)
665 elif entry == "tune":
666 # Start USALS calibration
667 self.printMsg(_("USALS calibration"))
668 print>>log, (_("Site latitude") + " : %5.1f %s") % PositionerSetup.latitude2orbital(self.sitelat)
669 print>>log, (_("Site longitude") + " : %5.1f %s") % PositionerSetup.longitude2orbital(self.sitelon)
670 Thread(target = self.gotoXcalibration).start()
673 if self.frontend is None:
675 entry = self.getCurrentConfigPath()
680 self.printMsg(_("Move east"))
681 self.diseqccommand("moveEast", 0)
683 self.statusMsg(_("Moving east ..."), blinking = True)
684 self.updateColors("move")
685 elif entry == "limits":
686 self.printMsg(_("Limits on"))
687 self.diseqccommand("limitOn")
688 self.statusMsg(_("Limits enabled"), timeout = self.STATUS_MSG_TIMEOUT)
689 elif entry == "tune":
690 # Start (re-)calculate
691 self.session.openWithCallback(self.recalcConfirmed, MessageBox, _("This will (re-)calculate all positions of your rotor and may remove previously memorised positions and fine-tuning!\nAre you sure?"), MessageBox.TYPE_YESNO, default = False, timeout = 10)
692 elif entry == "storage":
693 if self.advanced and self.getUsals() is False:
694 self.printMsg(_("Allocate unused memory index"))
696 if not len(self.allocatedIndices):
697 for sat in self.availablesats:
698 usals = self.advancedsats[sat].usals.value
700 self.allocatedIndices.append(int(self.advancedsats[sat].rotorposition.value))
701 if len(self.allocatedIndices) == self.rotorPositions:
702 self.statusMsg(_("No free index available"), timeout = self.STATUS_MSG_TIMEOUT)
705 if len(self.allocatedIndices):
706 for i in sorted(self.allocatedIndices):
710 if index <= self.rotorPositions:
711 self.positioner_storage.value = index
712 self["list"].invalidateCurrent()
713 self.allocatedIndices.append(index)
714 self.statusMsg((_("Index allocated:") + " %2d") % index, timeout = self.STATUS_MSG_TIMEOUT)
717 self.allocatedIndices = []
719 def recalcConfirmed(self, yesno):
721 self.printMsg(_("Calculate all positions"))
722 print>>log, (_("Site latitude") + " : %5.1f %s") % PositionerSetup.latitude2orbital(self.sitelat)
723 print>>log, (_("Site longitude") + " : %5.1f %s") % PositionerSetup.longitude2orbital(self.sitelon)
727 if lon < -30: # americas, make unsigned binary west positive polarity
729 lon = int(round(lon)) & 0xFF
730 lat = int(round(self.sitelat)) & 0xFF
731 index = int(self.positioner_storage.value) & 0xFF
732 self.diseqccommand("calc", (((index << 8) | lon) << 8) | lat)
733 self.statusMsg(_("Calculation complete"), timeout = self.STATUS_MSG_TIMEOUT)
736 self.session.open(PositionerSetupLog)
738 def diseqccommand(self, cmd, param = 0):
739 print>>log, "Diseqc(%s, %X)" % (cmd, param)
740 self["rotorstatus"].setText("")
741 self.diseqc.command(cmd, param)
744 def tune(self, transponder):
745 # re-start the update timer
746 self.statusTimer.start(self.UPDATE_INTERVAL, True)
748 if transponder is not None:
749 self.tuner.tune(transponder)
750 self.tuningChangedTo(transponder)
751 feparm = self.tuner.lastparm.getDVBS()
752 orb_pos = feparm.orbital_position
753 m = PositionerSetup.satposition2metric(orb_pos)
754 self.orbitalposition.value = [int(m[0] / 10), m[0] % 10]
755 self.orientation.value = m[1]
757 if orb_pos in self.availablesats:
758 rotorposition = int(self.advancedsats[orb_pos].rotorposition.value)
759 self.positioner_storage.value = rotorposition
760 self.allocatedIndices = []
761 self.setLNB(self.getLNBfromConfig(orb_pos))
763 def furtherOptions(self):
765 text = _("Select action")
766 description = _("Open setup tuner ") + "%s" % chr(0x41 + self.feid)
767 menu.append((description, self.openTunerSetup))
768 def openAction(choice):
771 self.session.openWithCallback(openAction, ChoiceBox, title=text, list=menu)
773 def openTunerSetup(self):
774 self.session.openWithCallback(self.closeTunerSetup, NimSetup, self.feid)
776 def closeTunerSetup(self):
777 self.restartPrevService(True)
780 return self.frontendStatus.get("tuner_locked", 0) == 1
782 def statusMsg(self, msg, blinking = False, timeout = 0): # timeout in seconds
783 self.statusMsgBlinking = blinking
785 self["status_bar"].visible = True
786 self["status_bar"].setText(msg)
787 self.statusMsgTimeoutTicks = (timeout * 1000 + self.UPDATE_INTERVAL / 2) / self.UPDATE_INTERVAL
789 def updateStatus(self):
790 self.statusTimer.start(self.UPDATE_INTERVAL, True)
792 self.frontend.getFrontendStatus(self.frontendStatus)
793 if self.rotor_diseqc:
794 self["snr_db"].update()
795 self["snr_percentage"].update()
796 self["ber_value"].update()
797 self["snr_bar"].update()
798 self["agc_percentage"].update()
799 self["agc_bar"].update()
800 self["ber_bar"].update()
801 self["lock_state"].update()
802 if self["lock_state"].getValue(TunerInfo.LOCK):
803 self["lock_on"].show()
805 self["lock_on"].hide()
806 if self.statusMsgBlinking:
807 self.statusMsgBlinkCount += 1
808 if self.statusMsgBlinkCount == self.statusMsgBlinkRate:
809 self.statusMsgBlinkCount = 0
810 self["status_bar"].visible = not self["status_bar"].visible
811 if self.statusMsgTimeoutTicks > 0:
812 self.statusMsgTimeoutTicks -= 1
813 if self.statusMsgTimeoutTicks == 0:
814 self["status_bar"].setText("")
815 self.statusMsgBlinking = False
816 self["status_bar"].visible = True
817 if self.isLocked() and self.isMoving and self.stopOnLock:
819 self.updateColors(self.getCurrentConfigPath())
820 if self.collectingStatistics:
821 self.low_rate_adapter_count += 1
822 if self.low_rate_adapter_count == self.MAX_LOW_RATE_ADAPTER_COUNT:
823 self.low_rate_adapter_count = 0
824 self.snr_percentage += self["snr_percentage"].getValue(TunerInfo.SNR)
825 self.lock_count += self["lock_state"].getValue(TunerInfo.LOCK)
827 if self.stat_count == self.max_count:
828 self.collectingStatistics = False
829 count = float(self.stat_count)
830 self.lock_count /= count
831 self.snr_percentage *= 100.0 / 0x10000 / count
832 self.dataAvailable.set()
834 def tuningChangedTo(self, tp):
836 def setLowRateAdapterCount(symbolrate):
837 # change the measurement time and update interval in case of low symbol rate,
838 # since more time is needed for the front end in that case.
839 # It is an heuristic determination without any pretence. For symbol rates
840 # of 5000 the interval is multiplied by 3 until 15000 which is seen
841 # as a high symbol rate. Linear interpolation elsewhere.
842 return max(int(round((3 - 1) * (symbolrate - 15000) / (5000 - 15000) + 1)), 1)
844 self.symbolrate = tp[1]
845 self.polarisation = tp[2]
846 self.MAX_LOW_RATE_ADAPTER_COUNT = setLowRateAdapterCount(self.symbolrate)
847 if len(self.tuner.getTransponderData()):
848 transponderdata = ConvertToHumanReadable(self.tuner.getTransponderData(), "DVB-S")
850 transponderdata = { }
851 polarization_text = ""
852 polarization = transponderdata.get("polarization")
854 polarization_text = str(polarization)
855 if polarization_text == _("Horizontal"):
856 polarization_text = " H"
857 elif polarization_text == _("Vertical"):
858 polarization_text = " V"
859 elif polarization_text == _("Circular right"):
860 polarization_text = " R"
861 elif polarization_text == _("Circular left"):
862 polarization_text = " L"
864 frequency = transponderdata.get("frequency")
866 frequency_text = str(frequency / 1000) + polarization_text
867 self["frequency_value"].setText(frequency_text)
869 symbolrate = transponderdata.get("symbol_rate")
871 symbolrate_text = str(symbolrate / 1000)
872 self["symbolrate_value"].setText(symbolrate_text)
874 fec_inner = transponderdata.get("fec_inner")
876 if frequency and symbolrate:
877 fec_text = str(fec_inner)
878 self["fec_value"].setText(fec_text)
882 def rotorCmd2Step(rotorCmd, stepsize):
883 return round(float(rotorCmd & 0xFFF) / 0x10 / stepsize) * (1 - ((rotorCmd & 0x1000) >> 11))
886 def gotoXcalc(satlon, sitelat, sitelon):
887 def azimuth2Rotorcode(angle):
888 gotoXtable = (0x00, 0x02, 0x03, 0x05, 0x06, 0x08, 0x0A, 0x0B, 0x0D, 0x0E)
889 a = int(round(abs(angle) * 10.0))
890 return ((a / 10) << 4) + gotoXtable[a % 10]
892 satHourAngle = rotor_calc.calcSatHourangle(satlon, sitelat, sitelon)
893 if sitelat >= 0: # Northern Hemisphere
894 rotorCmd = azimuth2Rotorcode(180 - satHourAngle)
895 if satHourAngle <= 180: # the east
899 else: # Southern Hemisphere
900 if satHourAngle <= 180: # the east
901 rotorCmd = azimuth2Rotorcode(satHourAngle) | 0xD000
903 rotorCmd = azimuth2Rotorcode(360 - satHourAngle) | 0xE000
906 def gotoX(self, satlon):
907 rotorCmd = PositionerSetup.gotoXcalc(satlon, self.sitelat, self.sitelon)
908 self.diseqccommand("gotoX", rotorCmd)
909 x = PositionerSetup.rotorCmd2Step(rotorCmd, self.tuningstepsize)
910 print>>log, (_("Rotor step position:") + " %4d") % x
913 def getTurningspeed(self):
914 if self.polarisation == eDVBFrontendParametersSatellite.Polarisation_Horizontal:
915 turningspeed = self.turningspeedH
917 turningspeed = self.turningspeedV
918 return max(turningspeed, 0.1)
920 TURNING_START_STOP_DELAY = 1.600 # seconds
921 MAX_SEARCH_ANGLE = 12.0 # degrees
922 MAX_FOCUS_ANGLE = 6.0 # degrees
923 LOCK_LIMIT = 0.1 # ratio
924 MEASURING_TIME = 2.500 # seconds
926 def measure(self, time = MEASURING_TIME): # time in seconds
927 self.snr_percentage = 0.0
928 self.lock_count = 0.0
930 self.low_rate_adapter_count = 0
931 self.max_count = max(int((time * 1000 + self.UPDATE_INTERVAL / 2)/ self.UPDATE_INTERVAL), 1)
932 self.collectingStatistics = True
933 self.dataAvailable.clear()
934 self.dataAvailable.wait()
936 def logMsg(self, msg, timeout = 0):
937 self.statusMsg(msg, timeout = timeout)
941 self.lock_count = 0.0
943 while self.lock_count < (1 - self.LOCK_LIMIT) and n < 5:
944 self.measure(time = 0.500)
946 if self.lock_count < (1 - self.LOCK_LIMIT):
950 randomGenerator = None
951 def randomBool(self):
952 if self.randomGenerator is None:
953 self.randomGenerator = SystemRandom()
954 return self.randomGenerator.random() >= 0.5
956 def gotoXcalibration(self):
959 z = self.gotoX(x + satlon)
960 time = int(abs(x - prev_pos) / turningspeed + 2 * self.TURNING_START_STOP_DELAY)
961 sleep(time * self.MAX_LOW_RATE_ADAPTER_COUNT)
964 def reportlevels(pos, level, lock):
965 print>>log, (_("Signal quality") + " %5.1f" + chr(176) + " : %6.2f") % (pos, level)
966 print>>log, (_("Lock ratio") + " %5.1f" + chr(176) + " : %6.2f") % (pos, lock)
968 def optimise(readings):
970 yi = map(lambda (x, y) : x, readings.values())
971 x0 = sum(map(mul, xi, yi)) / sum(yi)
972 xm = xi[yi.index(max(yi))]
987 self.logMsg(_("GotoX calibration"))
988 satlon = self.orbitalposition.float
989 print>>log, (_("Satellite longitude:") + " %5.1f" + chr(176) + " %s") % (satlon, self.orientation.value)
990 satlon = PositionerSetup.orbital2metric(satlon, self.orientation.value)
991 prev_pos = 0.0 # previous relative position w.r.t. satlon
992 turningspeed = self.getTurningspeed()
994 x = 0.0 # relative position w.r.t. satlon
996 if self.randomBool():
998 while abs(x) < self.MAX_SEARCH_ANGLE:
1001 x += (1.0 * dir) # one degree east/west
1002 self.statusMsg((_("Searching") + " " + toGeoposEx(dir) + " %2d" + chr(176)) % abs(x), blinking = True)
1008 while abs(x) < self.MAX_SEARCH_ANGLE:
1009 x += (1.0 * dir) # one degree east/west
1010 self.statusMsg((_("Searching") + " " + toGeoposEx(dir) + " %2d" + chr(176)) % abs(x), blinking = True)
1016 msg = _("Cannot find any signal ..., aborting !")
1019 self.session.open(MessageBox, msg, MessageBox.TYPE_ERROR, timeout = 5)
1021 x = round(x / self.tuningstepsize) * self.tuningstepsize
1026 print>>log, (_("Initial signal quality") + " %5.1f" + chr(176) + ": %6.2f") % (x, self.snr_percentage)
1027 print>>log, (_("Initial lock ratio") + " %5.1f" + chr(176) + ": %6.2f") % (x, self.lock_count)
1028 measurements[x] = (self.snr_percentage, self.lock_count)
1033 if self.randomBool():
1035 while x < self.MAX_FOCUS_ANGLE:
1036 x += self.tuningstepsize * dir # one step east/west
1037 self.statusMsg((_("Moving") + " " + toGeoposEx(dir) + " %5.1f" + chr(176)) % abs(x + start_pos), blinking = True)
1039 prev_pos = x + start_pos
1041 measurements[x + start_pos] = (self.snr_percentage, self.lock_count)
1042 reportlevels(x + start_pos, self.snr_percentage, self.lock_count)
1043 if self.lock_count < self.LOCK_LIMIT:
1046 msg = _("Cannot determine") + " " + toGeoposEx(dir) + " " + _("limit ..., aborting !")
1049 self.session.open(MessageBox, msg, MessageBox.TYPE_ERROR, timeout = 5)
1053 self.statusMsg((_("Moving") + " " + toGeoposEx(dir) + " %5.1f" + chr(176)) % abs(start_pos), blinking = True)
1055 prev_pos = start_pos
1057 msg = _("Sync failure moving back to origin !")
1060 self.session.open(MessageBox, msg, MessageBox.TYPE_ERROR, timeout = 5)
1062 while abs(x) < self.MAX_FOCUS_ANGLE:
1063 x += self.tuningstepsize * dir # one step west/east
1064 self.statusMsg((_("Moving") + " " + toGeoposEx(dir) + " %5.1f" + chr(176)) % abs(x + start_pos), blinking = True)
1066 prev_pos = x + start_pos
1068 measurements[x + start_pos] = (self.snr_percentage, self.lock_count)
1069 reportlevels(x + start_pos, self.snr_percentage, self.lock_count)
1070 if self.lock_count < self.LOCK_LIMIT:
1073 msg = _("Cannot determine") + " " + toGeoposEx(dir) + " " + _("limit ..., aborting !")
1076 self.session.open(MessageBox, msg, MessageBox.TYPE_ERROR, timeout = 5)
1078 (x0, xm) = optimise(measurements)
1084 print>>log, (_("Weighted position") + " : %5.1f" + chr(176) + " %s") % (abs(x0), toGeopos(x0))
1085 print>>log, (_("Strongest position") + " : %5.1f" + chr(176) + " %s") % (abs(xm), toGeopos(xm))
1086 self.logMsg((_("Final position at") + " %5.1f" + chr(176) + " %s / %d; " + _("offset is") + " %4.1f" + chr(176)) % (abs(x0), toGeopos(x0), x, x0 - satlon), timeout = 10)
1088 def autofocus(self):
1092 self.diseqccommand("moveEast", (-x) & 0xFF)
1094 self.diseqccommand("moveWest", x & 0xFF)
1096 time = int(abs(x) * self.tuningstepsize / turningspeed + 2 * self.TURNING_START_STOP_DELAY)
1097 sleep(time * self.MAX_LOW_RATE_ADAPTER_COUNT)
1099 def reportlevels(pos, level, lock):
1100 print>>log, (_("Signal quality") + " [%2d] : %6.2f") % (pos, level)
1101 print>>log, (_("Lock ratio") + " [%2d] : %6.2f") % (pos, lock)
1103 def optimise(readings):
1104 xi = readings.keys()
1105 yi = map(lambda (x, y) : x, readings.values())
1106 x0 = int(round(sum(map(mul, xi, yi)) / sum(yi)))
1107 xm = xi[yi.index(max(yi))]
1116 self.logMsg(_("Auto focus commencing ..."))
1117 turningspeed = self.getTurningspeed()
1119 maxsteps = max(min(round(self.MAX_FOCUS_ANGLE / self.tuningstepsize), 0x1F), 3)
1121 print>>log, (_("Initial signal quality:") + " %6.2f") % self.snr_percentage
1122 print>>log, (_("Initial lock ratio") + " : %6.2f") % self.lock_count
1123 if self.lock_count < 1 - self.LOCK_LIMIT:
1124 msg = _("There is no signal to lock on !")
1127 self.session.open(MessageBox, msg, MessageBox.TYPE_ERROR, timeout = 5)
1129 print>>log, _("Signal OK, proceeding")
1132 if self.randomBool():
1134 measurements[x] = (self.snr_percentage, self.lock_count)
1136 while nsteps < maxsteps:
1138 self.statusMsg((_("Moving") + " " + toGeoposEx(dir) + " %2d") % abs(x), blinking = True)
1139 move(dir) # one step
1141 measurements[x] = (self.snr_percentage, self.lock_count)
1142 reportlevels(x, self.snr_percentage, self.lock_count)
1143 if self.lock_count < self.LOCK_LIMIT:
1147 msg = _("Cannot determine") + " " + toGeoposEx(dir) + " " + _("limit ..., aborting !")
1150 self.session.open(MessageBox, msg, MessageBox.TYPE_ERROR, timeout = 5)
1153 self.statusMsg(_("Moving") + " " + toGeoposEx(dir) + " 0", blinking = True)
1156 msg = _("Sync failure moving back to origin !")
1159 self.session.open(MessageBox, msg, MessageBox.TYPE_ERROR, timeout = 5)
1163 while nsteps < maxsteps:
1165 self.statusMsg((_("Moving") + " " + toGeoposEx(dir) + " %2d") % abs(x), blinking = True)
1166 move(dir) # one step
1168 measurements[x] = (self.snr_percentage, self.lock_count)
1169 reportlevels(x, self.snr_percentage, self.lock_count)
1170 if self.lock_count < self.LOCK_LIMIT:
1174 msg = _("Cannot determine") + " " + toGeoposEx(dir) + " " + _("limit ..., aborting !")
1177 self.session.open(MessageBox, msg, MessageBox.TYPE_ERROR, timeout = 5)
1179 (x0, xm) = optimise(measurements)
1180 print>>log, (_("Weighted position") + " : %2d") % x0
1181 print>>log, (_("Strongest position") + " : %2d") % xm
1182 self.logMsg((_("Final position at index") + " %2d (%5.1f" + chr(176) + ")") % (x0, x0 * self.tuningstepsize), timeout = 6)
1186 def __init__(self, frontend):
1187 self.frontend = frontend
1189 def command(self, what, param = 0):
1191 cmd = eDVBDiseqcCommand()
1192 if what == "moveWest":
1193 string = 'E03169' + ("%02X" % param)
1194 elif what == "moveEast":
1195 string = 'E03168' + ("%02X" % param)
1196 elif what == "moveTo":
1197 string = 'E0316B' + ("%02X" % param)
1198 elif what == "store":
1199 string = 'E0316A' + ("%02X" % param)
1200 elif what == "gotoX":
1201 string = 'E0316E' + ("%04X" % param)
1202 elif what == "calc":
1203 string = 'E0316F' + ("%06X" % param)
1204 elif what == "limitOn":
1206 elif what == "limitOff":
1208 elif what == "limitEast":
1210 elif what == "limitWest":
1213 string = 'E03160' #positioner stop
1215 print "diseqc command:",
1217 cmd.setCommandString(string)
1218 self.frontend.setTone(iDVBFrontend.toneOff)
1219 sleep(0.015) # wait 15msec after disable tone
1220 self.frontend.sendDiseqc(cmd)
1221 if string == 'E03160': #positioner stop
1223 self.frontend.sendDiseqc(cmd) # send 2nd time
1225 class PositionerSetupLog(Screen):
1227 <screen position="center,center" size="560,400" title="Positioner setup log" >
1228 <ePixmap name="red" position="0,0" zPosition="2" size="140,40" pixmap="skin_default/buttons/red.png" transparent="1" alphatest="on" />
1229 <ePixmap name="green" position="230,0" zPosition="2" size="140,40" pixmap="skin_default/buttons/green.png" transparent="1" alphatest="on" />
1230 <ePixmap name="blue" position="420,0" zPosition="2" size="140,40" pixmap="skin_default/buttons/blue.png" transparent="1" alphatest="on" />
1232 <widget name="key_red" position="0,0" size="140,40" valign="center" halign="center" zPosition="4" foregroundColor="white" font="Regular;20" transparent="1" shadowColor="background" shadowOffset="-2,-2" />
1233 <widget name="key_green" position="230,0" size="140,40" halign="center" valign="center" zPosition="4" foregroundColor="white" font="Regular;20" transparent="1" shadowColor="background" shadowOffset="-2,-2" />
1234 <widget name="key_blue" position="420,0" size="140,40" valign="center" halign="center" zPosition="4" foregroundColor="white" font="Regular;20" transparent="1" shadowColor="background" shadowOffset="-2,-2" />
1236 <ePixmap alphatest="on" pixmap="skin_default/icons/clock.png" position="480,383" size="14,14" zPosition="3"/>
1237 <widget font="Regular;18" halign="left" position="505,380" render="Label" size="55,20" source="global.CurrentTime" transparent="1" valign="center" zPosition="3">
1238 <convert type="ClockToText">Default</convert>
1240 <widget name="list" font="Regular;16" position="10,40" size="540,340" />
1243 def __init__(self, session):
1244 self.session = session
1245 Screen.__init__(self, session)
1246 self.setTitle(_("Positioner setup log"))
1247 self["key_red"] = Button(_("Exit/OK"))
1248 self["key_green"] = Button(_("Save"))
1249 self["key_blue"] = Button(_("Clear"))
1250 self["list"] = ScrollLabel(log.getvalue())
1251 self["actions"] = ActionMap(["DirectionActions", "OkCancelActions", "ColorActions"],
1257 "cancel": self.cancel,
1259 "left": self["list"].pageUp,
1260 "right": self["list"].pageDown,
1261 "up": self["list"].pageUp,
1262 "down": self["list"].pageDown,
1263 "pageUp": self["list"].pageUp,
1264 "pageDown": self["list"].pageDown
1269 f = open('/tmp/positionersetup.log', 'w')
1270 f.write(log.getvalue())
1272 self.session.open(MessageBox, _("Write to /tmp/positionersetup.log"), MessageBox.TYPE_INFO, timeout = 5)
1273 except Exception, e:
1274 self["list"].setText(_("Failed to write /tmp/positionersetup.log: ") + str(e))
1282 log.logfile.truncate()
1285 class TunerScreen(ConfigListScreen, Screen):
1287 <screen position="center,center" size="520,400" title="Tune">
1288 <widget name="config" position="20,10" size="460,350" scrollbarMode="showOnDemand" />
1289 <widget name="introduction" position="60,360" size="450,23" halign="left" font="Regular;20" />
1292 def __init__(self, session, feid, fe_data):
1294 self.fe_data = fe_data
1295 Screen.__init__(self, session)
1296 self.setTitle(_("Tune"))
1297 ConfigListScreen.__init__(self, None)
1298 self.createConfig(fe_data)
1301 self.tuning.sat.addNotifier(self.tuningSatChanged)
1302 self.tuning.type.addNotifier(self.tuningTypeChanged)
1303 self.scan_sat.system.addNotifier(self.systemChanged)
1305 self["actions"] = NumberActionMap(["SetupActions"],
1308 "cancel": self.keyCancel,
1310 self["introduction"] = Label(_("Press OK, save and exit..."))
1312 def createConfig(self, frontendData):
1313 satlist = nimmanager.getRotorSatListForNim(self.feid)
1314 orb_pos = self.fe_data.get("orbital_position", None)
1315 self.tuning = ConfigSubsection()
1316 self.tuning.type = ConfigSelection(
1317 default = "manual_transponder",
1318 choices = { "manual_transponder" : _("Manual transponder"),
1319 "predefined_transponder" : _("Predefined transponder") } )
1320 self.tuning.sat = ConfigSatlist(list = satlist)
1321 if orb_pos is not None:
1322 orb_pos_str = str(orb_pos)
1324 if sat[0] == orb_pos and self.tuning.sat.value != orb_pos_str:
1325 self.tuning.sat.value = orb_pos_str
1326 self.updateTransponders()
1330 "system": eDVBFrontendParametersSatellite.System_DVB_S,
1332 "inversion": eDVBFrontendParametersSatellite.Inversion_Unknown,
1333 "symbolrate": 27500,
1334 "polarization": eDVBFrontendParametersSatellite.Polarisation_Horizontal,
1335 "fec": eDVBFrontendParametersSatellite.FEC_Auto,
1336 "fec_s2": eDVBFrontendParametersSatellite.FEC_9_10,
1337 "modulation": eDVBFrontendParametersSatellite.Modulation_QPSK }
1338 if frontendData is not None:
1339 ttype = frontendData.get("tuner_type", "UNKNOWN")
1340 defaultSat["system"] = frontendData.get("system", eDVBFrontendParametersSatellite.System_DVB_S)
1341 defaultSat["frequency"] = frontendData.get("frequency", 0) / 1000
1342 defaultSat["inversion"] = frontendData.get("inversion", eDVBFrontendParametersSatellite.Inversion_Unknown)
1343 defaultSat["symbolrate"] = frontendData.get("symbol_rate", 0) / 1000
1344 defaultSat["polarization"] = frontendData.get("polarization", eDVBFrontendParametersSatellite.Polarisation_Horizontal)
1345 if defaultSat["system"] == eDVBFrontendParametersSatellite.System_DVB_S2:
1346 defaultSat["fec_s2"] = frontendData.get("fec_inner", eDVBFrontendParametersSatellite.FEC_Auto)
1347 defaultSat["rolloff"] = frontendData.get("rolloff", eDVBFrontendParametersSatellite.RollOff_alpha_0_35)
1348 defaultSat["pilot"] = frontendData.get("pilot", eDVBFrontendParametersSatellite.Pilot_Unknown)
1350 defaultSat["fec"] = frontendData.get("fec_inner", eDVBFrontendParametersSatellite.FEC_Auto)
1351 defaultSat["modulation"] = frontendData.get("modulation", eDVBFrontendParametersSatellite.Modulation_QPSK)
1352 defaultSat["orbpos"] = frontendData.get("orbital_position", 0)
1354 self.scan_sat = ConfigSubsection()
1355 self.scan_sat.system = ConfigSelection(default = defaultSat["system"], choices = [
1356 (eDVBFrontendParametersSatellite.System_DVB_S, _("DVB-S")),
1357 (eDVBFrontendParametersSatellite.System_DVB_S2, _("DVB-S2"))])
1358 self.scan_sat.frequency = ConfigInteger(default = defaultSat["frequency"], limits = (1, 99999))
1359 self.scan_sat.inversion = ConfigSelection(default = defaultSat["inversion"], choices = [
1360 (eDVBFrontendParametersSatellite.Inversion_Off, _("Off")),
1361 (eDVBFrontendParametersSatellite.Inversion_On, _("On")),
1362 (eDVBFrontendParametersSatellite.Inversion_Unknown, _("Auto"))])
1363 self.scan_sat.symbolrate = ConfigInteger(default = defaultSat["symbolrate"], limits = (1, 99999))
1364 self.scan_sat.polarization = ConfigSelection(default = defaultSat["polarization"], choices = [
1365 (eDVBFrontendParametersSatellite.Polarisation_Horizontal, _("horizontal")),
1366 (eDVBFrontendParametersSatellite.Polarisation_Vertical, _("vertical")),
1367 (eDVBFrontendParametersSatellite.Polarisation_CircularLeft, _("circular left")),
1368 (eDVBFrontendParametersSatellite.Polarisation_CircularRight, _("circular right"))])
1369 self.scan_sat.fec = ConfigSelection(default = defaultSat["fec"], choices = [
1370 (eDVBFrontendParametersSatellite.FEC_Auto, _("Auto")),
1371 (eDVBFrontendParametersSatellite.FEC_1_2, "1/2"),
1372 (eDVBFrontendParametersSatellite.FEC_2_3, "2/3"),
1373 (eDVBFrontendParametersSatellite.FEC_3_4, "3/4"),
1374 (eDVBFrontendParametersSatellite.FEC_5_6, "5/6"),
1375 (eDVBFrontendParametersSatellite.FEC_7_8, "7/8"),
1376 (eDVBFrontendParametersSatellite.FEC_None, _("None"))])
1377 self.scan_sat.fec_s2 = ConfigSelection(default = defaultSat["fec_s2"], choices = [
1378 (eDVBFrontendParametersSatellite.FEC_1_2, "1/2"),
1379 (eDVBFrontendParametersSatellite.FEC_2_3, "2/3"),
1380 (eDVBFrontendParametersSatellite.FEC_3_4, "3/4"),
1381 (eDVBFrontendParametersSatellite.FEC_3_5, "3/5"),
1382 (eDVBFrontendParametersSatellite.FEC_4_5, "4/5"),
1383 (eDVBFrontendParametersSatellite.FEC_5_6, "5/6"),
1384 (eDVBFrontendParametersSatellite.FEC_7_8, "7/8"),
1385 (eDVBFrontendParametersSatellite.FEC_8_9, "8/9"),
1386 (eDVBFrontendParametersSatellite.FEC_9_10, "9/10")])
1387 self.scan_sat.modulation = ConfigSelection(default = defaultSat["modulation"], choices = [
1388 (eDVBFrontendParametersSatellite.Modulation_QPSK, "QPSK"),
1389 (eDVBFrontendParametersSatellite.Modulation_8PSK, "8PSK")])
1390 self.scan_sat.rolloff = ConfigSelection(default = defaultSat.get("rolloff", eDVBFrontendParametersSatellite.RollOff_alpha_0_35), choices = [
1391 (eDVBFrontendParametersSatellite.RollOff_alpha_0_35, "0.35"),
1392 (eDVBFrontendParametersSatellite.RollOff_alpha_0_25, "0.25"),
1393 (eDVBFrontendParametersSatellite.RollOff_alpha_0_20, "0.20"),
1394 (eDVBFrontendParametersSatellite.RollOff_auto, _("Auto"))])
1395 self.scan_sat.pilot = ConfigSelection(default = defaultSat.get("pilot", eDVBFrontendParametersSatellite.Pilot_Unknown), choices = [
1396 (eDVBFrontendParametersSatellite.Pilot_Off, _("Off")),
1397 (eDVBFrontendParametersSatellite.Pilot_On, _("On")),
1398 (eDVBFrontendParametersSatellite.Pilot_Unknown, _("Auto"))])
1400 def initialSetup(self):
1401 currtp = self.transponderToString([None, self.scan_sat.frequency.value, self.scan_sat.symbolrate.value, self.scan_sat.polarization.value])
1402 if currtp in self.tuning.transponder.choices:
1403 self.tuning.type.value = "predefined_transponder"
1405 self.tuning.type.value = "manual_transponder"
1407 def createSetup(self):
1409 self.list.append(getConfigListEntry(_('Tune'), self.tuning.type))
1410 self.list.append(getConfigListEntry(_('Satellite'), self.tuning.sat))
1411 nim = nimmanager.nim_slots[self.feid]
1413 if self.tuning.type.value == "manual_transponder":
1414 if nim.isCompatible("DVB-S2"):
1415 self.list.append(getConfigListEntry(_('System'), self.scan_sat.system))
1417 # downgrade to dvb-s, in case a -s2 config was active
1418 self.scan_sat.system.value = eDVBFrontendParametersSatellite.System_DVB_S
1419 self.list.append(getConfigListEntry(_('Frequency'), self.scan_sat.frequency))
1420 self.list.append(getConfigListEntry(_("Polarisation"), self.scan_sat.polarization))
1421 self.list.append(getConfigListEntry(_('Symbol rate'), self.scan_sat.symbolrate))
1422 if self.scan_sat.system.value == eDVBFrontendParametersSatellite.System_DVB_S:
1423 self.list.append(getConfigListEntry(_("FEC"), self.scan_sat.fec))
1424 self.list.append(getConfigListEntry(_('Inversion'), self.scan_sat.inversion))
1425 elif self.scan_sat.system.value == eDVBFrontendParametersSatellite.System_DVB_S2:
1426 self.list.append(getConfigListEntry(_("FEC"), self.scan_sat.fec_s2))
1427 self.list.append(getConfigListEntry(_('Inversion'), self.scan_sat.inversion))
1428 self.modulationEntry = getConfigListEntry(_('Modulation'), self.scan_sat.modulation)
1429 self.list.append(self.modulationEntry)
1430 self.list.append(getConfigListEntry(_('Roll-off'), self.scan_sat.rolloff))
1431 self.list.append(getConfigListEntry(_('Pilot'), self.scan_sat.pilot))
1432 else: # "predefined_transponder"
1433 self.list.append(getConfigListEntry(_("Transponder"), self.tuning.transponder))
1434 currtp = self.transponderToString([None, self.scan_sat.frequency.value, self.scan_sat.symbolrate.value, self.scan_sat.polarization.value])
1435 self.tuning.transponder.setValue(currtp)
1436 self["config"].list = self.list
1437 self["config"].l.setList(self.list)
1439 def tuningSatChanged(self, *parm):
1440 self.updateTransponders()
1443 def tuningTypeChanged(self, *parm):
1446 def systemChanged(self, *parm):
1449 def transponderToString(self, tr, scale = 1):
1460 return str(tr[1] / scale) + "," + pol + "," + str(tr[2] / scale)
1462 def updateTransponders(self):
1463 if len(self.tuning.sat.choices):
1464 transponderlist = nimmanager.getTransponders(int(self.tuning.sat.value))
1466 for transponder in transponderlist:
1467 tps.append(self.transponderToString(transponder, scale = 1000))
1468 self.tuning.transponder = ConfigSelection(choices = tps)
1471 ConfigListScreen.keyLeft(self)
1474 ConfigListScreen.keyRight(self)
1477 returnvalue = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
1478 satpos = int(self.tuning.sat.value)
1479 if self.tuning.type.value == "manual_transponder":
1480 if self.scan_sat.system.value == eDVBFrontendParametersSatellite.System_DVB_S2:
1481 fec = self.scan_sat.fec_s2.value
1483 fec = self.scan_sat.fec.value
1485 self.scan_sat.frequency.value,
1486 self.scan_sat.symbolrate.value,
1487 self.scan_sat.polarization.value,
1489 self.scan_sat.inversion.value,
1491 self.scan_sat.system.value,
1492 self.scan_sat.modulation.value,
1493 self.scan_sat.rolloff.value,
1494 self.scan_sat.pilot.value)
1495 elif self.tuning.type.value == "predefined_transponder":
1496 transponder = nimmanager.getTransponders(satpos)[self.tuning.transponder.index]
1497 returnvalue = (transponder[1] / 1000, transponder[2] / 1000,
1498 transponder[3], transponder[4], 2, satpos, transponder[5], transponder[6], transponder[8], transponder[9])
1499 self.close(returnvalue)
1501 def keyCancel(self):
1504 class RotorNimSelection(Screen):
1506 <screen position="center,center" size="400,130" title="Select slot">
1507 <widget name="nimlist" position="20,10" size="360,100" />
1510 def __init__(self, session):
1511 Screen.__init__(self, session)
1512 self.setTitle(_("Select slot"))
1513 nimlist = nimmanager.getNimListOfType("DVB-S")
1516 if len(nimmanager.getRotorSatListForNim(x)) != 0:
1517 nimMenuList.append((nimmanager.nim_slots[x].friendly_full_description, x))
1519 self["nimlist"] = MenuList(nimMenuList)
1521 self["actions"] = ActionMap(["OkCancelActions"],
1523 "ok": self.okbuttonClick ,
1524 "cancel": self.close
1527 def okbuttonClick(self):
1528 selection = self["nimlist"].getCurrent()
1529 self.session.open(PositionerSetup, selection[1])
1531 def PositionerMain(session, **kwargs):
1532 nimList = nimmanager.getNimListOfType("DVB-S")
1533 if len(nimList) == 0:
1534 session.open(MessageBox, _("No positioner capable frontend found."), MessageBox.TYPE_ERROR)
1538 configured_rotor_sats = nimmanager.getRotorSatListForNim(x)
1539 if len(configured_rotor_sats) != 0:
1540 usableNims.append(x)
1541 if len(usableNims) == 1:
1542 session.open(PositionerSetup, usableNims[0])
1543 elif len(usableNims) > 1:
1544 session.open(RotorNimSelection)
1546 session.open(MessageBox, _("No tuner is configured for use with a diseqc positioner!"), MessageBox.TYPE_ERROR)
1548 def PositionerSetupStart(menuid, **kwargs):
1549 if menuid == "scan":
1550 return [(_("Positioner setup"), PositionerMain, "positioner_setup", None)]
1554 def Plugins(**kwargs):
1555 if (nimmanager.hasNimType("DVB-S")):
1556 return PluginDescriptor(name=_("Positioner setup"), description = _("Setup your positioner"), where = PluginDescriptor.WHERE_MENU, needsRestart = False, fnc = PositionerSetupStart)