00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 __facility__ = "Online"
00011 __abstract__ = "Telemetry Monitor"
00012 __author__ = "S. Tuvi <STuvi@SLAC.Stanford.edu>"
00013 __date__ = "2005/09/15 23:45:02"
00014 __updated__ = "$Date: 2006/04/28 01:41:36 $"
00015 __version__ = "$Revision: 1.19 $"
00016 __release__ = "$Name: HEAD $"
00017 __credits__ = "SLAC"
00018
00019 import LICOS.copyright_SLAC
00020
00021 from qt import *
00022 from qttable import *
00023 import sys
00024 import types
00025 import logging as log
00026 from Queue import Queue
00027 import time
00028 import atexit
00029 import threading
00030 from ConfigParser import ConfigParser
00031
00032 import VSC
00033
00034 from LICOS.tools.monitor.TelemMonitor import TelemMonitor
00035 from LICOS.util.gOptions import Options
00036 from LICOS.core.thread.taskEngine import TaskEngine
00037 from LICOS.lib.cmdTlmDb.LCATtlmDb import LCATtlmDb
00038 from LICOS.core.thread.guiBridges import GUIbridge
00039
00040 from LICOS.scriptEngine.ScriptEngineConnector import LicosTelemetryRouter
00041
00042 from LICOS.tools.proxy.VscProxyTools import getip
00043 from LICOS.tools.proxy.VscProxyPorts import VscProxyPorts
00044 from LICOS.scriptEngine.seTelemetryHandler import seTelemetryHandler
00045
00046
00047
00048
00049 class TelemMonitorImpl(TelemMonitor):
00050 """!\brief Telemetry monitoring GUI.
00051
00052 """
00053 def __init__(self, telemHandler=None, parent = None, name = None, fl = 0):
00054 """!\brief TelemMonitorImpl constructor.
00055
00056 \param parent The parent GUI (typically the Run Control GUI)
00057 \param name Name of the GUI
00058 \param fl Qt flags
00059 """
00060 TelemMonitor.__init__(self, None, name, fl | Qt.WGroupLeader)
00061 atexit.register(self.shutdown)
00062 self.__parent = parent
00063 self.textTelem.setMaxLogLines(9999)
00064 self.__telemConsumer = None
00065 self.__telemHandler = None
00066 self.__guiBridge = None
00067 self.__verbose = False
00068 self.__telemHandler = telemHandler
00069 self.initialize()
00070 self.connect(self.buttonClear, SIGNAL("clicked()"), self.clearAction)
00071 self.connect(self.buttonPause, SIGNAL("clicked()"), self.pauseAction)
00072 self.connect(self.buttonVerbose,SIGNAL("toggled(bool)"),self.verboseAction)
00073 self.comboTelemFilter.insertItem(" ")
00074
00075
00076 def initialize(self):
00077 self.__quit = False
00078 self.__pause = False
00079 self.__lcatTlm = LCATtlmDb()
00080 self.__telemQueue = Queue()
00081 self.__telemConsumer = TaskEngine("TelemMonitorConsumer")
00082 self.__telemConsumer.start()
00083 self.__telemConsumer.spawn(self.consumeTelemPackets)
00084 self.__guiThread = threading.currentThread()
00085 self.__guiBridge = GUIbridge(self.__guiThread)
00086 self.__telemHandler.register(self.__lcatTlm.getApids(), self.process)
00087
00088
00089 def process(self, telemetry):
00090 """!\brief Store the incoming telemetry in a queue.
00091
00092 \param telemetry Raw packet
00093 """
00094 if self.isVisible():
00095 self.__telemQueue.put(telemetry)
00096
00097 def consumeTelemPackets(self):
00098 """!\brief Main thread loop which consumes packets from the queue.
00099
00100 """
00101 while not self.__quit:
00102 if self.__telemQueue.empty() or self.__pause:
00103 time.sleep(.1)
00104 continue
00105 self.execGUImethod(self.__updateGUI)
00106
00107 def __updateGUI(self):
00108 """!\brief Retrieve a packet from the queue and display it on the GUI.
00109
00110 """
00111 while not self.__telemQueue.empty():
00112 if self.__quit or self.__pause: break
00113 telem = self.__telemQueue.get()
00114 time.sleep(.005)
00115
00116
00117
00118
00119
00120 pkt = self.__lcatTlm.decodeTelemetry(telem)
00121 if pkt.name == 'LCMMSGOUTC':
00122 self.textTelem.append(self.__lcatTlm.msgOutToText(pkt))
00123 elif pkt.name == 'CmdConfirm':
00124 statusTuple = self.__lcatTlm.msgByValue(pkt.get_payload("ITC_EXESTATUS"))
00125 if statusTuple is not None:
00126 telemDump = "CVT - %s: %s" % (statusTuple[0], statusTuple[1])
00127 else:
00128 telemDump = "CVT - Unparsable MSG: 0x%08x" % pkt.get_payload("ITC_EXESTATUS")
00129 if self.__verbose:
00130 for (name, value) in self.__lcatTlm.getPayloadData(pkt):
00131 telemDump += "\n %20s: 0x%x" % (name, value)
00132 self.textTelem.append(telemDump)
00133 else:
00134 if str(self.comboTelemFilter.currentText()) == " " or \
00135 str(self.comboTelemFilter.currentText()) == pkt.name:
00136 telemDump = "Telemetry Name: %s Apid: 0x%04x" % (pkt.name, pkt.apid)
00137 if self.__verbose:
00138 for (name, value) in self.__lcatTlm.getPayloadData(pkt):
00139 telemDump += "\n %20s: 0x%x" % (name, value)
00140 self.textTelem.append(telemDump)
00141 found = False
00142 for i in range(self.comboTelemFilter.count()):
00143 if pkt.name == str(self.comboTelemFilter.text(i)):
00144 found = True
00145 break
00146 if not found:
00147 self.comboTelemFilter.insertItem(pkt.name)
00148 self.comboTelemFilter.listBox().sort()
00149
00150 def clearAction(self):
00151 """!\brief Handle Clear button clicked action.
00152
00153 """
00154 self.textTelem.clear()
00155
00156 def pauseAction(self):
00157 """!\brief Handle the Pause/Unpause button clicked action.
00158
00159 """
00160 if self.buttonPause.text() == "Pause":
00161 self.__pause = True
00162 self.buttonPause.setText("Unpause")
00163 if self.__telemHandler is not None:
00164 self.__telemHandler.unregister(self.__lcatTlm.getApids(), self.process)
00165 else:
00166 self.__pause = False
00167 self.buttonPause.setText("Pause")
00168 if self.__telemHandler is not None:
00169 self.__telemHandler.register(self.__lcatTlm.getApids(), self.process)
00170
00171 def verboseAction(self, on):
00172 """!\brief Handle the Verbose button toggle action.
00173
00174 \param on Toggle is on
00175
00176 """
00177 if on:
00178 self.__verbose = True
00179 else:
00180 self.__verbose = False
00181
00182 def shutdown(self):
00183 """!\brief Shutdown the monitor.
00184
00185 """
00186 self.__quit = True
00187 if self.__telemConsumer is not None:
00188 self.__telemConsumer.shutdown()
00189 apids = self.__lcatTlm.getApids()
00190 if self.__telemHandler is not None and self.__telemHandler.isregistered(apids, self.process):
00191 self.__telemHandler.unregister(apids, self.process)
00192 if self.__guiBridge is not None:
00193 self.__guiBridge.shutdown()
00194
00195 def customEvent(self, e):
00196 """This method overrides the QObject base class's. There is generally
00197 no reason to call this method directly. It is called by the Qt
00198 infrastructure whenever the custom event is posted, e.g. by the following
00199 three methods of this class: createGUI, execGUImethodNR and execGUImethod.
00200 """
00201 self.__guiBridge.handleCustomEvent(e)
00202
00203 def execGUImethodNR(self, func, *args, **kwargs):
00204 """Method used for executing a GUI function from a non-GUI thread.
00205 Use this method when no (useful) response is expected or
00206 when waiting for one could cause a deadlock. Any response from the
00207 function is lost."""
00208 if self.__quit: return
00209
00210 return self.__guiBridge.execGUImethodNR(self, func, *args, **kwargs)
00211
00212 def execGUImethod(self, func, *args, **kwargs):
00213 """Method used for executing a GUI function from a non-GUI thread.
00214 Use this method when a response is expected from the function and
00215 when it is appropriate to wait for it (no deadlock arises)"""
00216 if self.__quit: return
00217
00218 return self.__guiBridge.execGUImethod(self, func, *args, **kwargs)
00219
00220 def usage():
00221 """!\brief Output command line usage.
00222
00223 """
00224 return """
00225
00226 TelemMonitorImpl Usage:
00227
00228 Mandatory options:
00229 --proxyHost Specify the proxy host
00230 --type Specify the telemetry type ("telemetry" or "diagnostic")
00231 --vscConfig Specify the VSC configuration file path
00232
00233 Example:
00234 $ TelemMonitorImpl --proxyHost localhost --type telemetry --vscConfig vsc.cfg
00235
00236 """
00237
00238 if __name__ == "__main__":
00239 log.getLogger().setLevel(log.INFO)
00240 options = Options(['proxyHost','type','vscConfig'])
00241 try:
00242 options.parse()
00243 except Exception, msg:
00244 options.usage(usage())
00245 raise Exception, msg
00246
00247 a = QApplication(sys.argv)
00248 vscConfig = ConfigParser()
00249 vscConfig.read(options.vscConfig)
00250 ports = VscProxyPorts(vscConfig.getint('vsc', 'proxyPortBase'))
00251 if options.type == "telemetry":
00252 port = ports.telemMon()
00253 else:
00254 port = ports.diagMon()
00255
00256 apidRangeList = ([0x000, 0xfff],)
00257 ip_tel = getip(options.proxyHost)
00258 tele = VSC.VscProxy.Proxy(ip_tel, port)
00259 telemHandler = seTelemetryHandler(apidRangeList)
00260 vscRouter = LicosTelemetryRouter(telemHandler)
00261 latRouter = LicosTelemetryRouter(telemHandler)
00262 if options.type == "telemetry":
00263 tele.vscTelemetry(vscRouter)
00264 tele.latTelemetry(latRouter)
00265 else:
00266 tele.vscDiagnostic(vscRouter)
00267 tele.latDiagnostic(latRouter)
00268 dm = TelemMonitorImpl(telemHandler)
00269 if options.type == "telemetry":
00270 dm.setCaption("Telemetry Monitor (standalone)")
00271 else:
00272 dm.setCaption("Diagnostic Telemetry Monitor (standalone)")
00273 a.setMainWidget(dm)
00274 dm.show()
00275 a.exec_loop()
00276