Esempio n. 1
0
class LaserControlMain(QtGui.QMainWindow):
    act_stell_pos = QtCore.pyqtSignal(str, str)

    def __init__(self, parent=None):
        super(LaserControlMain, self).__init__(parent)
        self.confMode = False
        self.nRef = 0
        self.device = None
        (self._ra, self._dec) = ("0h0m0s", "0º0'0''")

        self.ui = Ui_LaserControl()
        self.ui.setupUi(self)
        self.ui.Reconfigure.setVisible(False)

        regex = QtCore.QRegExp(
            "%s" %
            (_fromUtf8("^-?[0-9]{1,3}(º|ᵒ)[0-9]{1,3}'[0-9]{1,3}([']{2}|\")$")))
        self.Valid = QtGui.QRegExpValidator(regex, self)
        self.ui.posHorizontal.setValidator(self.Valid)
        self.ui.posVertical.setValidator(self.Valid)
        self.ui.posHorizontal.setText("%s" % (_fromUtf8("0º0'0''")))
        self.ui.posVertical.setText("%s" % (_fromUtf8("0º0'0''")))
        self.ui.tabWidget.setCurrentIndex(1)
        self.ui.tabWidget.setTabEnabled(1, False)

        self.pos = ('0.0000', '0.0000')
        self._prev_pos = ("0º0'0''", "0º0'0''")

        #Starts server
        self.Server = Telescope_Server(pos_signal=self.act_stell_pos)
        self.Server.daemon = True
        self.Server.start()

        self.setSignals()
        self.setShortcuts()

        #At the beginning, configuration mode is On
        self.ui.confMode.setChecked(True)

    ## Connects the UI signals
    #
    def setSignals(self):
        #Movements
        QtCore.QObject.connect(self.ui.upButton, QtCore.SIGNAL("pressed()"),
                               self.upPressed)
        QtCore.QObject.connect(self.ui.downButton, QtCore.SIGNAL("pressed()"),
                               self.downPressed)
        QtCore.QObject.connect(self.ui.rightButton, QtCore.SIGNAL("pressed()"),
                               self.rightPressed)
        QtCore.QObject.connect(self.ui.leftButton, QtCore.SIGNAL("pressed()"),
                               self.leftPressed)
        QtCore.QObject.connect(self.ui.upButton, QtCore.SIGNAL("released()"),
                               self.arrow_released)
        QtCore.QObject.connect(self.ui.downButton, QtCore.SIGNAL("released()"),
                               self.arrow_released)
        QtCore.QObject.connect(self.ui.rightButton,
                               QtCore.SIGNAL("released()"),
                               self.arrow_released)
        QtCore.QObject.connect(self.ui.leftButton, QtCore.SIGNAL("released()"),
                               self.arrow_released)

        #Position
        QtCore.QObject.connect(self.ui.posVertical,
                               QtCore.SIGNAL("editingFinished()"),
                               self.posChanged)
        QtCore.QObject.connect(self.ui.posHorizontal,
                               QtCore.SIGNAL("editingFinished()"),
                               self.posChanged)

        #Laser
        QtCore.QObject.connect(self.ui.laserOn, QtCore.SIGNAL("toggled(bool)"),
                               self.laserToggled)

        #Options
        QtCore.QObject.connect(self.ui.confMode,
                               QtCore.SIGNAL("toggled(bool)"),
                               self.confModeChanged)
        QtCore.QObject.connect(self.ui.trackMode,
                               QtCore.SIGNAL("toggled(bool)"),
                               self.trackModeChanged)

        #Device connection
        self.refreshSerialPorts()
        QtCore.QObject.connect(self.ui.action_Refresh,
                               QtCore.SIGNAL("triggered(bool)"),
                               self.refreshSerialPorts)
        QtCore.QObject.connect(self.ui.action_Desconectar,
                               QtCore.SIGNAL("triggered(bool)"),
                               self.closeDevice)
        #El dispositivo debe recalcular el número de pasos por vuelta en cada eje
        QtCore.QObject.connect(self.ui.action_Recalibrar,
                               QtCore.SIGNAL("triggered(bool)"),
                               self.initDevice)

        #Stellarium..
        self.Server.stell_pos_recv.connect(self.stellariumRecv)

    ## Show available serial ports and set connection signals
    #
    def refreshSerialPorts(self):
        # Clear menu..
        self.ui.menu_Connect.clear()
        self.ui.menu_Connect.addAction(self.ui.action_Refresh)
        self.ui.menu_Connect.addSeparator()

        port_list = get_avalilable_ports()
        for device_path in port_list:
            act = QtGui.QAction(device_path, self)
            act.triggered.connect(
                functools.partial(self.connectDevice, device_path))
            self.ui.menu_Connect.addAction(act)

    ## Shortcuts for the device movements
    #
    def setShortcuts(self):
        self.ui.leftB_shortCut = QtGui.QShortcut(
            QtGui.QKeySequence("Shift+Left"), self,
            self.ui.leftButton.animateClick)
        self.ui.rightB_shortCut = QtGui.QShortcut(
            QtGui.QKeySequence("Shift+Right"), self,
            self.ui.rightButton.animateClick)
        self.ui.upB_shortCut = QtGui.QShortcut(QtGui.QKeySequence("Shift+Up"),
                                               self,
                                               self.ui.upButton.animateClick)
        self.ui.downB_shortCut = QtGui.QShortcut(
            QtGui.QKeySequence("Shift+Down"), self,
            self.ui.downButton.animateClick)

    ## Handles the coordinate reception from Stellarium
    #
    #  Receives the coordinates from Stellarium by the Telescope_Server instance.
    #  If the device is connected, sends the coordinates to it, as either the configuration or movement values.
    #
    #  Also manages the UI status along the configuration process.
    #
    # \param ra Right ascension
    # \param dec Declination
    # \param mtime Timestamp
    def stellariumRecv(self, ra, dec, mtime):
        ra = float(ra)
        dec = float(dec)
        mtime = float(mtime)

        mtime = 1.46037891509e+15

        logging.debug("%s" % mtime)
        logging.debug("%s" % coords.toJ2000(ra, dec, mtime))
        (sra, sdec, stime) = coords.eCoords2str(ra, dec, mtime)
        # print stime
        (self._ra, self._dec) = (sra, sdec)

        if self.device != None:
            logging.debug("Sending to the device: '%s','%s','%s'" %
                          (sra, sdec, stime))
            try:
                if self.ui.Reconfigure.isChecked():
                    if self.ui.redef_1:
                        self.ui.redef_1.setChecked(False)
                        redef = 1
                    elif self.ui.redef_2:
                        self.ui.redef_2.setChecked(False)
                        redef = 2
                    else:
                        self.ui.redef_3.setChecked(False)
                        redef = 3
                    self.ui.Reconfigure.setChecked(False)
                    self.device.setRef(redef, sra, sdec, stime)
                elif not self.confMode:
                    self.device.goto(sra, sdec, stime)
                else:
                    self.nRef = self.nRef + 1
                    self.ui.text_status.setText("References: %d/2" % self.nRef)
                    self.device.setRef(self.nRef, sra, sdec, stime)
                    if self.nRef == 2:
                        self.setConfigDone()
                        self.nRef = 0
            except:
                logging.debug("Device not found..")
                e = sys.exc_info()[1]
                print("Error: %s" % e)

    ## Up key pushed
    #
    #  Starts the upward movement of the device
    def upPressed(self):
        if self.device != None:
            self.device.movy('1')

    ## Down key pushed
    #
    #  Starts the downward movement
    def downPressed(self):
        if self.device != None:
            self.device.movy('0')

    ## Right key pushed
    #
    #  Starts the clockwise movement
    def rightPressed(self):
        if self.device != None:
            self.device.movx('1')

    ## Left key pushed
    #
    #  Starts the counter clockwise movement
    def leftPressed(self):
        if self.device != None:
            self.device.movx('0')

    ## Up/Down/Right/Left key released..
    #
    #  Stops any movement
    def arrow_released(self):
        if self.device != None:
            self.device.stop()

    ## Handles the changes on the coordinates text boxes
    #
    #  If the device is configured, sends the new coordinates to it
    def posChanged(self):
        logging.debug(
            "(%s, %s)" %
            (self.ui.posHorizontal.text(), self.ui.posVertical.text()))
        x = _toUtf8(self.ui.posHorizontal.text())
        y = _toUtf8(self.ui.posVertical.text())
        if self.device != None and (self._prev_pos[0] != x
                                    or self._prev_pos[1] != y):
            logging.debug("Sending (%s, %s) to device" % (x, y))
            self.device.move(x, y)
        self._prev_pos = (x, y)

    ## Handles the changes on "configuration mode" check box
    #
    def confModeChanged(self):
        if self.ui.confMode.isChecked():
            self.confMode = True
            self.nRef = 0
            logging.debug("Conf mode ON")
        else:
            self.setConfigDone()
            self.confMode = False
            logging.debug("Conf mode Off")

    ## Handles the end of the device configuration process
    #
    def setConfigDone(self):
        self.ui.confMode.setChecked(False)
        self.ui.tabWidget.setTabEnabled(1, True)
        self.ui.tabWidget.setCurrentIndex(1)
        self.ui.text_status.setText("References: 2/2")

        self.ui.confMode.setVisible(False)
        self.ui.textEdit.setVisible(False)

        self.ui.Reconfigure.setVisible(True)

    ## Handles changes on tracking check box
    #
    #  If check is On, starts the tracking mode on the device
    def trackModeChanged(self):
        if self.ui.trackMode.isChecked():
            self.track = RepeatTimer(5.0, self.tracking)
            self.track.start()
            logging.debug("Track mode ON")
        else:
            self.track.cancel()
            logging.debug("Track mode Off")

    ## Starts the device connection
    #
    #  In case of error, shows the message on UI
    # \param device_path USB Serial Device path
    def connectDevice(self, device_path):
        self.ui.action_Desconectar.setEnabled(True)
        self.ui.action_Recalibrar.setEnabled(True)
        logging.info("Connecting to device via '%s'" % device_path)
        try:
            if self.device == None:
                self.device = LaserDev(usb_serial=device_path)
                self.device.init_received.connect(self.init_received)
                self.device.pos_received.connect(self.pos_received)
                self.device.pos_e_received.connect(self.pos_e_received)
                self.device.start()
        except:
            logging.info("Device not found")
            QtGui.QMessageBox.warning(self, 'Warning', "Device not found")
            self.ui.action_Desconectar.setEnabled(False)
            self.ui.action_Recalibrar.setEnabled(False)
            self.device = None

    ## Initialize device
    #
    #  The device will calculate the steps per revolution
    def initDevice(self):
        logging.info("Initializing device..")
        try:
            if self.device != None:
                self.device.init()
        except:
            logging.info("Error initializing device.")

    ## Receives the end of initialization signal from the device
    #
    #  That signal indicates that the device is successfully initialized
    def init_received(self):
        logging.debug("Init received")
        self.pos = ('0.0000', '0.0000')
        self.ui.posHorizontal.setText("%s" % _fromUtf8("0º0'0''"))
        self.ui.posVertical.setText("%s" % _fromUtf8("0º0'0''"))

    ## Receives the position updated signal from the device
    #
    #  The parameters are the horizontal coordinates which the device points to
    def pos_received(self, x, y):
        logging.debug("%s,%s" % (x, y))
        self.pos = (x, y)
        self.ui.posHorizontal.setText("%s" % _fromUtf8(
            coords.deg_2_degStr(360.0 - coords.radStr_2_deg(self.pos[0]))))
        self.ui.posVertical.setText(
            "%s" % _fromUtf8(coords.radStr_2_degStr(self.pos[1])))

    ## Receives the position updated signal from the device
    #
    #  The parameters are the equatorial coordinates which the device points to
    def pos_e_received(self, x, y):
        logging.debug("%s,%s" % (x, y))
        self.act_stell_pos.emit(x, y)

    ## Tracking mode
    #
    #  Updates periodically the device position by sending the equatorial coordinates and time
    def tracking(self):
        logging.debug(
            "('%s', '%s', '%s')" %
            (self._ra, self._dec, strftime("%Hh%Mm%Ss", localtime())))
        if self.device != None and self._ra != '0h0m0s':
            self.device.goto(self._ra, self._dec,
                             strftime("%Hh%Mm%Ss", localtime()))

    ## Laser toggle..
    #
    def laserToggled(self):
        if self.ui.laserOn.isChecked():
            if self.device != None:
                self.device.laserOn()
            logging.debug("Laser ON")
        else:
            if self.device != None:
                self.device.laserOff()
            logging.debug("Laser Off")

    ## Close the device connection
    #
    def closeDevice(self):
        self.ui.action_Conectar.setEnabled(True)
        self.ui.action_Desconectar.setEnabled(False)
        self.ui.action_Recalibrar.setEnabled(False)
        logging.info("Disconnecting device..")
        try:
            if self.device != None:
                self.device.close()
                self.device = None
        except:
            self.device = None

    ## Exit..
    #
    def closeEvent(self, event):
        logging.debug("Bye!")
        try:
            self.Server.close_socket()
            self.track.cancel()
            event.accept()
        except:
            event.accept()
