def _onGoPushButtonClicked(self): """ Go push button has been clicked. """ Logger().trace("GotoController.__onGoPushButtonClicked()") if self._view.referenceRadioButton.isChecked(): yaw = 0. pitch = 0. useOffset = True elif self._view.initialRadioButton.isChecked(): yaw = 0. pitch = 0. useOffset = False elif self._view.freeRadioButton.isChecked(): yaw = self._view.yawFovDoubleSpinBox.value() pitch = self._view.pitchFovDoubleSpinBox.value() useOffset = True Logger().debug("GotoController.__onGoPushButtonClicked(): yaw=%.1f, pitch=%.1f, useOffset=%s" % (yaw, pitch, useOffset)) self._model.head.gotoPosition(yaw, pitch, useOffset=useOffset, wait=False) dialog = AbortMessageDialog(self.tr("Goto position"), self.tr("Please wait...")) dialog.show() while self._model.head.isAxisMoving(): QtGui.QApplication.processEvents() #QtCore.QEventLoop.ExcludeUserInputEvents) if dialog.result() == QtGui.QMessageBox.Abort: self._model.head.stopAxis() self._parent.setStatusbarMessage(self.tr("Operation aborted"), 10) break time.sleep(0.01) else: self._parent.setStatusbarMessage(self.tr("Position reached"), 10) dialog.hide()
def establishConnection(self): # Move to hardware? """ Establish the connection. The SIN-11 device used to control the Pixorb axis needs to be initialised before any command can be sent to the axis controllers. """ AbstractHardwarePlugin.establishConnection(self) Logger().trace("AbstractPixOrbHardware.establishConnection()") if not AbstractPixOrbHardware.__initSIN11: try: answer = "" self._driver.empty() # Ask the SIN-11 to scan online controllers self._driver.write('&') # Add '\n' if ethernet driver? self._driver.setTimeout(SIN11_INIT_TIMEOUT) # Sin-11 takes several seconds to answer c = '' while c != '\r': c = self._driver.read(1) if c in ('#', '?'): self._driver.read(2) # Read last CRLF Logger().debug("AbstractPixOrbHardware.establishConnection(): SIN-11 '&' answer=%s" % answer) raise HardwareError("Can't init SIN-11") else: answer += c answer = answer.strip() # Remove final CRLF Logger().debug("AbstractPixOrbHardware.establishConnection(): SIN-11 '&' answer=%s" % answer) AbstractPixOrbHardware.__initSIN11 = True self._driver.setTimeout(ConfigManager().getFloat('Plugins/HARDWARE_COM_TIMEOUT')) except: self._connected = False raise
def _triggerShutter(self, delay): """ Trigger the shutter contact. Note that FOCUS_ENABLE and DUAL_ENABLE options are exclusive (done via UI) @param delay: delay to wait between on/off, in s @type delay: float """ Logger().trace("ClaussShutter._triggerShutter()") # Autofocus mode enable if self._config['FOCUS_ENABLE']: self._triggerAutoFocus() time.sleep(self._config['FOCUS_TIME']) # Shoot regular camera self._triggerOnShutter() time.sleep(delay) self._triggerOffShutter() # Dual camera mode if self._config['DUAL_ENABLE']: time.sleep(self._config['DUAL_TIME']) Logger().info("ClaussShutter._triggerShutter(): dual camera shoot") self._triggerAutoFocus() time.sleep(delay) self._triggerOffShutter() self._LastShootTime = time.time()
def init(self): """ Init the MerlinOrion hardware. Done only once per axis. """ self._driver.acquireBus() try: # Stop motor self.__sendCmd("L") # Check motor? self.__sendCmd("F") # Get firmeware version value = self.__sendCmd("e") Logger().debug("MerlinOrionHardware.init(): firmeware version=%s" % value) # Get encoder full circle value = self.__sendCmd("a") self.__encoderFullCircle = self.__encoderFullCircle_ = self.__decodeAxisValue( value) Logger().debug( "MerlinOrionHardware.init(): encoder full circle=%s" % hex(self.__encoderFullCircle)) # Get sidereal rate value = self.__sendCmd("D") Logger().debug("MerlinOrionHardware.init(): sidereal rate=%s" % hex(self.__decodeAxisValue(value))) finally: self._driver.releaseBus()
def parseDir(self, pluginDir): """ Load plugins from given dir. @param pluginDir: dir where to search plugins @type pluginDir: str """ Logger().debug("PluginsManager.register(): parsing '%s' dir..." % pluginDir) for entry in os.listdir(pluginDir): #Logger().debug("PluginsManager.register(): entry=%s" % entry) if os.path.isfile(os.path.join(pluginDir, entry)): moduleName, ext = os.path.splitext(entry) if ext == '.py' and moduleName != "__init__": file_, pathname, description = imp.find_module( moduleName, [pluginDir]) Logger().debug( "PluginsManager.register(): found '%s' module" % moduleName) try: module = imp.load_module('module', file_, pathname, description) module.register() except AttributeError: Logger().exception("PluginsManager.register()", debug=True) Logger().warning( "Plugin module '%s' does not have a register function" % pathname) file_.close()
def run(self): """ Run the sniffer. Listen to the serial line and display commands/responses. """ Logger().info("Sniffer started") try: while True: data = self.__serial.read() if not data: raise IOError("Timeout while reading on serial bus") while data[-1] != '\r': c = self.__serial.read() if not c: raise IOError("Timeout while reading on serial bus") else: data += c if data[0] == ':': cmd = data[1:-1] elif data[0] == '=': resp = data[1:-1] Logger().info("%10s -> %10s" % (cmd, resp)) else: Logger().debug("%s" % data[1:-1]) except: Logger().exception("Sniffer.run()") Logger().info("Sniffer stopped")
def _initWidgets(self): self._view.setWindowTitle("%s %s" % (self._model.name, self._model.capacity)) # Create the Gui fields self._defineGui() # Populate GUI with fields widgets = {} for tabName, tabLabel in self._tabs.iteritems(): if tabName == 'Main': widget = self._view.mainTab formLayout = self._view.formLayout else: widget = QtGui.QWidget(self._view) formLayout = QtGui.QFormLayout(widget) widget.setLayout(formLayout) self._view.tabWidget.addTab(widget, tabLabel) Logger().debug( "AbstractPluginController._initWidgets(): created '%s' tab" % tabName) for label, field in self._fields[tabName].iteritems(): widgets[label] = field['widget'] field['widget'].setParent(widget) labelWidget = QtGui.QLabel(label) labelWidget.setSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.MinimumExpanding) formLayout.addRow(labelWidget, field['widget']) Logger().debug( "AbstractPluginController._initWidgets(): added '%s' field" % label) self._view.adjustSize()
def lockupMirror(self): # @todo: implement mirror lockup command cmd = "%s %s" %(self._config['PROGRAM_PATH'], MIRROR_LOCKUP_PARAMS) Logger().debug("DslrRemoteProShutter.lockupMirror(): command '%s'..." % cmd) time.sleep(1) Logger().debug("DslrRemoteProShutter.lockupMirror(): command over") return 0
def _onAccepted(self): """ Ok button has been clicked. """ Logger().trace("NbPictsController._onAccepted()") yawNbPicts = self._view.yawNbPictsSpinBox.value() pitchNbPicts = self._view.pitchNbPictsSpinBox.value() self._model.setCornersFromNbPicts(yawNbPicts, pitchNbPicts) Logger().debug("NbPictsController._onAccepted(): nb picts set to yaw=%d, pitch=%d" % (yawNbPicts, pitchNbPicts))
def lockupMirror(self): """ @todo: implement mirror lockup command """ Logger().debug( "GphotoBracketShutter.lockupMirror(): execute command '%s'..." % self._config['MIRROR_LOCKUP_COMMAND']) time.sleep(1) Logger().debug("GphotoBracketShutter.lockupMirror(): command over") return 0
def shutdown(self): """ Cleanly terminate the model. Save values to preferences. """ Logger().trace("Shooting.shutdown()") #self.head.shutdown() Logger().warning("Shooting.shutdown(): shutdown plugins here?") self.camera.shutdown() ConfigManager().save()
def _onAccepted(self): """ Ok button has been clicked. """ Logger().trace("TotalFovController._onAccepted()") yawFov = self._view.yawFovDoubleSpinBox.value() pitchFov = self._view.pitchFovDoubleSpinBox.value() self._model.setCornersFromFov(yawFov, pitchFov) Logger().debug( "TotalFovController._onAccepted(): total fov set to yaw=%.1f, pitch=%.1f" % (yawFov, pitchFov))
def mousePressEvent(self, event): Logger().trace("ShootingScene.mousePressEvent()") picture = self.itemAt(event.scenePos()) Logger().debug("ShootingScene.mousePressEvent(): picture=%s" % picture) try: index = picture.parentItem().getIndex() Logger().debug( "ShootingScene.mousePressEvent(): picture index=%d" % index) self.pictureClicked(index) except AttributeError: Logger().exception("ShootingScene.mousePressEvent()", debug=True)
def __newPosition(self, yaw, pitch): """ Signal callback. """ #Logger().debug("PublisherHandler.__newPosition(): yaw=%.1f, pitch=%.1f" % (yaw, pitch)) try: #Logger().debug("PublisherHandler.__newPosition(): sending to %s:%d" % self.client_address) self.request.sendall("%f, %f" % (yaw, pitch)) except socket.error, msg: Logger().exception("PublisherHandler.__newPosition()") self.request.close() Spy().newPosSignal.disconnect(self.__newPosition) Logger().debug("PublisherHandler.handle(): connection from %s:%d closed" % self.client_address)
def _saveConfig(self): """ Save the plugin config. """ Logger().trace("AbstractPlugin._saveConfig()") for key, value in self._config.iteritems(): group = "%s_%s" % (self.name, self.capacity) Logger().debug("AbstractPlugin._saveConfig(): %s/%s=%s" % (group, key, value)) if isinstance(value, list): value_ = ','.join(value) value = value_ ConfigManager().set('%s/%s' % (group, key), value) ConfigManager().save()
def __onSaveLogPushButtonClicked(self): """ Save button has been clicked. """ Logger().trace("LoggerController.__onSaveLogPushButtonClicked()") dateTime = time.strftime("%Y-%m-%d_%Hh%Mm%Ss", time.localtime()) logFileFormat = "papywizard_%s.log" % dateTime logFileName = os.path.join(ConfigManager().get('Configuration/DATA_STORAGE_DIR'), logFileFormat) logText = self._view.loggerPlainTextEdit.toPlainText() logFile = file(logFileName, 'w') logFile.write(logText) logFile.close() Logger().debug("LoggerController.__onSaveLogPushButtonClicked(): log saved to '%s'" % logFileName) self._view.saveLogPushButton.setEnabled(False)
def checkPause(): """ Check if pause requested. """ if self.__pause: Logger().info("Pause shooting") self.__pauseTime = time.time() self.__paused = True self.paused() while self.__pause: time.sleep(0.1) self.__paused = False self.resumed() self.__totalPausedTime += time.time() - self.__pauseTime Logger().info("Resume shooting")
def handle(self): Logger().debug( "GigaPanBotEthernetHandler.handle(): connection request from ('%s', %d)" % self.client_address) Logger().info("New ethernet connection established") while True: try: cmd = "" while not cmd.endswith('\r'): data = self.request.recv(1) if not data: # connection lost? Logger().error("Can't read data from ethernet") break cmd += data if cmd: response = GigaPanBotCommandDispatcher().handleCmd(cmd) Logger().debug( "GigaPanBotEthernetHandler.handle(): response=%s" % repr(response)) self.request.sendall(response) else: self.request.close() Logger().debug( "GigaPanBotEthernetHandler.handle(): lost connection with ('%s', %d)" % self.client_address) Logger().info("Ethernet connection closed") break except KeyboardInterrupt: self.request.close() Logger().info("Ethernet connection closed") break except: Logger().exception("GigaPanBotEthernetHandler.handle()")
def load(self): """ Load configuration. """ #Load dist config. distConfigFile = os.path.join(path, config.CONFIG_FILE) distConfig = QtCore.QSettings(distConfigFile, QtCore.QSettings.IniFormat) if not distConfig.contains('CONFIG_VERSION'): raise IOError("Can't read configuration file (%s)" % distConfigFile) # Check if user config. exists, or need to be updated/overwritten distConfigVersion = config.VERSION.split('.') userConfig = QtCore.QSettings(config.USER_CONFIG_FILE, QtCore.QSettings.IniFormat) if not userConfig.contains('CONFIG_VERSION'): self.__install = True else: userConfigVersion = unicode( userConfig.value('CONFIG_VERSION').toString()).split('.') Logger().debug( "ConfigManager.__init__(): versions: dist=%s, user=%s" % (distConfigVersion, userConfigVersion)) # Old versioning system if len(userConfigVersion) < 2: self.__install = True # Versions differ elif distConfigVersion != userConfigVersion: self.__install = True if self.__install: Logger().debug("ConfigManager.__init__(): install user config.") shutil.copy(distConfigFile, config.USER_CONFIG_FILE) # Set config. version userConfig.setValue( 'CONFIG_VERSION', QtCore.QVariant("%s" % '.'.join(distConfigVersion))) # Write user config. userConfig.sync() else: Logger().debug( "ConfigManager.__init__(): user config. is up-to-date") self.__config = userConfig
def run(self): """ Main entry of the thread. """ threadName = "%s_%s" % (self.name, self.capacity) threading.currentThread().setName(threadName) Logger().debug("SimulationAxis.run(): start thread") self.__run = True while self.__run: # TODO: use Events # Jog command if self.__jog: if self.__time == None: self.__time = time.time() else: if self.__drive: inc = (time.time() - self.__time) * self._config['SPEED'] else: inc = ( time.time() - self.__time ) * self._config['SPEED'] * MANUAL_MANUAL_SPEED_INDEX[ self._manualSpeed] self.__time = time.time() if self.__dir == '+': self.__pos += inc elif self.__dir == '-': self.__pos -= inc #Logger().debug("SimulationAxis.run(): '%s' inc=%.1f, new __pos=%.1f" % (self.capacity, inc, self.__pos)) else: self.__time = None # Drive command. Check when stop if self.__drive: #Logger().trace("SimulationAxis.run(): '%s' driving" % self.capacity) if self.__dir == '+': if self.__pos >= self.__setpoint: self.__jog = False self.__drive = False self.__pos = self.__setpoint elif self.__dir == '-': if self.__pos <= self.__setpoint: self.__jog = False self.__drive = False self.__pos = self.__setpoint self.msleep(config.SPY_REFRESH_DELAY) Logger().debug("SimulationAxis.run(): thread terminated")
def _onAccepted(self): """ Ok button has been clicked. """ Logger().trace("AbstractPluginController._onAccepted()") for tabName in self._tabs.keys(): for label, field in self._fields[tabName].iteritems(): value = field['widget'].value() if isinstance(value, QtCore.QString): value = unicode(value) self._model._config[field['configKey']] = value Logger().debug("AbstractPluginController._onAccepted(): config=%s" % self._model._config) self._model._saveConfig() if self._model.isConnected(): self._model.configure()
def _init(self): host = ConfigManager().get('Plugins/HARDWARE_ETHERNET_HOST') port = ConfigManager().getInt('Plugins/HARDWARE_ETHERNET_PORT') Logger().debug("EthernetDriver._init(): trying to connect to %s:%d..." % (host, port)) try: #import time #time.sleep(3) self.setDeviceHostPort(host, port) self._sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self._sock.connect((self.__host, self.__port)) self._sock.settimeout(ConfigManager().getFloat('Plugins/HARDWARE_COM_TIMEOUT')) self.empty() except Exception, msg: Logger().exception("EthernetDriver._init()") raise HardwareError(msg)
def _init(self): Logger().trace("BluetoothDriver._init()") address = ConfigManager().get('Plugins/HARDWARE_BLUETOOTH_DEVICE_ADDRESS') Logger().debug("BluetoothDriver._init(): trying to connect to %s..." % address) try: self._sock = BluetoothSocket(RFCOMM) self._sock.connect((address, 1)) try: self._sock.settimeout(ConfigManager().getFloat('Plugins/HARDWARE_COM_TIMEOUT')) except NotImplementedError: Logger().warning("BluetoothDriver._init(): bluetooth stack does not implment settimeout()") except BluetoothError, error: Logger().exception("BluetoothDriver._init()") err, msg = eval(error.message) raise HardwareError(msg)
def configure(self): AbstractShutterPlugin.configure(self) # Build camera exposure compensation list if self._config['CAMERA_EXPOSURE_COMPENSATION_LIST'] == u"±5@1/3": self.__cameraExposureCompensationList = CAMERA_EXPOSURE_COMPENSATION_LIST_1_3 elif self._config['CAMERA_EXPOSURE_COMPENSATION_LIST'] == u"±5@1/2": self.__cameraExposureCompensationList = CAMERA_EXPOSURE_COMPENSATION_LIST_1_2 Logger().debug("NkRemoteShutter.configure(): camera exposure compensation table=%s" % \ self.__cameraExposureCompensationList) # Build user exposure compensation list self.__userExposureCompensationList = self._config['USER_EXPOSURE_COMPENSATION_LIST'].split(',') Logger().debug("NkRemoteShutter.configure(): user exposure compensation list=%s" % \ self.__userExposureCompensationList)
def _alternateDrive(self, pos): """ Alternate drive. This method implements an external closed-loop regulation. It is faster for angles < 6-7°, because in this case, the head does not accelerate to full speed, but rather stays at very low speed. @param pos: position to reach, in ° @type pos: float """ Logger().trace("MerlinOrionAxis._alternateDrive()") # Compute initial direction # BUG!!! Arm side is not taken in account!!! if pos > self.__currentPos: dir_ = '+' else: dir_ = '-' self._hardware.startJog(dir_, MANUAL_SPEED_TABLE['alternate']) # Check when to stop #while ((dir_ == '-' and self.__currentPos - pos > self._config['INERTIA_ANGLE']) or \ #(dir_ == '+' and pos - self.__currentPos > self._config['INERTIA_ANGLE'])) and \ #self.__driveEvent.isSet(): while abs(self.__currentPos - pos) > self._config['INERTIA_ANGLE'] and self.__driveEvent.isSet(): time.sleep(config.SPY_REFRESH_DELAY / 1000.) self._hardware.stop()
def deactivate(self): Logger().trace("MerlinOrionPlugin.deactivate()") # Stop the thread self._stopThread() AbstractAxisPlugin.deactivate(self)
def ls(self, dir_=None, recurse=False): """ List dir. @param dir_: directory to list @type dir_: str @param recurse: if True, list dir recursively @type recurse: bool """ if dir_ is None: self.__sendCmd("ls") dir_ = "" else: self.__sendCmd("ls %s" % dir_) if len(dir_) > 0 and dir_[-1] != '/': dir_ += '/' # read directory entries line = self.__popen.stdout.readline().rstrip() if line.startswith(PREFIX_ERROR): Logger().error("GphotoShell.ls(): %s recurse=%s gphoto2=\"%s\"" % (dir_, recurse, line)) self.__handleError(line) return None, None childDirs = [] numDirs = int(line) for i in range(numDirs): if recurse: childDirs.append(dir_ + self.__popen.stdout.readline().rstrip() + '/') else: childDirs.append(self.__popen.stdout.readline().rstrip() + '/') # read file entries childFiles = [] line = self.__popen.stdout.readline().rstrip() numFiles = int(line) for i in range(numFiles): if recurse: childFiles.append(dir_ + self.__popen.stdout.readline().rstrip()) else: childFiles.append(self.__popen.stdout.readline().rstrip()) if recurse: dirs = [] files = childFiles[:] for childDir in childDirs: dirs.append(childDir) grandChildDirs, grandChildFiles = self.ls(childDir, recurse) # ??? if grandChildDirs is not None and len(grandChildDirs) > 0: dirs.extend([d for d in grandChildDirs ]) # or just dirs.extend(grandChildDirs) if grandChildFiles is not None and len(grandChildFiles) > 0: files.extend([f for f in grandChildFiles ]) # or just files.extend(grandChildFiles) return dirs, files else: return childDirs, childFiles
def getConfig(self, config): """ Get a specific config from camera. @param config: path of the config to get @type config: str """ self.__sendCmd("get-config %s\n" % config) props = {} choices = [] while True: line = self.__popen.stdout.readline().rstrip() if line.startswith(PREFIX_PROMPT): break elif line.startswith(PREFIX_ERROR): Logger().error( "GphotoShell.getConfig(): config=%s gphoto2=\"%s\"" % (config, line)) self.__handleError(line) return None, None else: key, sep, value = line.partition(': ') # 'Key: Value' form if key == "Choice": if props['Type'] == 'MENU' or props['Type'] == 'RADIO': idx, sep, value = value.partition(' ') choices.append(value) else: props[key] = value return props, choices
def __init__(self): """ Init object. """ super(AbstractData, self).__init__() date, time_ = self._getDateTime().split('_') #date = time.strftime("%Y-%m-%d", time.localtime()) #time_ = time.strftime("%Hh%Mm%Ss", time.localtime()) mode = self._getMode() self._dataFileFormatDict = { 'date': date, 'time': time_, 'date_time': "%s_%s" % (date, time_), 'mode': mode } # Create xml tree Logger().debug("Data.__init__(): create xml tree") self.__impl = xml.dom.minidom.getDOMImplementation() self._doc = self.__impl.createDocument(None, "papywizard", None) self._rootNode = self._doc.documentElement self._rootNode.setAttribute("version", config.VERSION_XML) # Create 'header' node self._headerNode = self._doc.createElement('header') self._rootNode.appendChild(self._headerNode) # Create 'shoot' node self._shootNode = self._doc.createElement('shoot') self._rootNode.appendChild(self._shootNode) self._pictId = 1
def addPicture(self, bracket, yaw, pitch, roll): """ Add a new picture node to shoot node. @param bracket: num of the pict (bracketing) @type bracket: int @param yaw: yaw position @type yaw: float @param pitch: pitch position @type pitch: float @param roll: roll value @type roll: float """ Logger().debug( "Data.addPicture(): bracket=%d, yaw=%.1f, pitch=%.1f, roll=%.1f" % (bracket, yaw, pitch, roll)) node = self._addNode(self._shootNode, 'pict', id="%d" % self._pictId, bracket="%d" % bracket) self._pictId += 1 dateTime = self._getDateTime() self._addNode(node, 'time', dateTime) self._addNode(node, 'position', yaw="%.1f" % yaw, pitch="%.1f" % pitch, roll="%.1f" % roll) self._headerShootingEndTime.firstChild.data = dateTime # Serialize xml file self._serialize()