class LaserControlMain(QtGui.QMainWindow):
	## @var act_stell_pos
	#  Signal to communications with the Telescope_Server instance
	#  It emits when we want to send to Stellarium the equatorial coordinates
	act_stell_pos = QtCore.pyqtSignal(str, str)

	## Class constructor
	#
	#  Starts the UI and the Telescope_Server instance
	#
	#  \param parent (optional) Parent object. By default is None
	def __init__(self, parent=None):
		super(LaserControlMain, self).__init__(parent)
		self.confMode = False
		self.nRef = 0
		self.device = None
		(self._ra, self._dec) = ("0h0m0s", "0º0'0''")

		self.ui = Ui_LaserControl()
		self.ui.setupUi(self)
		self.ui.Reconfigure.setVisible(False)

		regex=QtCore.QRegExp("%s" % (_fromUtf8("^-?[0-9]{1,3}(º|ᵒ)[0-9]{1,3}'[0-9]{1,3}([']{2}|\")$")))
		self.Valid=QtGui.QRegExpValidator(regex, self)
		self.ui.posHorizontal.setValidator(self.Valid)
		self.ui.posVertical.setValidator(self.Valid)
		self.ui.posHorizontal.setText("%s" % (_fromUtf8("0º0'0''")))
		self.ui.posVertical.setText("%s" % (_fromUtf8("0º0'0''")))
		self.ui.tabWidget.setCurrentIndex(1)
		self.ui.tabWidget.setTabEnabled(1, False)

		self.pos = ('0.0000', '0.0000')
		self._prev_pos = ("0º0'0''", "0º0'0''")
		
		#Starts server
		self.Server = Telescope_Server(pos_signal=self.act_stell_pos)
		self.Server.daemon = True
		self.Server.start()
		
		self.setSignals()
		self.setShortcuts()
		
		#At the beginning, configuration mode is On
		self.ui.confMode.setChecked(True)
		
	## Connects the UI signals
	#
	def setSignals(self):
		#Movements
		QtCore.QObject.connect(self.ui.upButton, QtCore.SIGNAL("pressed()"), self.upPressed)
		QtCore.QObject.connect(self.ui.downButton, QtCore.SIGNAL("pressed()"), self.downPressed)
		QtCore.QObject.connect(self.ui.rightButton, QtCore.SIGNAL("pressed()"), self.rightPressed)
		QtCore.QObject.connect(self.ui.leftButton, QtCore.SIGNAL("pressed()"), self.leftPressed)
		QtCore.QObject.connect(self.ui.upButton, QtCore.SIGNAL("released()"), self.arrow_released)
		QtCore.QObject.connect(self.ui.downButton, QtCore.SIGNAL("released()"), self.arrow_released)
		QtCore.QObject.connect(self.ui.rightButton, QtCore.SIGNAL("released()"), self.arrow_released)
		QtCore.QObject.connect(self.ui.leftButton, QtCore.SIGNAL("released()"), self.arrow_released)
		
		#Position
		QtCore.QObject.connect(self.ui.posVertical, QtCore.SIGNAL("editingFinished()"), self.posChanged)
		QtCore.QObject.connect(self.ui.posHorizontal, QtCore.SIGNAL("editingFinished()"), self.posChanged)
		
		#Laser
		QtCore.QObject.connect(self.ui.laserOn, QtCore.SIGNAL("toggled(bool)"), self.laserToggled)
		
		#Options
		QtCore.QObject.connect(self.ui.confMode, QtCore.SIGNAL("toggled(bool)"), self.confModeChanged)
		QtCore.QObject.connect(self.ui.trackMode, QtCore.SIGNAL("toggled(bool)"), self.trackModeChanged)
		
		#Device connection
		QtCore.QObject.connect(self.ui.action_Conectar, QtCore.SIGNAL("triggered(bool)"), self.connectDevice)
		QtCore.QObject.connect(self.ui.action_Desconectar, QtCore.SIGNAL("triggered(bool)"), self.closeDevice)
		#El dispositivo debe recalcular el número de pasos por vuelta en cada eje
		QtCore.QObject.connect(self.ui.action_Recalibrar, QtCore.SIGNAL("triggered(bool)"), self.initDevice)
		
		#Stellarium..
		self.Server.stell_pos_recv.connect(self.stellariumRecv)
		
	## Shortcuts for the device movements
	#
	def setShortcuts(self):
		self.ui.leftB_shortCut = QtGui.QShortcut(QtGui.QKeySequence("Shift+Left"), self, self.ui.leftButton.animateClick)
		self.ui.rightB_shortCut = QtGui.QShortcut(QtGui.QKeySequence("Shift+Right"), self, self.ui.rightButton.animateClick)
		self.ui.upB_shortCut = QtGui.QShortcut(QtGui.QKeySequence("Shift+Up"), self, self.ui.upButton.animateClick)
		self.ui.downB_shortCut = QtGui.QShortcut(QtGui.QKeySequence("Shift+Down"), self, self.ui.downButton.animateClick)
		
	## Handles the coordinate reception from Stellarium
	#
	#  Receives the coordinates from Stellarium by the Telescope_Server instance.
	#  If the device is connected, sends the coordinates to it, as either the configuration or movement values.
	#  
	#  Also manages the UI status along the configuration process.
	#
	# \param ra Right ascension
	# \param dec Declination
	# \param mtime Timestamp
	def stellariumRecv(self, ra, dec, mtime):
		ra = float(ra)
		dec = float(dec)
		mtime = float(mtime)
		logging.debug("%s" % coords.toJ2000(ra, dec, mtime))
		(sra, sdec, stime) = coords.eCoords2str(ra, dec, mtime)
		(self._ra, self._dec) = (sra, sdec)

		if self.device != None:
			logging.debug("Sending to the device: '%s','%s','%s'" % (sra, sdec, stime))
			try:
				if self.ui.Reconfigure.isChecked():
					if self.ui.redef_1:
						self.ui.redef_1.setChecked(False)
						redef = 1
					elif self.ui.redef_2:
						self.ui.redef_2.setChecked(False)
						redef = 2
					else:
						self.ui.redef_3.setChecked(False)
						redef = 3
					self.ui.Reconfigure.setChecked(False)
					self.device.setRef(redef, sra, sdec, stime)
				elif not self.confMode:
					self.device.goto(sra, sdec, stime)
				else:
					self.nRef = self.nRef + 1
					self.ui.text_status.setText("References: %d/2" % self.nRef)
					self.device.setRef(self.nRef, sra, sdec, stime)
					if self.nRef == 2:
						self.setConfigDone()
						self.nRef = 0
			except:
				logging.debug("Device not found..")
				e = sys.exc_info()[1]
				print("Error: %s" % e)
	
	## Up key pushed
	#
	#  Starts the upward movement of the device
	def upPressed(self):
		if self.device != None:
			self.device.movy('1')
	
	## Down key pushed
	#
	#  Starts the downward movement
	def downPressed(self):
		if self.device != None:
			self.device.movy('0')
	
	## Right key pushed
	#
	#  Starts the clockwise movement
	def rightPressed(self):
		if self.device != None:
			self.device.movx('1')
	
	## Left key pushed
	#
	#  Starts the counter clockwise movement
	def leftPressed(self):
		if self.device != None:
			self.device.movx('0')
	
	## Up/Down/Right/Left key released..
	#
	#  Stops any movement
	def arrow_released(self):
		if self.device != None:
			self.device.stop()
	
	## Handles the changes on the coordinates text boxes
	#
	#  If the device is configured, sends the new coordinates to it
	def posChanged(self):
		logging.debug("(%s, %s)" % (self.ui.posHorizontal.text(), self.ui.posVertical.text()))
		x = _toUtf8(self.ui.posHorizontal.text())
		y = _toUtf8(self.ui.posVertical.text())
		if self.device != None and (self._prev_pos[0]!=x or self._prev_pos[1]!=y):
			logging.debug("Sending (%s, %s) to device" % (x, y))
			self.device.move(x,y)
		self._prev_pos = (x, y)
		
	## Handles the changes on "configuration mode" check box
	#
	def confModeChanged(self):
		if self.ui.confMode.isChecked():
			self.confMode = True
			self.nRef = 0
			logging.debug("Conf mode ON")
		else:
			self.setConfigDone()
			self.confMode = False
			logging.debug("Conf mode Off")
	
	## Handles the end of the device configuration process
	#
	def setConfigDone(self):
		self.ui.confMode.setChecked(False)
		self.ui.tabWidget.setTabEnabled(1, True)
		self.ui.tabWidget.setCurrentIndex(1)
		self.ui.text_status.setText("References: 2/2")
		
		self.ui.confMode.setVisible(False)
		self.ui.textEdit.setVisible(False)
		
		self.ui.Reconfigure.setVisible(True)
		
			
	## Handles changes on tracking check box
	# 
	#  If check is On, starts the tracking mode on the device
	def trackModeChanged(self):
		if self.ui.trackMode.isChecked():
			self.track = RepeatTimer(5.0, self.tracking)
			self.track.start()
			logging.debug("Track mode ON")
		else:
			self.track.cancel()
			logging.debug("Track mode Off")
		
	## Starts the device connection
	#
	#  In case of error, shows the message on UI
	def connectDevice(self):
		self.ui.action_Conectar.setEnabled(False)
		self.ui.action_Desconectar.setEnabled(True)
		self.ui.action_Recalibrar.setEnabled(True)
		logging.info("Connecting device")
		try:
			if self.device == None:
				self.device = LaserDev(usb_serial='/dev/ttyUSB0')#TODO.. make this configurable..
				self.device.init_received.connect(self.init_received)
				self.device.pos_received.connect(self.pos_received)
				self.device.pos_e_received.connect(self.pos_e_received)
				self.device.start()
		except:
			logging.info("Device not found")
			QtGui.QMessageBox.warning(self, 'Warning', "Device not found")
			self.ui.action_Conectar.setEnabled(True)
			self.ui.action_Desconectar.setEnabled(False)
			self.ui.action_Recalibrar.setEnabled(False)
			self.device = None
			
	## Initialize device
	#
	#  The device will calculate the steps per revolution
	def initDevice(self):
		logging.info("Initializing device..")
		try:
			if self.device != None:
				self.device.init()
		except:
			logging.info("Error initializing device.")
	
	## Receives the end of initialization signal from the device
	#
	#  That signal indicates that the device is successfully initialized
	def init_received(self):
		logging.debug("Init received")
		self.pos = ('0.0000', '0.0000')
		self.ui.posHorizontal.setText("%s" % _fromUtf8("0º0'0''"))
		self.ui.posVertical.setText("%s" % _fromUtf8("0º0'0''"))
		
	## Receives the position updated signal from the device
	#
	#  The parameters are the horizontal coordinates which the device points to
	def pos_received(self, x, y):
		logging.debug("%s,%s" % (x, y))
		self.pos = (x, y)
		self.ui.posHorizontal.setText("%s" % _fromUtf8(coords.deg_2_degStr(360.0 - coords.radStr_2_deg(self.pos[0]))))
		self.ui.posVertical.setText("%s" % _fromUtf8(coords.radStr_2_degStr(self.pos[1])))
		
	## Receives the position updated signal from the device
	#
	#  The parameters are the equatorial coordinates which the device points to
	def pos_e_received(self, x, y):
		logging.debug("%s,%s" % (x, y))
		self.act_stell_pos.emit(x, y)
				
	## Tracking mode
	#
	#  Updates periodically the device position by sending the equatorial coordinates and time
	def tracking(self):
		logging.debug("('%s', '%s', '%s')" % (self._ra, self._dec, strftime("%Hh%Mm%Ss", localtime())))
		if self.device != None and self._ra != '0h0m0s':
			self.device.goto( self._ra, self._dec, strftime("%Hh%Mm%Ss", localtime()) )
	
	## Laser toggle..
	#
	def laserToggled(self):
		if self.ui.laserOn.isChecked():
			if self.device != None:
				self.device.laserOn()
			logging.debug("Laser ON")
		else:
			if self.device != None:
				self.device.laserOff()
			logging.debug("Laser Off")
		
	## Close the device connection
	#
	def closeDevice(self):
		self.ui.action_Conectar.setEnabled(True)
		self.ui.action_Desconectar.setEnabled(False)
		self.ui.action_Recalibrar.setEnabled(False)
		logging.info("Disconnecting device..")
		try:
			if self.device != None:
				self.device.close()
				self.device = None
		except:
			self.device = None

	## Exit..
	#
	def closeEvent(self, event):
		logging.debug("Bye!")
		try:
			self.Server.close_socket()
			self.track.cancel()
			event.accept()
		except:
			event.accept()
Esempio n. 3
0
class LEDShow(object):
    """ LEDShow manages the ultrasonic sensor readings and the LED animation sequence. """

    # LED strip configuration:
    LED_COUNT = 1536  # Number of LED pixels.
    LED_PIN = 18  # GPIO pin connected to the pixels (must support PWM!).
    LED_FREQ_HZ = 800000  # LED signal frequency in hertz (usually 800khz)
    LED_DMA = 5  # DMA channel to use for generating signal (try 5)
    LED_BRIGHTNESS = 100  # Set to 0 for darkest and 255 for brightest
    LED_INVERT = False  # True to invert the signal (when using NPN transistor level shift)

    #Sensor configuration
    ANIMATION_DURATION = 300  # The collective inactive (non animating) time from animation start to finish(trigger next animation)
    MAX_DISTANCE = 210.0  # The maximum distance accepted from the ultrasonic sensor (cm)
    MIN_DISTANCE = 80.0  # The minimum distance accepted from the ultrasonic sensor (cm)
    RANDOMIZE = True  # Next animation is selected randomly

    def __init__(self):
        """ Initialize sensor readings and led animations """

        #initialize ping sensor and register callback
        self.sensor = PingSensor(self.setDistance)

        #initialize neopixel object
        self.strip = Adafruit_NeoPixel(LEDShow.LED_COUNT, LEDShow.LED_PIN,
                                       LEDShow.LED_FREQ_HZ, LEDShow.LED_DMA,
                                       LEDShow.LED_INVERT,
                                       LEDShow.LED_BRIGHTNESS)
        self.strip.begin()

        #grid conversion
        self.grid = utils.stripToGrid(LEDShow.LED_COUNT, 8)

        ###SHUFFLE THESE!!!
        #list of animations to cycle through
        self.animations = [
            AnimationWipe(self),
            AnimationPulse(self),
            AnimationLeap(self),
            AnimationMirror(self),
            AnimationDuel(self),
            AnimationWave(self),
            AnimationSquares(self)
        ]

        #initialized animation index
        self.animationIndex = -1

        #animation duration timer
        if len(self.animations) > 1:
            self.timer = RepeatTimer()
            self.timer.start(LEDShow.ANIMATION_DURATION, self.nextAnimation)

        #initialize animations
        self.currentAnimation = None
        self.nextAnimation()
        self.startPingInterval = time.time()

        #ping loop
        try:
            GPIO.setmode(GPIO.BOARD)
            self.sensor.ping()

            #emit ping every interval defined by the animation
            while (True):
                self.endPingInterval = time.time() - self.startPingInterval
                if (self.endPingInterval >= self.pingInterval):
                    self.sensor.ping()

        #cleanup
        finally:
            GPIO.cleanup()
            self.clearPixels()

    def setDistance(self, d):
        """ The sensor callback evaluates the reported distance then sends it to the current
            animation when a change is detected. Also queues the next animation when the 
            *ANIMATION_DURATION* has expired.
        """

        #increment animation time
        self.startPingInterval = time.time()

        #only update animation when new distance is less than MAX_DISTANCE
        #and current animation is valid
        distance = int(d)
        if not self.currentAnimation == None:
            self.distance = distance
            self.currentAnimation.run()

    def nextAnimation(self):
        """ Queues the next animation in the list and updates the sensor interval.
            If the current animation is at the end of the list, the sequence starts over.
        """
        #next index
        if LEDShow.RANDOMIZE:
            index = self.animationIndex
            while index == self.animationIndex:
                index = randint(0, len(self.animations) - 1)
            self.animationIndex = index
        else:
            self.animationIndex = 0 if (self.animationIndex
                                        == len(self.animations) -
                                        1) else (self.animationIndex + 1)

        if not self.currentAnimation == None:
            self.currentAnimation.stop()

        self.currentAnimation = self.animations[self.animationIndex]
        print(self.currentAnimation)

        self.distance = 0
        self.pingInterval = self.currentAnimation.pingInterval()

    def clearPixels(self):
        """ Clears all pixels in the strip """
        for i in range(self.numPixels()):
            self.setPixelColor(i, 0, 0, 0)
        self.show()

    def setPixelColor(self, pixel, red, green, blue):
        """ Set specified LED to RGB value """
        if pixel < LEDShow.LED_COUNT:
            red = utils.clamp(red, 0, 255)
            green = utils.clamp(green, 0, 255)
            blue = utils.clamp(blue, 0, 255)
            self.strip.setPixelColorRGB(pixel, green, red, blue)  #GRB to RGB

    def getPixelColor(self, pixel):
        """ Return RGB value of specified pixel """
        return utils.intToRGB(self.strip.getPixelColor(pixel))

    def setPixelColorXY(self, x, y, red, green, blue):
        """ Set color of pixel at specified grid location """
        if x < len(self.grid) and y < len(self.grid[0]):
            self.setPixelColor(self.grid[x][y], red, green, blue)

    def getPixelColorXY(self, x, y):
        return self.getPixelColor(self.grid[x][y])

    def setRowColor(self, row, red, green, blue):
        """ Set entire a row to the provided color """
        if row < len(self.grid[0]):
            for x in range(len(self.grid)):
                self.setPixelColorXY(x, row, red, green, blue)

    def getRowCount(self):
        return len(self.grid[0])

    def getColumnCount(self):
        return len(self.grid)

    def setColumnColor(self, column, red, green, blue):
        """ Set entire column to the provided color """
        if column < len(self.grid):
            for y in range(len(self.grid[0])):
                self.setPixelColorXY(column, y, red, green, blue)

    def setGridColor(self, red, green, blue):
        for i in range(self.numPixels()):
            self.setPixelColor(i, red, green, blue)

    def drawSquare(self, x, y, width, height, red, green, blue):
        for w in range(width):
            for h in range(height):
                self.setPixelColorXY(x + w, y - h, red, green, blue)

    def show(self):
        """ Refresh LEDs """
        self.strip.show()

    def numPixels(self):
        """ The strips LED count """
        return self.strip.numPixels()

    def setBrightness(self, brightness):
        LEDShow.LED_BRIGHTNESS = brightness
        self.strip.setBrightness(LEDShow.LED_BRIGHTNESS)

    def getBrightness(self):
        return LEDShow.LED_BRIGHTNESS

    def getMaxDistance(self):
        return LEDShow.MAX_DISTANCE

    def getMinDistance(self):
        return LEDShow.MIN_DISTANCE
Esempio n. 4
0
class Monitor(object):

    def __init__(self, server_list, monitor_config, mqtt_client):

        self.interval = monitor_config['interval']
        self.recipients = monitor_config['recipients']
        self.servers = self.getServers(server_list)
        self.heartbeatFile = monitor_config['heartbeatFile']
        self.heartbeatHours = monitor_config['heartbeatHours']

        self.init_sound = monitor_config['init_sound']
        self.error_sound = monitor_config['error_sound']
        self.success_sound = monitor_config['success_sound']
        self.heartbeat_sound = monitor_config['heartbeat_sound']

        self.notification_user = monitor_config['notification_user']
        self.notification_token = monitor_config['notification_token']
        self.notification_url = monitor_config['notification_url']

        self.app_name = monitor_config['app_name']

        self.hostname = socket.gethostname()
        self.repeat_timer = None

        self.mode = 0

        self.client = mqtt_client

        self.learnIp()
        self.startChecks()

        self.notify(self.app_name + ' Started', self.init_sound)
        self.client.publish(self.app_name + ' Started|' + self.get_time() + "|" + self.get_date())

        time.sleep(2)

        self.checkServers()


    def startChecks(self):
        """Initalise timer and heartbeat"""
        self.heartbeat()
        self.getTimer()


    def notify(self, mymessage, sound):
        """Sends a pushover notification"""

        mytitle = self.hostname + " > monitor."

        return create_request([self.notification_url], 'POST', {
            "token": self.notification_token,      # Pushover app token
            "user": self.notification_user,        # Pushover user token
            "html": "1",           # 1 for HTML, 0 to disable
            "title": mytitle,      # Title of message
            "message": mymessage,  # Message (HTML if required)
            "sound": sound,     # Sound played on receiving device
            })


    def cancelTimer(self):
        self.repeat_timer.cancel()


    def getTimer(self):
        if self.repeat_timer is None:
            self.repeat_timer = RepeatTimer(self.interval,
                                        self.checkServers,
                                        *args,
                                        **kwargs)


    def get_date(self):
        now = datetime.now()
        return now.strftime("%d/%m/%Y")


    def get_time(self):
        now = datetime.now()
        return now.strftime("%H:%M")


    def learnIp(self):
        s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        s.connect(("gmail.com",80))
        ip = s.getsockname()[0]
        self.ip = ip
        s.close()
        self.client.publish(self.hostname + "|" + ip)
        time.sleep(3)
        logging.info(self.hostname + " IP " + ip)


    def run(self):
        logging.info("Run: " + self.app_name)
        self.repeat_timer.start()


    def checkServers(self, *args, **kwargs):
        self.heartbeat()

        for server in self.servers:
            _thread.start_new_thread(server.check_status, ())
            time.sleep(0.1)

        time.sleep(1)
        down_servers = self.getDownServers()

        if len(down_servers) > 0:
            self.notifyDown(down_servers)
        else:
            mes = "UP @ " + self.get_time() + "|" + self.get_date()

            logging.info(mes)
            self.client.publish(mes)
            self.reset()


    def getDownServers(self):
        down_servers = []
        for server in self.servers:
             # if server.status != 'OK' and server.fails >= server.max_fails and server.notified_fail == False:
             if server.status != 'OK' and server.fails >= server.max_fails:
                down_servers.append(server)
        return down_servers


    def notifyDown(self, down_servers):
        message = ''
        for server in down_servers:
            text = "%s %s %s - %s\n" % (server.name,
                                        server.last_checked,
                                        server.url,
                                        server.status)
            message += text
            server.notified_fail = True

            mes = "Down|" + server.name
            logging.info(mes)
            self.client.publish(mes)
            time.sleep(1)

        time.sleep(2)

        self.notify(message, self.error_sound)

        mes = "DOWN @ " + self.get_time() + "|" + self.get_date()
        logging.info(mes)
        self.client.publish(mes)


    def getServers(self, server_list):
        servers = []

        # for row in records:
        #     print("Id = ", row[0], )
        #     print("Name = ", row[1])
        #     print("URL  = ", row[2])
        #     print("Max Fails  = ", row[3])
        #     print("Assert String  = ", row[4])
        #     print("Timeout  = ", row[5], "\n")

        # for server in server_list:
        #     servers.append(Server(name=server['name'],
        #                           url=server['url'],
        #                           timeout=server['timeout'],
        #                           max_fails=server['max_fails'],
        #                           assert_string=server['assert_string']))

        for server in server_list:
            servers.append(Server(name=server[1],
                                  url=server[2],
                                  timeout=server[5],
                                  max_fails=server[3],
                                  assert_string=server[4]))

        return servers



    def reset(self):
        # logging.info("reset")
        for server in self.servers:
            server.notified_fail = False
            server.fails = 0
            server.status = 'OK'
            server.assert_pass = True


    def heartbeat(self):
        # logging.info("heartbeat")
        filePath = self.heartbeatFile
        a_name = self.app_name

        if(os.path.isfile(filePath)):

            f = open(filePath,"r")
            last = f.readline()
            f.close()

            dt_last = datetime.strptime(last, '%b %d %Y %I:%M%p')
            hours = math.floor(((datetime.now() - dt_last).total_seconds()) / 3600)
            if(hours > self.heartbeatHours):
                self.notify(a_name + ' Heartbeat', self.heartbeat_sound)
                self.client.publish("Heartbeat @ " + self.get_time() + "|" + self.get_date())
                # for recipient in self.recipients:
                self.writeHeartbeat()
        else:
            self.writeHeartbeat()


    def writeHeartbeat(self):
        # logging.info("writeHeartbeat")
        filePath = self.heartbeatFile
        f = open(filePath,"w")
        f.write(datetime.now().strftime('%b %d %Y %I:%M%p'))
        f.close()


    def update(self):
        # logging.info('update')
        self.reset()


    def setMode(self, mode):
        self.mode = mode
        modes = {
            0: "Monitor",
            1: "Backup",
            2: "Configuration",
            3: "Connect",
            4: "Disconnect",
            5: "Reboot",
            6: "Shutdown"
        }
        mode_text = modes.get(mode, "Unknown")


    def getMode(self):
        return self.mode