Example #1
1
class SerialSensorReader(SensorReader):
	def __init__(self,commConfig,sensorName,rowType=(),rateSec=60,db=None,log=None):
		SensorReader.__init__(self,commConfig,sensorName,rowType,rateSec,db,log)
		self.eol = "\n"
		self.delimiterPattern = "\\S+"
		self.delimiter = " "
	def initSensor(self):
		from serial import Serial
		self.serialP = Serial(**self.commConfig) 
		self.resetSensor()
	def stopSensor(self):
		self.serialP.close()
	def getReadings(self):
		readings = []
		ts = str((int(time())/self.rateSec)*self.rateSec)
		while self.serialP.inWaiting():
			line = readlineR(self.serialP,self.eol)
			readings.append(self.delimiter.join([ts, line]))
		readings = [x for x in readings if x != None]
		return readings
	def toRow(self, reading):
		row = re.findall(self.delimiterPattern,reading.strip())
		row = [x.strip() for x in row]
		return row
	def resetSensor(self):
		print "Reseting Sensor:" + self.sensorName
		return readlineR(self.serialP,self.eol)
Example #2
0
def scan(dev="/dev/ttyS", sta=1, end=256):
    """ scanner serial port
     --> None
     <-- list port available
    """
    mLis = []

    # if sys.platform == 'win32':
    #     # winzoz
    #     por = "COM"
    # else:
    #     # Unix
    #     por = "/dev/ttyS"
    #     #por = "/dev/ttyUSB"
    #     #por = "/dev/ttymxc"

    print "try with:", dev
    for ind in range(sta,end):
        try:
            ser = Serial("%s%d" %(dev, ind))
            por = ser.portstr.find(dev)
            print ser.portstr, por
            mLis.append( (ind, ser.portstr[sta:]))
            ser.close()
        except SerialException:
            pass
    print "found it:"
    return mLis
Example #3
0
class MachineCom():
	def __init__(self, port = 'AUTO', baudrate = 250000):
		self.serial = None
		if port == 'AUTO':
			programmer = stk500v2.Stk500v2()
			for port in serialList():
				try:
					programmer.connect(port)
					programmer.close()
					self.serial = Serial(port, baudrate, timeout=5)
					break
				except ispBase.IspError:
					pass
			programmer.close()
		else:
			self.serial = Serial(port, baudrate, timeout=5)

	def readline(self):
		if self.serial == None:
			return ''
		ret = self.serial.readline()
		print "Recv: " + ret.rstrip()
		return ret
	
	def close(self):
		if self.serial != None:
			self.serial.close()
		self.serial = None
	
	def sendCommand(self, cmd):
		if self.serial == None:
			return
		self.serial.write(cmd + '\n')
Example #4
0
class SerialPortBackEnd(BackEnd):
	
	def __init__(self, port = None, baudrate = 115200,
	             read_timeout = 1.0, write_timeout = 0.1):
		"""
		Provides a serial-port back-end for the protocol. Timeouts are in seconds.
		"""
		BackEnd.__init__(self)
		
		self.name = "Serial"
		
		# Start the emulator as a child-process
		self.serial = Serial(port,
		                     baudrate     = baudrate,
		                     timeout      = read_timeout,
		                     writeTimeout = write_timeout)
		
	
	
	def read(self, length):
		return self.serial.read(length)
	
	
	def write(self, data):
		self.serial.write(data)
	
	
	def flush(self):
		self.serial.flush()
	
	
	def close(self):
		self.serial.close()
Example #5
0
class tarjetaTOC():
    '''
    Clase de comunicacion con la tarjeta mediante puerto serial. 
    '''


    def __init__(self, controlador):
        '''
        Constructor de la clase
        '''
        self.puerto = "/dev/ttyS0"
        self.BAUDS = "9600"
        self.TIMEOUT = 1
        
        self.serial = Serial(port=self.puerto,
                             baudrate=self.BAUDS,
                             bytesize=8,
                             stopbits=1,
                             timeout=self.TIMEOUT,
                             dsrdtr=False,
                             rtscts=True)
        self.cerrar_puerto()
        
    def abrir_puerto(self):
        try:
            self.serial.open()
            #time.sleep(2)
        except:
            print "Error de apertura de puerto"
    
    def cerrar_puerto(self):
        self.serial.close()
        
    def desconectar(self):
        self.cerrar_puerto()
    
    def escribir_datos(self, datos):
        # Escribe datos en el puerto
        self.serial.flushOutput()
        self.serial.write(datos)
        print "Escribio"
        
    def crear_datos_simulador(self):
        pass
        
    def leer_datos(self):
        recv = self.serial.readline()            
        if len(recv) >= 5:
            self.serial.flushInput()
            return recv
        else:
            return (recv)
        
    def enviar_comando(self, comando):
        # Envia un comando y espera a que se reciba respuesta
        self.abrir_puerto()
        self.escribir_datos(comando)
        recv = self.leer_datos()
        self.cerrar_puerto()
        return recv
Example #6
0
def main():
    if len(sys.argv) != 2:
        print('requires one argument, the filter position')      
        sys.exit(1)
    filterwheel = Serial('/dev/filterwheel', 115200, timeout=0.1)
    filterwheel.write('pos=%i\r' % int(sys.argv[1]))
    filterwheel.close()
Example #7
0
class SerialNavigator(AbstractNavigator):
    
    FORWARD = "Forward";
    BACKWARD ="Backward";
    LEFT = "Left";
    RIGHT = "Right";

    __movements = { FORWARD : '1', BACKWARD: '2', LEFT : '3', RIGHT: '4' };
    __serial = None;

    @classmethod
    def __init__(self, com, baudRate, dataBits):
        self.__serial = Serial( com-1, baudRate, dataBits);
        self.__serial.close();
        self.__serial.open();

    @classmethod
    def moveForward(self):
        self.__serial.write(self.__movements[self.FORWARD]);
    
    @classmethod
    def moveBackward(self):
        self.__serial.write(self.__movements[self.BACKWARD]);
    
    @classmethod
    def turnLeft(self):
        self.__serial.write(self.__movements[self.LEFT]);

    @classmethod
    def turnRight(self):
        self.__serial.write(self.__movements[self.RIGHT]);
class ESP8266():
    def __init__(self, port, baud_rate):
        print "opening connection"
        self.ser = Serial(port, baud_rate, timeout=1)
        self.ser.close()
        self.ser.open()
        print "connection opened"

    def send_command(self, cmd, timeout=1000, until="-a-string-thats-never-there-"):
        self.ser.write(cmd + "\r\n")
        last_activity = millis()
        buf = ""
        while True and (millis() - last_activity) < timeout and until not in buf:
            bytes_to_read = self.ser.inWaiting()
            buf += self.ser.read(bytes_to_read)
            if bytes_to_read > 0:
                last_activity = millis()
        return buf

    def make_http_request(self, host, port, route):
        start = millis()
        self.send_command("AT+CIPSTART=0,\"TCP\",\"" + host + "\"," + str(port), 500, "OK")
        self.send_command("AT+CIPSTATUS", 500, "OK")
        msg = "GET " + route + " HTTP/1.1\r\nHost: " + host + "\r\n\r\n"
        self.send_command("AT+CIPSEND=0," + str(len(msg)), 500, "OK")
        result = self.send_command(msg, 10000, "+IPD,0,5:0")
        print result
        self.send_command("AT+CIPCLOSE=0", 500, ",CLOSED")
        print str(1 if "CC3000" in result else 0) + "," + str(millis() - start)
Example #9
0
    def testConnection(self):
        """Test connection with defined settings"""

        port_name = self.ui.portNameComboBox.currentText()
        
        try:
            baud_rate = int(self.ui.baudRateComboBox.currentText())
        except ValueError:
            baud_rate = 9600    

        if not port_name or not baud_rate:
            QMessageBox.warning(self, 'Test Connection', 'Please specify Port Name and Baud Rate')
        else:
            connected = False

            try:
                serial = Serial(port_name, baud_rate)

                if serial.isOpen():
                    connected = True
                    serial.close()
            except SerialException:
                pass

            if connected:
                QMessageBox.information(self, 'Test Connection', 'Connection ok!')
            else:
                QMessageBox.information(self, 'Test Connection', 'Connection failed!')
Example #10
0
 def _openPortWithBaudrate(self, port, baudrate):
     if baudrate != 0:
         return Serial(port, baudrate, timeout=2)
     for baudrate in baudrateList():
         try:
             ser = Serial(port, baudrate, timeout=2)
         except:
             print "Unexpected error while connecting to serial port:" + port, sys.exc_info()[0]
             continue
         ser.setDTR(1)
         time.sleep(0.1)
         ser.setDTR(0)
         time.sleep(0.2)
         starttime = time.time()
         for line in ser:
             if "start" in line:
                 ser.close()
                 ser = Serial(port, baudrate, timeout=2)
                 ser.setDTR(1)
                 time.sleep(0.1)
                 ser.setDTR(0)
                 time.sleep(0.2)
                 return ser
             if starttime - time.time() > 10:
                 break
         ser.close()
     return None
class SerialCommunicator:

    def __init__(self, port='/dev/usb/ttyUSB0', baudrate=19200):
        self.connection = Serial()
        self.connection.port = port
        self.connection.baudrate = baudrate

    def set_port(self, port_name):
        self.connection.port = port_name

    def send_command(self, message):
        self.connection.open()
        self.connection.write(message)

        # Waits until the robot starts the response
        while self.connection.read() != SOT:
            time.sleep(SLEEPING_TIME)

        message_length = self.connection.read()
        remaining_chars = ord(message_length) + 1
        message = self.connection.read(remaining_chars)
        message_type = message[0]
        encoded_data = message[1:-1]

        self.connection.close()

        return message_type, encoded_data
Example #12
0
def sms(modem_device,tel,message):
	s=Serial(modem_device)
	s.write('AT+CMGF=1\r\n'.encode('ascii'))
	s.write('AT+CMGS="{}"\r\n'.format(tel).encode('ascii'))
	s.write(message.encode('ascii'))
	s.write(b'\x1a')
	s.close()
Example #13
0
class SerialInstrument(object):

    def __init__(self, port, baud=19200):
        self.port = port
        self.baud = baud

    def read(self, num=None):
        if num:
            while self.instr.inWaiting() < num:
                pass
            return self.instr.read(num)
        while not self.instr.inWaiting():
            pass
        return self.instr.read()
        
    def write(self, data):
        self.instr.write(data)

    def __enter__(self):
        self.instr = Serial(self.port, self.baud)
        self.instr.open()
        return self

    def __exit__(self, type, value, tb):
        self.instr.close()
def uart1(portName, q):
    while not exitFlag:
        queueLock.acquire()
        if not workQueue.empty():
            data = q.get()
            ser = Serial(
                data,
                baudrate=9600,
                bytesize=8,
                parity='N',
                stopbits=1,
                timeout=None)
            while True:
                line = ser.readline(ser.inWaiting()).decode('utf-8')[:-2]
                if line:
                    t = line.split(",")
                    line2 = float(t[5])
                    if line2 > 0:
                        print(portName, line2)
                        if line == '520':
                            subprocess.call(["xte", "key Up"])
                        elif line == '620':
                            subprocess.call(["xte", "key Down"])
                        elif line == '110':
                            break
            ser.close()
class SerialSocket(WebSocket):
    def __init__(self, sock, protocols=None, extensions=None, environ=None, heartbeat_freq=None):
        super(SerialSocket, self).__init__(sock, protocols, extensions, environ, heartbeat_freq)
        self.serial = Serial()

    def received_message(self, message):
        if message.data[0:len(OPEN_CONNECTION_STRING)] == OPEN_CONNECTION_STRING:
            port = message.data[len(OPEN_CONNECTION_STRING):]
            self.serial.port = port
            self.serial.baudrate = 115200
            try:
                self.serial.open()
            except SerialException as se:
                self.send("Failed to connect to: " + port + "\n\r(" + se.message + ")\n\r")
                return

            if self.serial.isOpen():
                self.send("Connection established with: " + port + "\n\r")
                thread.start_new_thread(serial_poll, (self.serial, self))
            else:
                self.send("Failed to connect to: " + port + "\n\r")
        else:
            if self.serial.isOpen():
                self.send(message.data)
                self.serial.write(message.data)

    def close(self, code=1000, reason=''):
        # close serial connection
        print 'closing'
        self.serial.close()
        super(SerialSocket, self).close(code, reason)
Example #16
0
def main(argv):
    loglevels = [logging.CRITICAL, logging.ERROR, logging.WARN, logging.INFO, logging.DEBUG]
    parser = argparse.ArgumentParser(argv)
    parser.add_argument('-v', '--verbosity', type=int, default=4,
                        help='set logging verbosity, 1=CRITICAL, 5=DEBUG')
    parser.add_argument('tty',
                        help='Serial port device file name')
    parser.add_argument('-b', '--baudrate', default=115200, type=int,
                        help='Serial port baudrate')
    args = parser.parse_args()
    # logging setup
    logging.basicConfig(level=loglevels[args.verbosity-1])

    # open serial port
    try:
        logging.debug("Open serial port %s, baud=%d", args.tty, args.baudrate)
        port = Serial(args.tty, args.baudrate, dsrdtr=0, rtscts=0, timeout=0.3)
    except IOError:
        logging.critical("error opening serial port", file=sys.stderr)
        sys.exit(2)

    try:
        app = rssi_plot()
        app.plot_rssi(port)
    except KeyboardInterrupt:
        port.close()
        sys.exit(2)
class AcquisitionThread(Thread):
    BAUDRATE = 57600
    START_CHARACTER = b's'
    PACKET_SIZE = 69

    def __init__(self, acquisition_queue):
        super(AcquisitionThread, self).__init__()
        self.acquisition_queue = acquisition_queue
        self.exit_flag = False

    def run(self):
        port_nb = serial_port()[0]
        self.device = Serial(port_nb, baudrate=self.BAUDRATE, timeout=0.2)
        while not self.exit_flag:
            c = self.device.read(1)
            if c == self.START_CHARACTER:
                while self.device.inWaiting() < self.PACKET_SIZE:
                    pass
                data = self.device.read(self.PACKET_SIZE)

                rocket_data = RocketData(data)
                # checksum_validated = rocket_data.validateCheckSum()
                checksum_validated = True
                if checksum_validated:
                    self.acquisition_queue.put(rocket_data)
        self.device.close()



    def stop(self):
        self.exit_flag = True
Example #18
0
class GPS:

    def __init__(self, port_name, baud_rate, logger):
        self.logger = logger
        self.logger.write("Starting GPS Communications")
        self.serial = Serial(port_name, baud_rate)

        self.lat = 0
        self.long = 0

    def get_GPS(self):
        while (self.lat == 0.0):
            self.logger.write("Waiting for GPS")
            time.sleep(1)
        return (self.lat, self.long)

    def read_data(self):
        if self.serial.inWaiting() > 0:
            data = self.serial.readline().rstrip()
            if data[0:6] == "$GPRMC":
                fields = data.split(',')
                if fields[2] == 'A':
                  self.lat = int(fields[3][0:2]) + (float(fields[3][2:]) / 60.0) #ASSUMES TWO DIGIT LATITUDE
                  self.long = int(fields[5][0:3]) + (float(fields[5][3:]) / 60.0) #ASSUMES THREE DIGIT LONGITUDE
                else:
                  self.lat = 0.0
                  self.long = 0.0

    def close(self):
        self.serial.close()
class SerialPortDataSource:
	def __init__(self, params):
		self.port = Serial()
		self.port.port = params['port']
		self.port.baudrate = params['baudrate']

	def open(self):
		try:
			self.port.open()
			return True
		except SerialException as e:
			return str(e)
	
	def close(self):
	    self.port.close()
	
	def execute(self, command):
		self.port.write(command + '\r\n')
		res = ""
		c = ''
		while (c != '>'):
			res += c
			c = self.port.read(1)
		
		return res
Example #20
0
def run(command):
    global protocolSettings
    global databaseSettings
    global usefix
    if command == "list":
        listPorts()
    elif command == "read":
        debug("Reading sequence")
        process(read(usefix))
    elif command == "defaults":
        listDefaults()
    elif command == "jobread":
        debug("Starting endless read")
        global serialSettings
        global job
        job = True
        serial = None
        try:
            serial = Serial(port=serialSettings["port"], baudrate=serialSettings["baudrate"])
            debug("flushing")
            serial.flushInput()
            serial.flushOutput()
            while True:
                debug("Reading sequence (job)")
                process(read(usefix, serial))
                sleep(float(databaseSettings["wait"]))
        finally:
            if serial is not None and serial.isOpen():
                serial.close()
    else:
        log("Unknown command: " + command)
    def handle(self, *args, **options):
        if len(args) < 2:
            print "No enough arguments"
            return

        n = 0
        MAX = 5
        while(n < MAX):
            try:
                ser = Serial(args[0], args[1], timeout=5)
                ser.write('t')
                temp = float(ser.readline()[:-1]) / 10
                ser.write('c')
                state = ser.read()
                TempHistory.objects.create(datetime=datetime.utcnow(), temp=temp, state=state)

                settings = TempSettings.load()
                ser.write('sl{:d} '.format(int(settings.low_boundary * 10)))
                ser.write('sh{:d} '.format(int(settings.high_boundary * 10)))
            except TimeoutException:
                ser.close()
                n += 1
            else:
                break
        if n == MAX:
            sys.stderr.write('Error syncing with thermostat')
Example #22
0
    def available_ports():
        usb_serial_ports = filter(
            (lambda x: x.startswith('ttyUSB')),
            os.listdir('/dev'))

        ports = []
        for p in usb_serial_ports:
            ports.append(serial_for_url('/dev/'+p, do_not_open=True))


        """
        also check for old school serial ports, my hope is that this will enable
        both USB serial adapters and standard serial ports

        Scans COM1 through COM255 for available serial ports

        returns a list of available ports
        """
        for i in range(256):
            try:
                p = Serial(i)
                p.close()
                ports.append(p)
            except SerialException:
                pass

        return ports
Example #23
0
class SerialServer(Thread):
	def __init__(self, port="/dev/ttyACM0", baudrate=9600, timetoread=2):
		Thread.__init__(self)
		self.server = Serial(port=port, baudrate=baudrate)
		self.dataInQueeud = False
		self.running = True
		self.timetoread = timetoread #periodicite de lecture du port
		self.datas = "" #les donnees lus
		self.dataToSend = ""  #les donneees à envoyer
		
	def run(self):
		"""lecture continue du port série. Lorsqu'il y'a quelque chose à lire, il lie puis envoie les donnees"""
		while self.running == True:
			while self.server.inWaiting() > 0:
				self.datas += self.server.readline()
			sleep(self.timetoread) #pause
			#envoie s'il y'a quelques a envoyer
			if self.dataToSend != "":
				self.server.write(self.dataToSend)
				self.server.flush()

	def recvdatas(self):
		res = self.datas
		self.datas = ""
		return res

	def senddatas(self, data = ""):
		self.dataToSend = data

	def toStop(self):
		self.server.close()
		self.running = False
def buildDataSet(mySerialPort, numOfPoints, workingDir):
    # Ask user for # of samples and prefix of dir
    (numOfSamples, prefix) = askForPnN()
    # Create the dir to store the results
    createResultsDir(prefix, workingDir)

    # Now create nSample files with the results
    for i in range(0, numOfSamples, 1):
        print "\nSpeak into the mic now\n"

        # Open the serial port
        port = Serial(mySerialPort, 230400, timeout=2.0)
        port.close()
        port.open()

        # Read results from serial line
        rawData = getSerialData(numOfPoints, port)

        # Close the serial port
        port.close()

        # Normalize the data and convert to FFT
        dataNorm = normalize(rawData)
        saveAsWav(dataNorm, prefix, workingDir, i)
        dataFFT = fftMyWav(dataNorm, numOfPoints)
        saveAsTxt(dataFFT, prefix, workingDir, i)

        print "\nGot it. " + str(numOfSamples - i - 1) + " samples left to go."
    return numOfSamples
Example #25
0
class Joystick():

  def __init__(self, port, baud=57600):
    self.port = port
    self.baud = baud
    self.ser = None
  def open(self):
    try:
      self.ser = Serial(self.port, self.baud)
    except:
      print(" Open serial port %s failled with baudrate %d"%(self.port, self.baud))

  def __enter__(self):
    self.open()
    return self

  def __exit__(self, type, value, traceback):
    self.ser.close()
    return True

  def __iter__(self):
    print("iter")
    return self

  def __next__(self):
    s = self.ser.readline()
    return s
class PlotUpdater(threading.Thread):
    """This class sets the fraction of the progressbar"""
    
    #Thread event, stops the thread if it is set.
    stopthread = threading.Event()
    
    def __init__(self, gui):
        threading.Thread.__init__(self) #Call constructor of parent
        self.gui = gui
        self.frac = 0
        self.ser = Serial("/dev/ttyACM0",115200)
        #self.ser.timeout = 1
        self.i = 0
    
    def run(self):
        """Run method, this is the code that runs while thread is alive."""
        
        #self.ser.readline()
        #self.ser.readline()
        
        #While the stopthread event isn't setted, the thread keeps going on
        while not self.stopthread.isSet() :
            # Acquiring the gtk global mutex
            #gtk.threads_enter()
            #Setting the fraction
            self.frac += 0.01
            self.i += 1
            #self.gui.line.set_data((t, np.sin(3*np.pi*(t+self.frac))))
            
            rslt = ''
            self.ser.write("d\n")
            s =  self.ser.readline().strip()
            while s != '' :
                rslt += s+'\n'
                s =  self.ser.readline().strip()
                #print repr(s)
            
            try:
                n = np.loadtxt(StringIO(rslt))
            
                angles = n[:,1]
                intensities = n[:,2]
                
                #(self.gui.s0p, self.gui.s1, self.gui.s2, self.gui.s3, self.gui.dop)=get_stokes(angles,intensities)
                
                self.gui.line.set_data((angles, intensities))

            except ValueError:
                print "Value Error"
                
            # Releasing the gtk global mutex
            #gtk.threads_leave()
            
            #Delaying 100ms until the next iteration
        
        self.ser.close()
            
    def stop(self):
        """Stop method, sets the event to terminate the thread's main loop"""
        self.stopthread.set()
Example #27
0
def listenPort():
    ser = Serial(port=config.serialPort, baudrate=config.serialBaudrate, timeout=1)
    print("connected to: " + ser.portstr)
    while True:
        line = ser.readline()
        if line:
            parse(line)
    ser.close()
Example #28
0
def main():
    port = Serial(options.port, options.baudrate, timeout=options.timeout)
    mk2 = MK2(port).start()

    #mk2.set_state(3)
    print mk2.get_state()

    port.close()
Example #29
0
    def __init__(self):
        try:

            self._toQuit = False

            rospy.init_node('RiCTraffic')
            params = RiCParam()
            ser = Serial('/dev/%s' % params.getConPort())
            ser.flushInput()
            ser.flushOutput()
            incomingHandler = IncomingHandler()
            input = ser
            output = SerialWriteHandler(ser, incomingHandler, input)
            data = []
            toPrint = ''
            input.baudrate = 9600
            incomingLength = 0
            headerId = 0
            devBuilder = DeviceBuilder(params, output, input, incomingHandler)
            gotHeaderStart = False
            gotHeaderDebug = False
            msgHandler = None
            server = None

            rospy.loginfo("Current version: %.2f" % VERSION)
            is_wd_active = False
            try:
                self.waitForConnection(output)
                if self.checkVer(input):
                    input.timeout = None
                    rospy.loginfo("Configuring devices...")
                    devBuilder.createServos()
                    devBuilder.createCLMotors()
                    devBuilder.createDiff()
                    devBuilder.createURF()
                    devBuilder.createSwitchs()
                    devBuilder.createPPM()
                    devBuilder.createIMU()
                    devBuilder.createRelays()
                    devBuilder.createGPS()
                    devBuilder.createOpenLoopMotors()
                    devBuilder.createBattery()
                    devBuilder.createOpenDiff()
                    devBuilder.createDiffFour()
                    devBuilder.createEmergencySwitch()
                    devs = devBuilder.getDevs()
                    devBuilder.sendFinishBuilding()
                    input.timeout = None
                    rospy.loginfo("Done, RiC Board is ready.")
                    msgHandler = IncomingMsgHandler(devs, output)
                    server = Server(devs, params)
                    Thread(target=self.checkForSubscribers,
                           args=(devs, )).start()
                    Thread(target=msgHandler.run, args=()).start()
                    wd_keep_alive = int(round(time.time() * 1000))
                    while not rospy.is_shutdown() and not is_wd_active:
                        if gotHeaderStart:
                            if len(data) < 1:
                                data.append(input.read())
                                incomingLength, headerId = incomingHandler.getIncomingHeaderSizeAndId(
                                    data)
                            elif incomingLength >= 1:
                                for i in range(1, incomingLength):
                                    data.append(input.read())
                                msg = self.genData(data, headerId)
                                if msg is not None and msg.getId() != CON_REQ:
                                    msgHandler.addMsg(msg)
                                elif msg.getId(
                                ) == CON_REQ and not msg.toConnect():
                                    subprocess.Popen(
                                        shlex.split("pkill -f RiCTraffic"))
                                    rospy.logerr(
                                        "Emergency button is activated.")
                                    break
                                data = []
                                gotHeaderStart = False
                            else:
                                data = []
                                gotHeaderStart = False
                        elif gotHeaderDebug:
                            size = ord(input.read())

                            for i in xrange(size):
                                toPrint += input.read()

                            code = ord(input.read())

                            if code == INFO:
                                rospy.loginfo(toPrint)
                            elif code == ERROR:
                                rospy.logerr(toPrint)
                            elif code == WARRNING:
                                rospy.logwarn(toPrint)

                            toPrint = ''
                            gotHeaderDebug = False
                        elif input.inWaiting() > 0:
                            checkHead = ord(input.read())
                            if checkHead == HEADER_START:
                                gotHeaderStart = True
                            elif checkHead == HEADER_DEBUG:
                                gotHeaderDebug = True
                            elif checkHead == KEEP_ALIVE_HEADER:
                                wd_keep_alive = int(round(time.time() * 1000))
                        is_wd_active = (int(round(time.time() * 1000)) -
                                        wd_keep_alive) > WD_TIMEOUT
                else:
                    raise VersionError(NEED_TO_UPDATE)
                if is_wd_active:
                    rospy.logerr(
                        "RiCBoard isn't responding.\nThe Following things can make this happen:"
                        "\n1) If accidentally the manual driving is turn on, If so turn it off the relaunch the RiCBoard"
                        "\n2) If accidentally the RiCTakeovver gui is turn on,If so turn it off the relaunch the RiCBoard"
                        "\n3) The RiCBoard is stuck, If so please power off the robot and start it again. And contact RobotICan support by this email: [email protected]"
                    )
            except KeyboardInterrupt:
                pass

            except VersionError:
                rospy.logerr(
                    "Can't load RiCBoard because the version don't mach please update the firmware."
                )

            finally:
                if not is_wd_active:
                    con = ConnectionResponse(False)
                    output.writeAndWaitForAck(con.dataTosend(), RES_ID)
                ser.close()
                if msgHandler != None: msgHandler.close()
                self._toQuit = True

        except SerialException:
            rospy.logerr(
                "Can't find RiCBoard, please check if its connected to the computer."
            )
Example #30
0
class Uart(threading.Thread, Device):
    def __init__(self, port, baudrate=115200, device_name=None, rtscts=True):
        self.events_queue = collections.deque(maxlen=EVT_Q_BUF)
        threading.Thread.__init__(self)
        if not device_name:
            device_name = port
        self.device_name = device_name
        self.logger = logging.getLogger(self.device_name)
        Device.__init__(self, self.device_name)

        self._write_lock = threading.Lock()

        self.logger.debug("log Opening port %s, baudrate %s, rtscts %s", port,
                          baudrate, rtscts)

        # We change the baudrate around to reset the UART state.
        # This is a trick to force detection of flow control settings etc.
        _trick_baudrate = 9600
        if baudrate == _trick_baudrate:
            _trick_baudrate = 115200
        self.serial = Serial(port=port,
                             baudrate=_trick_baudrate,
                             rtscts=rtscts,
                             timeout=0.1)
        self.serial.baudrate = baudrate

        self.keep_running = True
        self.start()

    def __del__(self):
        self.stop()

    def stop(self):
        self.keep_running = False
        self.kill_writer()

    def get_packet_from_uart(self):
        tmp = bytearray([])
        while self.keep_running:
            tmp += bytearray(self.serial.read())
            tmp_len = len(tmp)
            if tmp_len > 0:
                pkt_len = tmp[0]
                if tmp_len > pkt_len:
                    data = tmp[:pkt_len + 1]
                    yield data
                    tmp = tmp[pkt_len + 1:]

    def run(self):
        for pkt in self.get_packet_from_uart():
            self.logger.debug("RX: %s", pkt.hex())
            try:
                if len(pkt) < 2:
                    self.logger.error('Invalid packet: %r', pkt)
                    continue
                parsed_packet = event_deserialize(pkt)
                if not parsed_packet:
                    self.logger.error("Unable to deserialize %s", pkt.hex())

            except Exception:
                self.logger.error('Exception with packet %s', pkt.hex())
                self.logger.error('traceback: %s', traceback.format_exc())
                parsed_packet = None

            if parsed_packet:
                self.events_queue.append(parsed_packet)
                self.logger.debug('parsed_packet %r', parsed_packet)
                self.process_packet(parsed_packet)

        self.serial.close()
        self.logger.debug("exited read event")

    def write_data(self, cmd):
        with self._write_lock:
            if self.keep_running:
                data = cmd.serialize()
                self.logger.debug("TX: %s", bytearray(data).hex())
                self.serial.write(bytearray(data))
                self.process_command(cmd)

    def __repr__(self):
        return '%s(port="%s", baudrate=%s, device_name="%s")' % (
            self.__class__.__name__, self.serial.port, self.serial.baudrate,
            self.device_name)
Example #31
0
class Manipulator():
    def __init__(self):
        #print(time, self, file=stderr)
        self.r2 = photo()
        im2 = Image.open('test.png')
        (self.x, self.y) = im2.size

    def search_object(self, object_serch):
        #найти объект на снимке
        self.x_degree = 0
        self.y_degree = 0
        self.object_file = object_serch
        for Y1 in range(0, self.y, Step):
            print('конец строки', file=stderr)
            for X1 in range(0, self.x, Step):
                for path, dirs, files in os.walk(self.object_file):
                    for f in files:
                        i = '%s/%s' % (path, f)
                        self.r1 = cv.imread(i)
                        im1 = Image.open("%s/%s" % (path, f))
                        (x1, y1) = im1.size
                        self.r2_1 = self.r2[Y1:Y1 + y1, X1:X1 + x1]
                        self.r2_2 = cv.resize(self.r2_1, (Compress, Compress))
                        self.r1 = cv.resize(self.r1, (Compress, Compress))
                        compare(self.r1, self.r2_2)
                        print(i,
                              '  ',
                              compare(self.r1, self.r2_2),
                              file=stderr)
                    if compare(self.r1, self.r2_2) <= Coefficient:
                        print('обьект найден :)', file=stderr)
                        #//////////////////////////////////////////////////////////////////////////////
                        #расчет расположения обьекта на фото
                        self.X_pix = X1 + (y1 / 2)
                        self.Y_pix = Y1 + (x1 / 2)
                        print('X',
                              self.X_pix,
                              "/",
                              'Y',
                              self.Y_pix,
                              file=stderr)
                        #//////////////////////////////////////////////////////////////////////////////
                        #расчет угла поворота
                        #self.a1=(self.Y_pix)
                        #self.b1=(self.X_pix)
                        #self.a2=(self.x/2)-self.a1
                        #self.b2=(self.y-self.b1)
                        #self.tg_A=(self.b2/self.a2)
                        #print( 'tg',self.tg_A)

                        self.x_degree = int(
                            (0 + self.X_pix) / 2 / (self.x / 360))
                        if self.x_degree > 180:
                            self.x_degree = 180
                        self.y_degree = int(
                            (0 + self.Y_pix) / 2 / (self.y / 360))

                        break


#//////////////////////////////////////////////////////////////////////////////
                if compare(self.r1, self.r2_2) <= Coefficient:
                    break
            if compare(self.r1, self.r2_2) <= Coefficient:
                break
        if compare(self.r1, self.r2_2) >= Coefficient:
            print('обьект не найден :(', file=stderr)
        return self.x_degree, self.y_degree

    def show_object(self):
        #вывести найденное изображение на экран
        try:
            if compare(self.r1, self.r2_2) <= Coefficient:
                cv.imshow('обьект', self.r2_1)
                cv.waitKey(0)
                cv.destroyAllWindows()
            elif compare(self.r1, self.r2_2) >= Coefficient:
                print('не удалось показать изображение :(', file=stderr)
        except AttributeError:
            pass

    def show_diagram_photo(self):
        #вывести изображение в plt
        try:
            print('разрешение -', '(', self.x, '/', self.y, ')')
            plt.imshow(cv.cvtColor(self.r2, cv.COLOR_BGR2RGB))
        except AttributeError:
            print('не удалось показать диаграмму :(', file=stderr)

    def connect(self, com='/dev/ttyACM0', serial=9600):
        #подключение к ардуино
        self.com = com  # номер ком порта
        self.serial = serial  # частота
        try:
            self.arduino = Serial(self.com, self.serial, timeout=2)
            sleep(1)
            print("Connected to arduino! :)", file=stderr)
        except SerialException:
            print("Error connecting to arduino!!! :(", file=stderr)

    def disconnect(self):
        #отключение от ардуино
        self.arduino.close()
        print('Disconnected  arduino!', file=stderr)

    def moveX(self, x):
        #отправка угла поворота на ардуино по оси X
        try:
            print('градусы X =', x)
            self.arduino.write(bytes([9, x]))
            sleep(1)
            print('движение по X ', file=stderr)
        except AttributeError:
            print('Arduino:X не отправлен', file=stderr)

    def moveY(self, y):
        #отправка угла поворота на ардуино по оси Y
        try:
            print('градусы Y =', y, file=stderr)
            sleep(1)
            self.arduino.write(bytes([9, y]))
            sleep(1)
            print('движение по Y', file=stderr)
        except AttributeError:
            print('Arduino:Y не отправлен', file=stderr)
Example #32
0
class Stk500v2(ispBase.IspBase):
    def __init__(self):
        self.serial = None
        self.seq = 1
        self.last_addr = -1
        self.progress_callback = None

    def connect(self, port="COM22", speed=115200):
        if self.serial is not None:
            self.close()
        try:
            self.serial = Serial(str(port),
                                 speed,
                                 timeout=1,
                                 writeTimeout=10000)
        except SerialException:
            raise ispBase.IspError("Failed to open serial port")
        except:
            raise ispBase.IspError(
                "Unexpected error while connecting to serial port:" + port +
                ":" + str(sys.exc_info()[0]))
        self.seq = 1

        #Reset the controller
        for n in range(0, 2):
            self.serial.setDTR(True)
            time.sleep(0.1)
            self.serial.setDTR(False)
            time.sleep(0.1)
        time.sleep(0.2)

        self.serial.flushInput()
        self.serial.flushOutput()
        try:
            if self.sendMessage([
                    0x10, 0xc8, 0x64, 0x19, 0x20, 0x00, 0x53, 0x03, 0xac, 0x53,
                    0x00, 0x00
            ]) != [0x10, 0x00]:
                raise ispBase.IspError("Failed to enter programming mode")

            self.sendMessage([0x06, 0x80, 0x00, 0x00, 0x00])
            if self.sendMessage([0xEE])[1] == 0x00:
                self._has_checksum = True
            else:
                self._has_checksum = False
        except ispBase.IspError:
            self.close()
            raise
        self.serial.timeout = 5

    def close(self):
        if self.serial is not None:
            self.serial.close()
            self.serial = None

    #Leave ISP does not reset the serial port, only resets the device, and returns the serial port after disconnecting it from the programming interface.
    #	This allows you to use the serial port without opening it again.
    def leaveISP(self):
        if self.serial is not None:
            if self.sendMessage([0x11]) != [0x11, 0x00]:
                raise ispBase.IspError("Failed to leave programming mode")
            ret = self.serial
            self.serial = None
            return ret
        return None

    def isConnected(self):
        return self.serial is not None

    def hasChecksumFunction(self):
        return self._has_checksum

    def sendISP(self, data):
        recv = self.sendMessage(
            [0x1D, 4, 4, 0, data[0], data[1], data[2], data[3]])
        return recv[2:6]

    def writeFlash(self, flash_data):
        #Set load addr to 0, in case we have more then 64k flash we need to enable the address extension
        page_size = self.chip["pageSize"] * 2
        flash_size = page_size * self.chip["pageCount"]
        Logger.log("d", "Writing flash")
        if flash_size > 0xFFFF:
            self.sendMessage([0x06, 0x80, 0x00, 0x00, 0x00])
        else:
            self.sendMessage([0x06, 0x00, 0x00, 0x00, 0x00])
        load_count = (len(flash_data) + page_size - 1) / page_size
        for i in range(0, int(load_count)):
            self.sendMessage([
                0x13, page_size >> 8, page_size
                & 0xFF, 0xc1, 0x0a, 0x40, 0x4c, 0x20, 0x00, 0x00
            ] + flash_data[(i * page_size):(i * page_size + page_size)])
            if self.progress_callback is not None:
                if self._has_checksum:
                    self.progress_callback(i + 1, load_count)
                else:
                    self.progress_callback(i + 1, load_count * 2)

    def verifyFlash(self, flash_data):
        if self._has_checksum:
            self.sendMessage([
                0x06, 0x00, (len(flash_data) >> 17) & 0xFF,
                (len(flash_data) >> 9) & 0xFF, (len(flash_data) >> 1) & 0xFF
            ])
            res = self.sendMessage([0xEE])
            checksum_recv = res[2] | (res[3] << 8)
            checksum = 0
            for d in flash_data:
                checksum += d
            checksum &= 0xFFFF
            if hex(checksum) != hex(checksum_recv):
                raise ispBase.IspError(
                    "Verify checksum mismatch: 0x%x != 0x%x" %
                    (checksum & 0xFFFF, checksum_recv))
        else:
            #Set load addr to 0, in case we have more then 64k flash we need to enable the address extension
            flash_size = self.chip["pageSize"] * 2 * self.chip["pageCount"]
            if flash_size > 0xFFFF:
                self.sendMessage([0x06, 0x80, 0x00, 0x00, 0x00])
            else:
                self.sendMessage([0x06, 0x00, 0x00, 0x00, 0x00])

            load_count = (len(flash_data) + 0xFF) / 0x100
            for i in range(0, int(load_count)):
                recv = self.sendMessage([0x14, 0x01, 0x00, 0x20])[2:0x102]
                if self.progress_callback is not None:
                    self.progress_callback(load_count + i + 1, load_count * 2)
                for j in range(0, 0x100):
                    if i * 0x100 + j < len(flash_data) and flash_data[
                            i * 0x100 + j] != recv[j]:
                        raise ispBase.IspError("Verify error at: 0x%x" %
                                               (i * 0x100 + j))

    def sendMessage(self, data):
        message = struct.pack(">BBHB", 0x1B, self.seq, len(data), 0x0E)
        for c in data:
            message += struct.pack(">B", c)
        checksum = 0
        for c in message:
            checksum ^= c
        message += struct.pack(">B", checksum)
        try:
            self.serial.write(message)
            self.serial.flush()
        except SerialTimeoutException:
            raise ispBase.IspError("Serial send timeout")
        self.seq = (self.seq + 1) & 0xFF
        return self.recvMessage()

    def recvMessage(self):
        state = "Start"
        checksum = 0
        while True:
            s = self.serial.read()
            if len(s) < 1:
                raise ispBase.IspError("Timeout")
            b = struct.unpack(">B", s)[0]
            checksum ^= b
            if state == "Start":
                if b == 0x1B:
                    state = "GetSeq"
                    checksum = 0x1B
            elif state == "GetSeq":
                state = "MsgSize1"
            elif state == "MsgSize1":
                msg_size = b << 8
                state = "MsgSize2"
            elif state == "MsgSize2":
                msg_size |= b
                state = "Token"
            elif state == "Token":
                if b != 0x0E:
                    state = "Start"
                else:
                    state = "Data"
                    data = []
            elif state == "Data":
                data.append(b)
                if len(data) == msg_size:
                    state = "Checksum"
            elif state == "Checksum":
                if checksum != 0:
                    state = "Start"
                else:
                    return data
Example #33
0
class printcore():
    def __init__(self, port = None, baud = None, dtr=None):
        """Initializes a printcore instance. Pass the port and baud rate to
           connect immediately"""
        self.baud = None
        self.dtr = None
        self.port = None
        self.analyzer = gcoder.GCode()
        # Serial instance connected to the printer, should be None when
        # disconnected
        self.printer = None
        # clear to send, enabled after responses
        # FIXME: should probably be changed to a sliding window approach
        self.clear = 0
        # The printer has responded to the initial command and is active
        self.online = False
        # is a print currently running, true if printing, false if paused
        self.printing = False
        self.mainqueue = None
        self.priqueue = Queue(0)
        self.queueindex = 0
        self.lineno = 0
        self.resendfrom = -1
        self.paused = False
        self.sentlines = {}
        self.log = deque(maxlen = 10000)
        self.sent = []
        self.writefailures = 0
        self.tempcb = None  # impl (wholeline)
        self.recvcb = None  # impl (wholeline)
        self.sendcb = None  # impl (wholeline)
        self.preprintsendcb = None  # impl (wholeline)
        self.printsendcb = None  # impl (wholeline)
        self.layerchangecb = None  # impl (wholeline)
        self.errorcb = None  # impl (wholeline)
        self.startcb = None  # impl ()
        self.endcb = None  # impl ()
        self.onlinecb = None  # impl ()
        self.loud = False  # emit sent and received lines to terminal
        self.tcp_streaming_mode = False
        self.greetings = ['start', 'Grbl ']
        self.wait = 0  # default wait period for send(), send_now()
        self.read_thread = None
        self.stop_read_thread = False
        self.send_thread = None
        self.stop_send_thread = False
        self.print_thread = None
        if port is not None and baud is not None:
            self.connect(port, baud)
        self.xy_feedrate = None
        self.z_feedrate = None

    def logError(self, error):
        if self.errorcb:
            try: self.errorcb(error)
            except: logging.error(traceback.format_exc())
        else:
            logging.error(error)

    @locked
    def disconnect(self):
        """Disconnects from printer and pauses the print
        """
        if self.printer:
            if self.read_thread:
                self.stop_read_thread = True
                if threading.current_thread() != self.read_thread:
                    self.read_thread.join()
                self.read_thread = None
            if self.print_thread:
                self.printing = False
                self.print_thread.join()
            self._stop_sender()
            try:
                self.printer.close()
            except socket.error:
                pass
            except OSError:
                pass
        self.printer = None
        self.online = False
        self.printing = False

    @locked
    def connect(self, port = None, baud = None, dtr=None, err_message_softness=False):
        """Set port and baudrate if given, then connect to printer
        """
        if self.printer:
            self.disconnect()
        if port is not None:
            self.port = port
        if baud is not None:
            self.baud = baud
        if dtr is not None:
            self.dtr = dtr
        if self.port is not None and self.baud is not None:
            # Connect to socket if "port" is an IP, device if not
            host_regexp = re.compile("^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$|^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$")
            is_serial = True
            if ":" in port:
                bits = port.split(":")
                if len(bits) == 2:
                    hostname = bits[0]
                    try:
                        port = int(bits[1])
                        if host_regexp.match(hostname) and 1 <= port <= 65535:
                            is_serial = False
                    except:
                        pass
            self.writefailures = 0
            if not is_serial:
                self.printer_tcp = socket.socket(socket.AF_INET,
                                                 socket.SOCK_STREAM)
                self.printer_tcp.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
                self.timeout = 0.25
                self.printer_tcp.settimeout(1.0)
                try:
                    self.printer_tcp.connect((hostname, port))
                    self.printer_tcp.settimeout(self.timeout)
                    self.printer = self.printer_tcp.makefile()
                except socket.error as e:
                    self.logError(_("Could not connect to %s:%s:") % (hostname, port) +
                                  "\n" + _("Socket error %s:") % e.errno +
                                  "\n" + e.strerror)
                    self.printer = None
                    self.printer_tcp = None
                    return
            else:
                disable_hup(self.port)
                self.printer_tcp = None
                try:
                    self.printer = Serial(port = self.port,
                                          baudrate = self.baud,
                                          timeout = 0.25,
                                          parity = PARITY_ODD)
                    self.printer.close()
                    self.printer.parity = PARITY_NONE
                    try:
                        # This appears not to work on many platforms,
                        # so we're going to call it but not care if it fails
                        self.printer.setDTR(dtr)
                    except:
                        #not sure whether to output an error message
                        #self.logError(_("Could not set DTR on this platform"))
                        pass
                    self.printer.open()
                except SerialException as e:
                    self.printer = None
                    raise
                    return e.errno
                except IOError as e:
                    if not err_message_softness:
                        self.logError(_("Could not connect to %s at baudrate %s:") % (self.port, self.baud) +
                                        "\n" + _("IO error: %s") % e)
                    self.printer = None
                    raise
                    return
            self.stop_read_thread = False
            self.read_thread = threading.Thread(target = self._listen)
            self.read_thread.start()
            self._start_sender()

    def reset(self):
        """Reset the printer
        """
        if self.printer and not self.printer_tcp:
            self.printer.setDTR(1)
            time.sleep(0.2)
            self.printer.setDTR(0)

    def _readline(self):
        try:
            try:
                line = self.printer.readline()
                if self.printer_tcp and not line:
                    raise OSError(-1, "Read EOF from socket")
            except socket.timeout:
                return ""

            if len(line) > 1:
                self.log.append(line)
                if self.recvcb:
                    try: self.recvcb(line)
                    except: self.logError(traceback.format_exc())
                if self.loud: logging.info("RECV: %s" % line.rstrip())
            return line
        except SelectError as e:
            if 'Bad file descriptor' in e.args[1]:
                self.logError(_(u"Can't read from printer (disconnected?) (SelectError {0}): {1}").format(e.errno, decode_utf8(e.strerror)))
                return None
            else:
                self.logError(_(u"SelectError ({0}): {1}").format(e.errno, decode_utf8(e.strerror)))
                raise
        except SerialException as e:
            self.logError(_(u"Can't read from printer (disconnected?) (SerialException): {0}").format(decode_utf8(str(e))))
            return None
        except socket.error as e:
            self.logError(_(u"Can't read from printer (disconnected?) (Socket error {0}): {1}").format(e.errno, decode_utf8(e.strerror)))
            return None
        except OSError as e:
            if e.errno == errno.EAGAIN:  # Not a real error, no data was available
                return ""
            self.logError(_(u"Can't read from printer (disconnected?) (OS Error {0}): {1}").format(e.errno, e.strerror))
            return None

    def _listen_can_continue(self):
        if self.printer_tcp:
            return not self.stop_read_thread and self.printer
        return (not self.stop_read_thread
                and self.printer
                and self.printer.isOpen())

    def _listen_until_online(self):
        while not self.online and self._listen_can_continue():
            self._send("M105")
            if self.writefailures >= 4:
                logging.error(_("Aborting connection attempt after 4 failed writes."))
                return
            empty_lines = 0
            while self._listen_can_continue():
                line = self._readline()
                if line is None: break  # connection problem
                # workaround cases where M105 was sent before printer Serial
                # was online an empty line means read timeout was reached,
                # meaning no data was received thus we count those empty lines,
                # and once we have seen 15 in a row, we just break and send a
                # new M105
                # 15 was chosen based on the fact that it gives enough time for
                # Gen7 bootloader to time out, and that the non received M105
                # issues should be quite rare so we can wait for a long time
                # before resending
                if not line:
                    empty_lines += 1
                    if empty_lines == 15: break
                else: empty_lines = 0
                if line.startswith(tuple(self.greetings)) \
                   or line.startswith('ok') or "T:" in line:
                    self.online = True
                    if self.onlinecb:
                        try: self.onlinecb()
                        except: self.logError(traceback.format_exc())
                    return

    def _listen(self):
        """This function acts on messages from the firmware
        """
        self.clear = True
        if not self.printing:
            self._listen_until_online()
        while self._listen_can_continue():
            line = self._readline()
            if line is None:
                break
            if line.startswith('DEBUG_'):
                continue
            if line.startswith(tuple(self.greetings)) or line.startswith('ok'):
                self.clear = True
            if line.startswith('ok') and "T:" in line and self.tempcb:
                # callback for temp, status, whatever
                try: self.tempcb(line)
                except: self.logError(traceback.format_exc())
            elif line.startswith('Error'):
                self.logError(line)
            # Teststrings for resend parsing       # Firmware     exp. result
            # line="rs N2 Expected checksum 67"    # Teacup       2
            if line.lower().startswith("resend") or line.startswith("rs"):
                for haystack in ["N:", "N", ":"]:
                    line = line.replace(haystack, " ")
                linewords = line.split()
                while len(linewords) != 0:
                    try:
                        toresend = int(linewords.pop(0))
                        self.resendfrom = toresend
                        break
                    except:
                        pass
                self.clear = True
        self.clear = True

    def _start_sender(self):
        self.stop_send_thread = False
        self.send_thread = threading.Thread(target = self._sender)
        self.send_thread.start()

    def _stop_sender(self):
        if self.send_thread:
            self.stop_send_thread = True
            self.send_thread.join()
            self.send_thread = None

    def _sender(self):
        while not self.stop_send_thread:
            try:
                command = self.priqueue.get(True, 0.1)
            except QueueEmpty:
                continue
            while self.printer and self.printing and not self.clear:
                time.sleep(0.001)
            self._send(command)
            while self.printer and self.printing and not self.clear:
                time.sleep(0.001)

    def _checksum(self, command):
        return reduce(lambda x, y: x ^ y, map(ord, command))

    def startprint(self, gcode, startindex = 0):
        """Start a print, gcode is an array of gcode commands.
        returns True on success, False if already printing.
        The print queue will be replaced with the contents of the data array,
        the next line will be set to 0 and the firmware notified. Printing
        will then start in a parallel thread.
        """
        if self.printing or not self.online or not self.printer:
            return False
        self.queueindex = startindex
        self.mainqueue = gcode
        self.printing = True
        self.lineno = 0
        self.resendfrom = -1
        self._send("M110", -1, True)
        if not gcode or not gcode.lines:
            return True
        self.clear = False
        resuming = (startindex != 0)
        self.print_thread = threading.Thread(target = self._print,
                                             kwargs = {"resuming": resuming})
        self.print_thread.start()
        return True

    def cancelprint(self):
        self.pause()
        self.paused = False
        self.mainqueue = None
        self.clear = True

    # run a simple script if it exists, no multithreading
    def runSmallScript(self, filename):
        if filename is None: return
        f = None
        try:
            with open(filename) as f:
                for i in f:
                    l = i.replace("\n", "")
                    l = l[:l.find(";")]  # remove comments
                    self.send_now(l)
        except:
            pass

    def pause(self):
        """Pauses the print, saving the current position.
        """
        if not self.printing: return False
        self.paused = True
        self.printing = False

        # try joining the print thread: enclose it in try/except because we
        # might be calling it from the thread itself
        try:
            self.print_thread.join()
        except RuntimeError, e:
            if e.message == "cannot join current thread":
                pass
            else:
                self.logError(traceback.format_exc())
        except:
Example #34
0
class MTRF64Adapter(object):
    _packet_size = 17
    _serial = None
    _read_thread = None
    _command_response_queue = Queue()
    _incoming_queue = Queue()
    _send_lock = Lock()
    _listener_thread = None
    _listener = None
    _is_released = False

    def __init__(self, port: str, on_receive_data=None):
        self._serial = Serial(baudrate=9600)
        self._serial.port = port
        self._serial.open()

        self._listener = on_receive_data

        self._read_thread = Thread(target=self._read_loop)
        self._read_thread.daemon = True
        self._read_thread.start()

        self._listener_thread = Thread(target=self._read_from_incoming_queue)
        self._listener_thread.daemon = True
        self._listener_thread.start()

    def release(self):
        self._is_released = True
        self._serial.close()
        self._incoming_queue.put(None)
        self._listener = None

    def send(self, data: OutgoingData) -> [IncomingData]:
        responses = []

        packet = self._build(data)
        with self._send_lock:
            _LOGGER.debug("Send:\n - request: {0},\n - packet: {1}".format(
                data, packet))
            self._command_response_queue.queue.clear()
            self._serial.write(packet)

            try:
                while True:
                    response = self._command_response_queue.get(timeout=2)
                    responses.append(response)
                    if response.count == 0:
                        break

            except Empty as err:
                _LOGGER.error("Error receiving response: {0}.".format(err))

            # For NooLite.TX we should make a bit delay. Adapter send the response without waiting until command was delivered.
            # So if we send new command until previous command was sent to module, adapter will ignore new command. Note:
            if data.mode == Mode.TX or data.mode == Mode.RX:
                sleep(0.2)

        return responses

    # Private
    def _crc(self, data) -> int:
        sum = 0
        for i in range(0, len(data)):
            sum = sum + data[i]
        sum = sum & 0xFF
        return sum

    def _build(self, data: OutgoingData) -> bytes:
        format_begin = Struct(">BBBBBBB4sI")
        format_end = Struct("BB")

        packet = format_begin.pack(171, data.mode, data.action, 0,
                                   data.channel, data.command, data.format,
                                   data.data, data.id)
        packet_end = format_end.pack(self._crc(packet), 172)

        packet = packet + packet_end

        return packet

    def _parse(self, packet: bytes) -> IncomingData:
        if len(packet) != self._packet_size:
            raise IncomingDataException("Invalid packet size: {0}".format(
                len(packet)))

        format = Struct(">BBBBBBB4sIBB")

        data = IncomingData()
        start_byte, data.mode, data.status, data.count, data.channel, data.command, data.format, data.data, data.id, crc, stop_byte = format.unpack(
            packet)

        if (start_byte != 173) or (stop_byte != 174) or (crc != self._crc(
                packet[0:-2])):
            raise IncomingDataException("Invalid response")

        return data

    def _read_loop(self):
        while True:
            packet = self._serial.read(self._packet_size)

            if self._is_released:
                break

            try:
                data = self._parse(packet)
                _LOGGER.debug("Receive:\n - packet: {0},\n - data: {1}".format(
                    packet, data))

                if data.mode == Mode.TX or data.mode == Mode.TX_F:
                    self._command_response_queue.put(data)
                elif data.mode == Mode.RX or data.mode == Mode.RX_F:
                    self._incoming_queue.put(data)
                else:
                    pass

            except IncomingDataException as err:
                _LOGGER.error("Packet error: {0}".format(err))
                pass

    def _read_from_incoming_queue(self):
        while True:
            input_data = self._incoming_queue.get()

            if self._is_released:
                break

            if self._listener is not None:
                self._listener(input_data)
Example #35
0
    print(ser.readline())
    ser.write("AT+RB".encode())
    print(ser.readline())
    ser.write("AT+RC".encode())
    print(ser.readline())
    ser.write("AT+RF".encode())
    print(ser.readline())
    ser.write("AT+RP".encode())
    print(ser.readline())

    ser.write("AT".encode())
    print(ser.readline())


# initializeAntenna()
ser.close()
currentBaud = int(antennaConfig["baud"])
ser = Serial("/dev/ttyS0", currentBaud)

newMessage = False
id = 0
payload = []


def quit(_,__):
    killThreads.set()
    thrd.join()
    exit(0)


def sendSerial():
class Uart:
    class Receiver(Thread, IMqttConnector):
        def __init__(self, handle):
            super().__init__()
            self.__running = True
            self.__handle: Serial = handle

            # MQTT
            self.__mqtt = MqttClient(self, "127.0.0.1", [], "UART")
            self.__topic = ""

            # enOcean packet
            self.__packet = {}
            self.__rawPacket = []
            self.__syncByte = "55"
            self.__byte = ""
            self.__uniqueID = "00:00:00:00"
            self.__dataLength = 0
            self.__RORG = "f6"
            self.start()

        def Receive(self, server, topic: str, payload: bytes):
            pass

        def Connected(self, server):
            pass

        def Acknowledge(self, server, messageId: int):
            pass

        def Send(self, topics, msg):

            if msg[6] == "f6":
                jsonMsg = {
                    'packet': {
                        'header': {
                            'syncByte': msg[0],
                            'dataLength': msg[1] + msg[2],
                            'optionalDataLength': msg[3],
                            'packetType': msg[4],
                            'CRC8H': msg[5]
                        },
                        'data': {
                            'RORG': msg[6],
                            'data': msg[7],
                            'senderID': msg[8] + msg[9] + msg[10] + msg[11],
                            'status': msg[12]
                        },
                        'optionalData': {
                            'subTelNum': msg[13],
                            'destinationID':
                            msg[14] + msg[15] + msg[16] + msg[17],
                            'dBm': msg[18],
                            'securityLevel': msg[19],
                            'CRC8D': msg[20]
                        }
                    }
                }

            if msg[6] == "a5":
                jsonMsg = {
                    'packet': {
                        'header': {
                            'syncByte': msg[0],
                            'dataLength': msg[1] + msg[2],
                            'optionalDataLength': msg[3],
                            'packetType': msg[4],
                            'CRC8H': msg[5]
                        },
                        'data': {
                            'RORG': msg[6],
                            'DB3': msg[7],
                            'DB2': msg[8],
                            'DB1': msg[9],
                            'DB0': msg[10],
                            'senderID': msg[11] + msg[12] + msg[13] + msg[14],
                            'status': msg[15]
                        },
                        'optionalData': {
                            'subTelNum': msg[16],
                            'destinationID':
                            msg[17] + msg[18] + msg[19] + msg[20],
                            'dBm': msg[21],
                            'securityLevel': msg[22],
                            'CRC8D': msg[23]
                        }
                    }
                }
            # print(jsonMsg)
            jsonMsg = json.dumps(jsonMsg)
            self.__mqtt.sendMessage(self.__topic, jsonMsg)

        def run(self) -> None:
            while self.__running:
                self.__byte = (self.__handle.read(1).hex())
                # Check for SyncByte
                if self.__byte == self.__syncByte:

                    # Start saving packet with sync byte
                    self.__rawPacket.append(self.__byte)

                    # Add the header of the packet
                    for x in range(0, 5):
                        self.__rawPacket.append(self.__handle.read(1).hex())

                    self.__dataLength = int(
                        self.__rawPacket[1] + self.__rawPacket[2], 16)

                    for x in range(0, self.__dataLength):
                        self.__rawPacket.append(self.__handle.read(1).hex())
                    self.__RORG = self.__rawPacket[6]

                    for x in range(0, 8):
                        self.__rawPacket.append(self.__handle.read(1).hex())

                    # Extract uniqueID for packet
                    if self.__RORG == "f6":
                        self.__uniqueID = self.__rawPacket[8]
                        self.__uniqueID += self.__rawPacket[9]
                        self.__uniqueID += self.__rawPacket[10]
                        self.__uniqueID += self.__rawPacket[11]

                    if self.__RORG == "a5":
                        self.__uniqueID = self.__rawPacket[11]
                        self.__uniqueID += self.__rawPacket[12]
                        self.__uniqueID += self.__rawPacket[13]
                        self.__uniqueID += self.__rawPacket[14]

                    print("[UART] Receiving enOcean packet from : " +
                          self.__uniqueID)

                    self.__topic = "enocean/device/id/{}".format(
                        self.__uniqueID)

                    # Send packet to topics with uniqueID
                    self.Send(self.__topic, self.__rawPacket)

                self.__rawPacket.clear()

        def Stop(self):
            print("[UART] Serial line closed")
            self.__running = False
            self.__handle.cancel_read()

    def __init__(self):
        self.__SerialPortName = "/dev/ttyAMA0"
        self.__SerialPortSpeed = "57600"
        self.__handle = Serial(self.__SerialPortName,
                               self.__SerialPortSpeed,
                               timeout=2.0)
        print(("[UART] Serial line {} @ {} bauds opened".format(
            self.__SerialPortName, self.__SerialPortSpeed)))
        self.__thread: Uart.Receiver = self.Receiver(self.__handle)

    def __del__(self):
        self.Stop()
        self.__handle.close()

    def Stop(self):
        self.__thread.Stop()
Example #37
0
class Polytec(Instrument):
    """The polytec class"""
    def __init__(self, config, plotter):
        """Constructor"""
        Instrument.__init__(self, config, plotter)
        self._serial = None
        self._signal = None
        self.min_used = None
        self.max_used = None

    def config(self, metadata, total_updates):
        """Configure the vibrometer.

        :param metadata: experiment metadata
        :type metadata: dict

        :param total_updates: number of updates for the experiment
        :type total_updates: int
        """
        name = self.__class__.__name__
        self._serial = Serial(
            port=PlaceConfig().get_config_value(name, "port"),
            baudrate=PlaceConfig().get_config_value(name, "baudrate"),
            timeout=10,
            parity=serial.PARITY_NONE,
            stopbits=serial.STOPBITS_ONE,
            bytesize=serial.EIGHTBITS)

        if self._config['dd_300']:
            self._setup_decoder(metadata, 'dd_300')

        if self._config['dd_900']:
            self._setup_decoder(metadata, 'dd_900')

        if self._config['vd_08']:
            self._setup_decoder(metadata, 'vd_08')

        if self._config['vd_09']:
            self._setup_decoder(metadata, 'vd_09')

        if self._config['autofocus'] == 'custom':
            curr_set = self._write_and_readline(
                'GetDevInfo,SensorHead,0,Focus\n')
            curr_min, curr_max = ast.literal_eval(curr_set)
            self.min_used = max(curr_min, self._config['area_min'])
            self.max_used = min(curr_max, self._config['area_max'])
            metadata['actual_area_min'] = self.min_used
            metadata['actual_area_max'] = self.max_used

    def update(self, update_number, progress):
        """Update the vibrometer.

        :param update_number: the count of the current update (0-indexed)
        :type update_number: int

        :param progress: a dictionary of values passed back to your Elm app
        :type progress: dict

        :returns: an array containing the signal level
        :rtype: numpy.array dtype='uint64'
        """
        if self._config['autofocus'] != 'none':
            if update_number == 0 or self._config[
                    'autofocus_everytime'] is True:
                self._autofocus_vibrometer(span=self._config['autofocus'],
                                           timeout=self._config['timeout'])
        signal_level = self._get_signal_level()
        field = '{}-signal'.format(self.__class__.__name__)
        data = np.array([(signal_level, )], dtype=[(field, 'uint64')])
        if self._config['plot']:
            self._draw_plot(signal_level, update_number, progress)
        return data

    def cleanup(self, abort=False):
        """Closes the serial port to the Polytec.

        :param abort: indicates that the experiment is being aborted and is unfinished
        :type abort: bool
        """
        if abort is False:
            self._serial.close()


# PRIVATE METHODS

    def _write(self, message):
        """Send a message

        :param message: message to be sent to the Polytec receiver
        :type message: str
        """
        self._serial.write(message.encode())

    def _write_and_readline(self, message):
        """Send a message and get a response.

        :param message: message to be sent to the Polytec receiver
        :type message: str

        :returns: the decoded response
        :rtype: str
        """
        self._write(message)
        return self._serial.readline().decode('ascii', 'replace')

    def _setup_decoder(self, metadata, name):
        """Set the range for the decoder and obtain metadata

        :param metadata: experiment metadata
        :type metadata: dict

        :param name: the name to use for the decoder
        :type name: str
        """
        id_ = PlaceConfig().get_config_value(self.__class__.__name__, name)
        self._set_range(id_, self._config[name + '_range'])
        if name == 'vd_08' or name == 'vd_09':
            metadata[name + '_time_delay'] = self._get_delay(id_)
            metadata[name +
                     '_maximum_frequency'] = self._get_maximum_frequency(id_)

    def _autofocus_vibrometer(self, span='Full', timeout=30):
        """Autofocus the vibrometer.

        :param span: the range in which the vibrometer should look for focus
        :type span: str

        :param timeout: the number of seconds to wait for focus before failing
        :type timeout: int

        :raises RuntimeError: if focus is not found before timeout
        """

        if self._config['autofocus'] == 'custom':
            self._write('Set,SensorHead,0,AutoFocusArea,{},{}\n'.format(
                self.min_used, self.max_used))
        else:
            self._write('Set,SensorHead,0,AutoFocusSpan,' + span + '\n')

        self._write('Set,SensorHead,0,AutoFocus,Search\n')
        countdown = timeout
        tick = 1
        while countdown > 0:
            sleep(tick)
            countdown -= tick
            if self._write_and_readline(
                    'Get,SensorHead,0,AutoFocusResult\n') == 'Found\n':
                break
        else:
            raise RuntimeError('autofocus failed')

    def _get_delay(self, id_):
        """Get time delay.

        :param id_: the identification string for the decoder
        :type id_: str

        :returns: the delay time
        :rtype: float
        """
        delay_string = self._write_and_readline('Get,' + id_ +
                                                ',SignalDelay\n')
        return float(re.findall(_NUMBER, delay_string)[0])

    def _get_maximum_frequency(self, id_):
        """Get the maximum frequency.

        :param id_: the identification string for the decoder
        :type id_: str

        :returns: the frequency value of the selected decoder
        :rtype: float

        :raises ValueError: if maximum frequency is not available
        """
        frequency_string = self._write_and_readline('Get,' + id_ +
                                                    ',MaxFreq\n')
        if frequency_string == 'Not Available':
            raise ValueError(
                'maximum frequency for {} not available'.format(id_))
        return _parse_frequency(frequency_string)

    def _get_range(self, name, id_):
        """Get the current range.

        :param name: the name for the decoder
        :type name: str

        :param id_: the identification string for the decoder
        :type id_: str

        :returns: the range value and units returned from the instrument
        :rtype: float, string

        :raises ValueError: if decoder name is not recognized
        """
        decoder_range = self._write_and_readline('Get,' + id_ + ',Range\n')
        if name == 'dd_300':
            range_num = re.findall(_NUMBER, self._config['dd_300_range'])
        elif name == 'dd_900':
            raw_num = re.findall(_NUMBER, self._config['dd_900_range'])
            range_num = [string.replace('um', 'µm') for string in raw_num]
        elif name == 'vd_08':
            range_num = re.findall(_NUMBER, self._config['vd_08_range'])
        elif name == 'vd_09':
            range_num = re.findall(_NUMBER, self._config['vd_09_range'])
        else:
            raise ValueError('unknown decoder: ' + name)
        del_num_r = len(range_num) + 1
        calib = float(range_num[0])
        calib_unit = decoder_range[del_num_r:].lstrip()
        return calib, calib_unit

    def _set_range(self, id_, range_):
        """Set the range.

        :param id_: the identification string for the decoder
        :type id_: str

        :param range_: the desired decoder range
        :type range_: str
        """
        self._write('Set,' + id_ + ',Range,' + range_ + '\n')

    def _get_signal_level(self):
        return int(self._write_and_readline('Get,SignalLevel,0,Value\n'))

    def _draw_plot(self, signal_level, update_number, progress):
        if update_number == 0:
            self._signal = [signal_level]
        else:
            self._signal.append(signal_level)
        title = 'Signal level at each PLACE update'
        self.plotter.view(title, [
            self.plotter.line(
                self._signal, color='purple', shape='cross', label='signal')
        ])
class LX16AServos():

    _released = False

    SerialPort = None

    _shutingDown = False

    CMD_START_BYTE = 0x55
    CMD_SERVO_MOVE_TIME_WRITE_BYTE = 1
    CMD_READ_DATA_BYTE = 3
    CMD_TEMP_READ_BYTE = 26
    CMD_VOLT_READ_BYTE = 27
    CMD_POS_READ_BYTE = 28
    CMD_LOAD_OR_UNLOAD_WRITE = 31

    TX_DELAY_TIME = 0.00002
    _readWaitTime1 = 0.001
    _readWaitTime2 = 0.001

    def __init__(self):
        self.SerialPort = Serial("/dev/ttyUSB0", baudrate=115200)
        self.SerialPort.setDTR(1)

    def checksumWithLength(self, id, byteArry):
        check = id + len(byteArry) + 2
        for val in byteArry:
            check = check + val
        check = bytes([(~(check)) & 0xff])
        return check[0]

    def checksum(self, id, byteArry):
        check = id
        for val in byteArry:
            check = check + val
        check = bytes([(~(check)) & 0xff])
        return check[0]

    def MoveServo(self, id, speed, position):

        if (self._shutingDown == True):
            return False

        if (position < 0):
            position = 0
        if (position > 1000):
            position = 1000
        if (speed < 0):
            speed = 0
        if (speed > 10000):
            speed = 10000

        p = [position & 0xff, position >> 8]
        s = [speed & 0xff, speed >> 8]

        command = bytes(
            [self.CMD_SERVO_MOVE_TIME_WRITE_BYTE, p[0], p[1], s[0], s[1]])

        self.SerialPort.write(
            bytes([
                self.CMD_START_BYTE, self.CMD_START_BYTE, id,
                len(command) + 2
            ]))
        self.SerialPort.write(command)
        self.SerialPort.write(bytes([self.checksumWithLength(id, command)]))

        sleep(self.TX_DELAY_TIME)
        return True

    def SetServoPower(self, id, on):
        value = 0
        if (on == True):
            value = 1

        command = bytes([self.CMD_LOAD_OR_UNLOAD_WRITE, value])

        self.SerialPort.write(
            bytes([
                self.CMD_START_BYTE, self.CMD_START_BYTE, id,
                len(command) + 2
            ]))
        self.SerialPort.write(command)
        self.SerialPort.write(bytes([self.checksumWithLength(id, command)]))

        sleep(self.TX_DELAY_TIME)
        return True

    def ReadTemperature(self, id):

        if (self._shutingDown == True):
            return False

        self.SerialPort.flushInput()

        command = bytes([self.CMD_READ_DATA_BYTE, self.CMD_TEMP_READ_BYTE])

        self.SerialPort.write(
            bytes([self.CMD_START_BYTE, self.CMD_START_BYTE, id]))
        self.SerialPort.write(command)
        self.SerialPort.write(bytes([self.checksum(id, command)]))

        sleep(self.TX_DELAY_TIME)

        sleep(0.1)
        retry = 0
        while retry < 100:
            if (self.SerialPort.inWaiting() > 0):
                value = self.SerialPort.read(1)
                if value != '':
                    for pos in range(0, 7):
                        if pos == 5:
                            tempture = int(ord(value))
                            return tempture
                        value = self.SerialPort.read(1)
            retry += 1
            sleep(0.1)
        print("Servo " + str(id) + " not responding!")
        return -1

    def ReadVolt(self, id, showError=True):

        if (self._shutingDown == True):
            return False

        self.SerialPort.flushInput()

        command = bytes([self.CMD_READ_DATA_BYTE, self.CMD_VOLT_READ_BYTE])

        self.SerialPort.write(
            bytes([self.CMD_START_BYTE, self.CMD_START_BYTE, id]))
        self.SerialPort.write(command)
        self.SerialPort.write(bytes([self.checksum(id, command)]))

        sleep(0.1)
        retry = 0
        while retry < 100:
            if (self.SerialPort.inWaiting() > 0):
                value = self.SerialPort.read(1)
                if value != '':
                    for pos in range(0, 8):
                        if pos == 5:
                            volt1 = int(ord(value))
                        if pos == 6:
                            volt2 = int(ord(value))
                            volt2 = volt1 + 256 * volt2
                            return volt2
                        value = self.SerialPort.read(1)
            retry += 1
            sleep(0.1)

        if (showError == True):
            print("Servo " + str(id) + " not responding!")
        return -1

    def ShutDown(self, ids):
        self._shutingDown = True
        for id in ids:
            print("shutting down servo " + str(id))
            self.SetServoPower(id, False)

    def ReadPos(self, id, showError=True):

        if (self._shutingDown == True):
            return False

        self.SerialPort.flushInput()

        command = bytes([self.CMD_READ_DATA_BYTE, self.CMD_POS_READ_BYTE])

        self.SerialPort.write(
            bytes([self.CMD_START_BYTE, self.CMD_START_BYTE, id]))
        self.SerialPort.write(command)
        self.SerialPort.write(bytes([self.checksum(id, command)]))

        sleep(0.001)

        retry = 0
        while retry < 100:
            if (self.SerialPort.inWaiting() > 0):
                value = self.SerialPort.read(1)
                if value != '':
                    for pos in range(0, 8):
                        if pos == 5:
                            pos1 = int(ord(value))
                        if pos == 6:
                            pos2 = int(ord(value))
                            pos2 = pos1 + 256 * pos2
                            return pos2
                        if (self.SerialPort.inWaiting() == 0):
                            sleep(self._readWaitTime1)
                        if (self.SerialPort.inWaiting() > 0):
                            value = self.SerialPort.read(1)
                        else:
                            print("Servo " + str(id) + " value loss!")
            retry += 1
            sleep(self._readWaitTime2)

        if (showError == True):
            print("Servo " + str(id) + " not responding!")
        return -1

    def Release(self):
        if (self._released == False):
            self.SerialPort.close()

    def __del__(self):
        self.Release()
class PiAnywhere():

    MAX_UART_BUFFER = 128

    def __init__(self):
        self.uart = Serial("/dev/ttyS0")
        self.uart.baudrate = 9600
        self.uart.timeout = 1

    def __exit__(self):
        self.uart.close()

    def send_command(self, command):
        self.uart.write(command)
        response = self.uart.read(MAX_UART_BUFFER)
        return response

    def send_command_with_check(self, command, check):
        if not (command.startswith(("AT+", "PI+"))):
            raise PIANYWHERE_BAD_COMMAND()

        self.uart.write(command.append("/r/n"))
        response = self.uart.read(self.MAX_UART_BUFFER)

        if (check in response):
            return true
        elif ("ERROR" in response):
            raise PIANYWHERE_ERROR_RESPONSE()
        elif ("NO CARRIER" in response):
            raise PIANYWHERE_NO_CARRIER()
        elif ("BUFFER OVERFLOW" in response):
            raise PIANYWHERE_BUFFER_OVERFLOW()
        else:
            raise PIANYWHERE_BAD_RESPONSE()

    def add_sms_responder(self, number):
        return self.send_command_with_check("PI+SETRESPONDER=%s" % number,
                                            "OK")

    def remove_sms_responder(self, number):
        return self.send_command_with_check("PI+UNSETRESPONDER=%s" % number,
                                            "OK")

    def clear_sms_responders(self):
        return self.send_command_with_check("PI+CLEARRESPONDERS", "OK")

    def send_sms_message(self, number, message):
        self.send_command_with_check("AT+", "OK")

    def get_all_sms_messages(self):
        self.send_command_with_check("AT+", "OK")

    def get_unread_sms_messages(self):
        self.send_command_with_check("AT+", "OK")

    def get_sms_message(self, id):
        self.send_command_with_check("AT+", "OK")

    def set_wake_datetime(self, datetime):
        self.send_command_with_check("PI+WAKEON=%s" % datetime, "OK")

    def set_sleep_datetime(self, datetime):
        self.send_command_with_check("PI+SLEEPON=%s" % datetime, "OK")

    def get_pianywhere_date(self):
        datetime = send_command_with_check("PI+DATETIME", "OK")
        return time.strptime(datetime, '%b %d %Y %I:%M%p')

    def powerkey_modem(self):
        self.send_command_with_check("AT+", "OK")

    def reset_modem(self):
        self.send_command_with_check("AT+", "OK")
Example #40
0
    def doFlashTasmota(self, room: str, espType: str, siteId: str):
        port = self.findUSBPort(timeout=60)
        if port:
            self.MqttManager.say(text=self.TalkManager.randomTalk(
                'usbDeviceFound', module='AliceCore'),
                                 client=siteId)
            try:
                mac = ESPLoader.detect_chip(port=port, baud=115200).read_mac()
                mac = '%s' % (':'.join(map(lambda x: '%02x' % x, mac)))
                cmd = list()
                cmd.append('--port')
                cmd.append(port)
                cmd.append('--baud')
                cmd.append('115200')
                cmd.append('--after')
                cmd.append('no_reset')
                cmd.append('write_flash')
                cmd.append('--flash_mode')
                cmd.append('dout')
                cmd.append('0x00000')
                cmd.append('sonoff.bin')
                cmd.append('--erase-all')
                esptool.main(cmd)
            except Exception as e:
                self._logger.error(
                    f'[{self.name}] Something went wrong flashing esp device: {e}'
                )
                self.MqttManager.say(text=self.TalkManager.randomTalk(
                    'espFailed', module='AliceCore'),
                                     client=siteId)
                self._broadcastFlag.clear()
                return
        else:
            self.MqttManager.say(text=self.TalkManager.randomTalk(
                'noESPFound', module='AliceCore'),
                                 client=siteId)
            self._broadcastFlag.clear()
            return

        self._logger.info(f'[{self.name}] Tasmota flash done')
        self.MqttManager.say(text=self.TalkManager.randomTalk(
            'espFlashedUnplugReplug', module='AliceCore'),
                             client=siteId)
        found = self.findUSBPort(timeout=60)
        if found:
            self.MqttManager.say(text=self.TalkManager.randomTalk(
                'espFoundReadyForConf', module='AliceCore'),
                                 client=siteId)
            time.sleep(10)
            uid = self._getFreeUID(mac)
            tasmotaConfigs = TasmotaConfigs(deviceType=espType, uid=uid)
            confs = tasmotaConfigs.getBacklogConfigs(room)
            if not confs:
                self._logger.error(
                    f'[{self.name}] Something went wrong getting tasmota configuration'
                )
                self.MqttManager.say(text=self.TalkManager.randomTalk(
                    'espFailed', module='AliceCore'),
                                     client=siteId)
            else:
                serial = Serial()
                serial.baudrate = 115200
                serial.port = port
                serial.open()

                try:
                    for group in confs:
                        cmd = ';'.join(group['cmds'])
                        if len(group['cmds']) > 1:
                            cmd = f'Backlog {cmd}'

                        arr = list()
                        if len(cmd) > 50:
                            while len(cmd) > 50:
                                arr.append(cmd[:50])
                                cmd = cmd[50:]
                            arr.append(f'{cmd}\r\n')
                        else:
                            arr.append(f'{cmd}\r\n')

                        for piece in arr:
                            serial.write(piece.encode())
                            self._logger.info('[{}] Sent {}'.format(
                                self.name, piece.replace('\r\n', '')))
                            time.sleep(0.5)

                        time.sleep(group['waitAfter'])

                    serial.close()
                    self._logger.info(
                        f'[{self.name}] Tasmota flashing and configuring done')
                    self.MqttManager.say(text=self.TalkManager.randomTalk(
                        'espFlashingDone', module='AliceCore'),
                                         client=siteId)
                    self.addNewDevice(espType, room, uid)
                    self._broadcastFlag.clear()

                except Exception as e:
                    self._logger.error(
                        f'[{self.name}] Something went wrong writting configuration to esp device: {e}'
                    )
                    self.MqttManager.say(text=self.TalkManager.randomTalk(
                        'espFailed', module='AliceCore'),
                                         client=siteId)
                    self._broadcastFlag.clear()
                    serial.close()
        else:
            self.MqttManager.say(text=self.TalkManager.randomTalk(
                'espFailed', module='AliceCore'),
                                 client=siteId)
            self._broadcastFlag.clear()
            return
Example #41
0
class TestSuite():
    '''Class representing the ImageProc test suite'''

    def __init__(self, dev_name, baud_rate=230400, dest_addr='\xff\xff'):
        '''
        Description:
        Initiate the 802.15.4 connection and configure the target.
        Class must be instantiated with a connection name. On Windows this is
        typically of the form "COMX". On Mac, the serial device connection
        string is typically '/dev/tty.DEVICE_NAME-SPP-(1)' where the number at
        the end is optional depending on the version of the OS.


        Inputs:
            dev_name: The device name to connect to. Examples are COM5 or
                      /dev/tty.usbserial.
                print ord(datum)
        '''
        if dev_name == "" or dev_name == None:
            print "You did not instantiate the class with a device name " + \
                    "(eg. COM5, /dev/tty.usbserial)."
            sys.exit(1)

        if dest_addr == '\xff\xff':
            print "Destination address is set to broadcast. You will " +\
                    "interfere with other 802.15.4 devices in the area." +\
                    " To avoid interfering, instantiate the class with a " +\
                    "destination address explicitly."

        self.dest_addr = dest_addr
        self.last_packet = None

        try:
            self.conn = Serial(dev_name, baudrate=baud_rate, rtscts=True)
            if self.conn.isOpen():
                self.radio = XBee(self.conn, callback=self.receive)
                print "Radio opened:" + str(dev_name)
                pass
            else:
                raise SerialException('')
        except (AttributeError, SerialException):
            print "Unable to open a connection to the target. Please" + \
                  "  verify your basestation is enabled and properly configured."
            raise

    def set_dest_addr(self, dest_addr):
        self.dest_addr = dest_addr

    def check_conn(self):
        '''
        Description:
            A simple utility function for checking the status of the
            connection.
        '''
        if self.conn == None or not self.conn.isOpen():
            print 'The connection to the target appears to be closed.'
            return False
        else:
            return True

    def receive(self, packet):
        self.last_packet = packet
        rf_data = packet.get('rf_data')
        typeID = ord(rf_data[1])
        print "got packet type " + str(typeID)
        if typeID == kTestAccelCmd or typeID == kTestGyroCmd:
            self.print_gyro(self.last_packet)
        elif typeID == kTestDFlashCmd:
            print ''.join(rf_data[2:])
#            print rf_data[2:]
#            print map(ord,rf_data[2:])
#            print map(str,rf_data[2:])
        elif typeID == kTestMotorCmd:
            print ''.join(rf_data[2:])
        elif typeID == kTestHallCmd:
            self.print_hall(self.last_packet)
#        elif typeID == kTestRadioCmd:
#            self.print_packet(self.last_packet)

    def test_radio(self):
        '''
        Description:
            This test sends command packets to the target requesting
            the results of a radio test. The results should be the
            receipt of three packets. The payloads of those three packets
            should print as consecutive integers 0-9, 10-19, and 20-29
            respectively.
        '''

        header = chr(kStatusUnused) + chr(kTestRadioCmd)
        for i in range(1, 3):
            data_out = header + ''.join([str(datum) for datum in range((i-1)*10,i*10)])
            print("\nTransmitting packet " + str(i) + "...")
            print map(str,data_out[2:])
            print data_out[2:]
            if(self.check_conn()):
                self.radio.tx(dest_addr=self.dest_addr, data=data_out)
                time.sleep(0.1) # possible over run of packets?
                self.print_packet(self.last_packet)
            time.sleep(1)

############
    def test_gyro(self, num_test_packets):
        '''
        Description:
            Read the XYZ values from the gyroscope.
        '''
        data_out = chr(kStatusUnused) + chr(kTestGyroCmd) + chr(num_test_packets)
        if self.check_conn():
            self.radio.tx(dest_addr=self.dest_addr, data=data_out)
            time.sleep(num_test_packets * 0.5)

#################
    def test_accel(self, num_test_packets):
        '''
        Description:
            Read the XYZ values from the accelerometer.
        '''
        data_out = chr(kStatusUnused) + chr(kTestAccelCmd) + chr(num_test_packets)
        packets_received = 0
        prev_data = None
        if(self.check_conn()):
            self.radio.tx(dest_addr=self.dest_addr, data=data_out)
            time.sleep(num_test_packets * 0.5)

###############
    def test_hall(self, num_test_packets):
        '''
        Description:
            Read the position values from the Hall angle sensors.
        '''
        data_out = chr(kStatusUnused) + chr(kTestHallCmd) + chr(num_test_packets)
        if self.check_conn():
            self.radio.tx(dest_addr=self.dest_addr, data=data_out)
            time.sleep(num_test_packets * 0.5)

################
    def test_dflash(self):
        '''
        Description:
            Read out a set of strings that have been written to and read from
            memory.
        '''
        data_out = chr(kStatusUnused) + chr(kTestDFlashCmd)
        if(self.check_conn()):
            self.radio.tx(dest_addr=self.dest_addr, data=data_out)
            time.sleep(1)
            
####################
    def test_motor(self, motor_id,duty_cycle):
        '''
        Description:
            Turn on a motor.
        Parameters:
            motor_id    : The motor number to turn on
            time        : The amount of time to turn the motor on for (in
                          milliseconds)
            duty_cycle  : The duty cycle of the PWM signal used to control the
                          motor in -4000 < dc < 4000
            direction   : The direction to spin the motor. There are *three*
                          options for this parameter. 0 - reverse, 1 - forward,
                          2 high impedance motor controller output = braking
            return_emf  : Send the back emf readings over the radio channel.
        '''
        duration = 500; # time in milliseconds
        data_out = chr(kStatusUnused) + chr(kTestMotorCmd) + \
                   pack('3h', motor_id, duration, duty_cycle)
        print "testing motor " + str(motor_id)           
        if(self.check_conn()):
            self.radio.tx(dest_addr=self.dest_addr, data=data_out)
            time.sleep(1)
            
###########
    def test_sma(self, chan_id, time, duty_cycle):
        '''
        Description:
            Turn on an SMA
        Parameters:
            chan_id     : The SMA channel to turn on
            time        : The amount of time to turn the SMA on for (in
                          seconds)
            duty_cycle  : The duty cycle of the PWM signal used to control the
                          SMA in percent (0 - 100)
        '''

        if(duty_cycle < 0 or duty_cycle > 100):
            print("You entered an invalid duty cycle.")
            return

        data_out = chr(kStatusUnused) + chr(kTestSMACmd) + chr(chan_id) + \
                   chr(time) + chr(duty_cycle)

        if(self.check_conn()):
            self.radio.tx(dest_addr=self.dest_addr, data=data_out)


    def print_packet(self, packet):
        '''
        Description:
            Print the contents of a packet to the screen. This function
            will primarily be used for debugging purposes. May need to
            replace print with stdio or stderr to accommodate GUI test
            suite.
        '''
        if(packet is not None):
            print("Received the following: ")
            print("RSSI: " + str(ord(packet.get('rssi'))))
            (src_h, src_l) = unpack('cc', packet.get('source_addr'))
            print("Source Address: 0x%.2X 0x%.2X" % (ord(src_h),
                  ord(src_l)))
            print("ID: " + (packet.get('id')))
            print("Options: " + str(ord(packet.get('options'))))
            rf_data = packet.get('rf_data')
            print("Status Field: " + str(ord(rf_data[0])))
            print("Type Field: " + str(ord(rf_data[1])))
  #          print("Payload Data: " + ''.join([str(ord(i)) for i in rf_data[2:]]))
            print "Payload Data: " 
            print map(ord,rf_data[2:])
  #          print("Payload" + rf_data[2:])
            print map(str,rf_data[2:])
  #          print(map(chr,rf_data))

# gyro packet :  int xl_data[3]; int gyro_data[3]; int temp;
    def print_gyro(self, packet):
        rf_data = packet.get('rf_data')
#        print "length of data " + str(len(rf_data[2:]))
        print "xl data:" + str(map(hex,unpack('3h',rf_data[2:8])))
        print "gyro data:" + str(map(hex,unpack('3h',rf_data[8:14])))
        print "temperature:" + str(map(hex,unpack('1h',rf_data[14:16])))
#        print map(hex,unpack('7h',rf_data[2:]))

# Austria Microsystems Hall angle sensor packet:
# int pos; long oticks; int calibPOS; int offset;
    def print_hall(self,packet):
        rf_data = packet.get('rf_data')
        index = 0
        for i in range(1,3):
            print "Hall encoder:" + str(i-1)
            print "position" + str(map(hex,unpack('1h',rf_data[index+2:index+4]))) + \
                " revolutions" + str(map(hex,unpack('1i',rf_data[index+4:index+8])))
            print "cal. pos and offset" + \
                  str(map(hex,unpack('2h',rf_data[index+8:index+12])))
            index = index + 10
        print " "

    def __del__(self):
        '''
        Description:
            Clean up the connection when the object is deleted.
        '''
        self.radio.halt()
        self.conn.close()
class SerialConnectorPrimitive(ConnectorPrimitive):
    def __init__(self, name, port, baudrate, config):
        ConnectorPrimitive.__init__(self, name)
        self.port = port
        self.baudrate = int(baudrate)
        self.timeout = 0.01  # 10 milli sec
        self.config = config
        self.target_id = self.config.get('target_id', None)
        self.polling_timeout = config.get('polling_timeout', 60)
        self.forced_reset_timeout = config.get('forced_reset_timeout', 1)
        self.skip_reset = config.get('skip_reset', False)
        self.serial = None

        # Values used to call serial port listener...

        # Check if serial port for given target_id changed
        # If it does we will use new port to open connections and make sure reset plugin
        # later can reuse opened already serial port
        #
        # Note: This listener opens serial port and keeps connection so reset plugin uses
        # serial port object not serial port name!
        serial_port = HostTestPluginBase().check_serial_port_ready(self.port, target_id=self.target_id, timeout=self.polling_timeout)
        if serial_port is None:
            raise ConnectorPrimitiveException("Serial port not ready!")

        if serial_port != self.port:
            # Serial port changed for given targetID
            self.logger.prn_inf("serial port changed from '%s to '%s')"% (self.port, serial_port))
            self.port = serial_port

        startTime = time.time()
        self.logger.prn_inf("serial(port=%s, baudrate=%d, timeout=%s)"% (self.port, self.baudrate, self.timeout))
        while time.time() - startTime < self.polling_timeout:
            try:
                # TIMEOUT: While creating Serial object timeout is delibrately passed as 0. Because blocking in Serial.read
                # impacts thread and mutliprocess functioning in Python. Hence, instead in self.read() s delay (sleep()) is
                # inserted to let serial buffer collect data and avoid spinning on non blocking read().
                self.serial = Serial(self.port, baudrate=self.baudrate, timeout=0)
            except SerialException as e:
                self.serial = None
                self.LAST_ERROR = "connection lost, serial.Serial(%s, %d, %d): %s"% (self.port,
                    self.baudrate,
                    self.timeout,
                    str(e))
                self.logger.prn_err(str(e))
                self.logger.prn_err("Retry after 1 sec until %s seconds" % self.polling_timeout)
            else:
                if not self.skip_reset:
                    self.reset_dev_via_serial(delay=self.forced_reset_timeout)
                break
            time.sleep(1)

    def reset_dev_via_serial(self, delay=1):
        """! Reset device using selected method, calls one of the reset plugins """
        reset_type = self.config.get('reset_type', 'default')
        if not reset_type:
            reset_type = 'default'
        disk = self.config.get('disk', None)

        self.logger.prn_inf("reset device using '%s' plugin..."% reset_type)
        result = host_tests_plugins.call_plugin('ResetMethod',
            reset_type,
            serial=self.serial,
            disk=disk,
            target_id=self.target_id)
        # Post-reset sleep
        if delay:
            self.logger.prn_inf("waiting %.2f sec after reset"% delay)
            time.sleep(delay)
        self.logger.prn_inf("wait for it...")
        return result

    def read(self, count):
        """! Read data from serial port RX buffer """
        # TIMEOUT: Since read is called in a loop, wait for self.timeout period before calling serial.read(). See
        # comment on serial.Serial() call above about timeout.
        time.sleep(self.timeout)
        c = str()
        try:
            if self.serial:
                c = self.serial.read(count)
        except SerialException as e:
            self.serial = None
            self.LAST_ERROR = "connection lost, serial.read(%d): %s"% (count, str(e))
            self.logger.prn_err(str(e))
        return c

    def write(self, payload, log=False):
        """! Write data to serial port TX buffer """
        try:
            if self.serial:
                self.serial.write(payload)
                if log:
                    self.logger.prn_txd(payload)
        except SerialException as e:
            self.serial = None
            self.LAST_ERROR = "connection lost, serial.write(%d bytes): %s"% (len(payload), str(e))
            self.logger.prn_err(str(e))
        return payload

    def flush(self):
        if self.serial:
            self.serial.flush()

    def connected(self):
        return bool(self.serial)

    def finish(self):
        if self.serial:
            self.serial.close()

    def __del__(self):
        self.finish()
Example #43
0
def TouchSerialPort(env, port, baudrate):
    s = Serial(port=env.subst(port), baudrate=baudrate)
    s.setDTR(False)
    s.close()
    sleep(0.4)
Example #44
0
class ArduinoSerial(object):
    
    DEFAULT_BAUD = 115200
    _logger = logging.getLogger("ArduinoSerial")

    def __init__(self, port, scalex=1, scaley=1):
        self._serial = Serial()
        self._scale_x = scalex
        self._scale_y = scaley
        self.open(port)

    def _send_gcode(self, gcode):
        if gcode:
            self._logger.debug("sending gcode %s", gcode)
        #gcode += "\n"
        try:
            self._serial.write("%s\r\n" % (gcode,))
            # Wait for grbl response with carriage return
            grbl_out = self._serial.readline().strip()
        except SerialException:
            pass
        else:
            if grbl_out:
                self._logger.debug("recived %s", grbl_out)

    def _go_to(self, point):
        """
        Send a command to the arduino to move the magnet to a specific (x, y)
        """
        self._logger.debug("going to %s", point)
        self._send_gcode("G90X%sY%s" % (point[1] * self._scale_y, point[0] * self._scale_x))

    def _set_magnet_state(self, is_on):
        """
        Send a command to the arduino to activate/deactivate the magnet
        """
        self._logger.debug("turning magnet %s", "on" if is_on else "off")
        self._send_gcode("M4" if is_on else "M3")

    def open(self, port, baud=DEFAULT_BAUD):
        try:
            self._serial = Serial(port=port, baudrate=baud)
            self._serial.open()
        except Exception as e:
            self._logger.error('Failed to open {}'.format(e))
	    return
        self._send_gcode("")
        self._send_gcode("")
        self._logger.info("%s is opened", self._serial.port)

    def close(self):
        self._serial.close()
        self._logger.info("%s is closed", self._serial.port)

    def move(self, points):
        """
        Move a game piece via the given points
        """
        self._logger.info("moving via %s", points)
        # deactivate the magnet for safety before moving
        self._set_magnet_state(False)
        # go to the 'from' piece location
        self._go_to(points.pop(0))
        # activate the magnet for moving
        self._set_magnet_state(True)
        # move via the points (dragging the piece with the magnet)
        for point in points:
            self._go_to(point)
        # deactivate the magnet for safety
        self._set_magnet_state(False)
Example #45
0
class DfuTransportSerial(DfuTransport):

    DEFAULT_BAUD_RATE = 115200
    DEFAULT_FLOW_CONTROL = True
    DEFAULT_TIMEOUT = 30.0  # Timeout time for board response
    DEFAULT_SERIAL_PORT_TIMEOUT = 1.0  # Timeout time on serial port read
    DEFAULT_PRN = 0
    DEFAULT_DO_PING = True

    OP_CODE = {
        'CreateObject': 0x01,
        'SetPRN': 0x02,
        'CalcChecSum': 0x03,
        'Execute': 0x04,
        'ReadError': 0x05,
        'ReadObject': 0x06,
        'GetSerialMTU': 0x07,
        'WriteObject': 0x08,
        'Ping': 0x09,
        'Response': 0x60,
    }

    def __init__(self,
                 com_port,
                 baud_rate=DEFAULT_BAUD_RATE,
                 flow_control=DEFAULT_FLOW_CONTROL,
                 timeout=DEFAULT_TIMEOUT,
                 prn=DEFAULT_PRN,
                 do_ping=DEFAULT_DO_PING):

        super().__init__()
        self.com_port = com_port
        self.baud_rate = baud_rate
        self.flow_control = 1 if flow_control else 0
        self.timeout = timeout
        self.prn = prn
        self.serial_port = None
        self.dfu_adapter = None
        self.ping_id = 0
        self.do_ping = do_ping

        self.mtu = 0
        """:type: serial.Serial """

    def open(self):
        super().open()
        try:
            self.__ensure_bootloader()
            self.serial_port = Serial(port=self.com_port,
                                      baudrate=self.baud_rate,
                                      rtscts=self.flow_control,
                                      timeout=self.DEFAULT_SERIAL_PORT_TIMEOUT)
            self.dfu_adapter = DFUAdapter(self.serial_port)
        except Exception as e:
            raise NordicSemiException("Serial port could not be opened on {0}"
                                      ". Reason: {1}".format(
                                          self.com_port, e.strerror))

        if self.do_ping:
            ping_success = False
            start = datetime.now()
            while (datetime.now() - start < timedelta(seconds=self.timeout)
                   and ping_success == False):
                if self.__ping() == True:
                    ping_success = True

            if ping_success == False:
                raise NordicSemiException(
                    "No ping response after opening COM port")

        self.__set_prn()
        self.__get_mtu()

    def close(self):
        super().close()
        self.serial_port.close()

    def send_init_packet(self, init_packet):
        def try_to_recover():
            if response['offset'] == 0 or response['offset'] > len(
                    init_packet):
                # There is no init packet or present init packet is too long.
                return False

            expected_crc = (binascii.crc32(init_packet[:response['offset']])
                            & 0xFFFFFFFF)

            if expected_crc != response['crc']:
                # Present init packet is invalid.
                return False

            if len(init_packet) > response['offset']:
                # Send missing part.
                try:
                    self.__stream_data(data=init_packet[response['offset']:],
                                       crc=expected_crc,
                                       offset=response['offset'])
                except ValidationException:
                    return False

            self.__execute()
            return True

        response = self.__select_command()
        assert len(
            init_packet) <= response['max_size'], 'Init command is too long'

        if try_to_recover():
            return

        try:
            self.__create_command(len(init_packet))
            self.__stream_data(data=init_packet)
            self.__execute()
        except ValidationException:
            raise NordicSemiException("Failed to send init packet")

    def send_firmware(self, firmware):
        def try_to_recover():
            if response['offset'] == 0:
                # Nothing to recover
                return

            expected_crc = binascii.crc32(
                firmware[:response['offset']]) & 0xFFFFFFFF
            remainder = response['offset'] % response['max_size']

            if expected_crc != response['crc']:
                # Invalid CRC. Remove corrupted data.
                response[
                    'offset'] -= remainder if remainder != 0 else response[
                        'max_size']
                response['crc']     = \
                        binascii.crc32(firmware[:response['offset']]) & 0xFFFFFFFF
                return

            if (remainder != 0) and (response['offset'] != len(firmware)):
                # Send rest of the page.
                try:
                    to_send = firmware[response['offset']:response['offset'] +
                                       response['max_size'] - remainder]
                    response['crc'] = self.__stream_data(
                        data=to_send,
                        crc=response['crc'],
                        offset=response['offset'])
                    response['offset'] += len(to_send)
                except ValidationException:
                    # Remove corrupted data.
                    response['offset'] -= remainder
                    response['crc']     = \
                        binascii.crc32(firmware[:response['offset']]) & 0xFFFFFFFF
                    return

            self.__execute()
            self._send_event(event_type=DfuEvent.PROGRESS_EVENT,
                             progress=response['offset'])

        response = self.__select_data()
        try_to_recover()
        for i in range(response['offset'], len(firmware),
                       response['max_size']):
            data = firmware[i:i + response['max_size']]
            try:
                self.__create_data(len(data))
                response['crc'] = self.__stream_data(data=data,
                                                     crc=response['crc'],
                                                     offset=i)
                self.__execute()
            except ValidationException:
                raise NordicSemiException("Failed to send firmware")

            self._send_event(event_type=DfuEvent.PROGRESS_EVENT,
                             progress=len(data))

    def __ensure_bootloader(self):
        lister = DeviceLister()

        device = None
        start = datetime.now()
        while not device and datetime.now() - start < timedelta(
                seconds=self.timeout):
            time.sleep(0.5)
            device = lister.get_device(com=self.com_port)

        if device:
            device_serial_number = device.serial_number

            if not self.__is_device_in_bootloader_mode(device):
                retry_count = 10
                wait_time_ms = 500

                trigger = DFUTrigger()
                try:
                    trigger.enter_bootloader_mode(device)
                    logger.info("Serial: DFU bootloader was triggered")
                except NordicSemiException as err:
                    logger.error(err)

                for checks in range(retry_count):
                    logger.info("Serial: Waiting {} ms for device to enter bootloader {}/{} time"\
                    .format(500, checks + 1, retry_count))

                    time.sleep(wait_time_ms / 1000.0)

                    device = lister.get_device(
                        serial_number=device_serial_number)
                    if self.__is_device_in_bootloader_mode(device):
                        self.com_port = device.get_first_available_com_port()
                        break

                trigger.clean()
            if not self.__is_device_in_bootloader_mode(device):
                logger.info(
                    "Serial: Device is either not in bootloader mode, or using an unsupported bootloader."
                )

    def __is_device_in_bootloader_mode(self, device):
        if not device:
            return False

        #  Return true if nrf bootloader or Jlink interface detected.
        return (
            (device.vendor_id.lower() == '1915'
             and device.product_id.lower() == '521f')  # nRF52 SDFU USB
            or (device.vendor_id.lower() == '1366'
                and device.product_id.lower() == '0105')  # JLink CDC UART Port
            or (device.vendor_id.lower() == '1366'
                and device.product_id.lower() == '1015')
        )  # JLink CDC UART Port (MSD)

    def __set_prn(self):
        logger.debug("Serial: Set Packet Receipt Notification {}".format(
            self.prn))
        self.dfu_adapter.send_message([DfuTransportSerial.OP_CODE['SetPRN']] +
                                      list(struct.pack('<H', self.prn)))
        self.__get_response(DfuTransportSerial.OP_CODE['SetPRN'])

    def __get_mtu(self):
        self.dfu_adapter.send_message(
            [DfuTransportSerial.OP_CODE['GetSerialMTU']])
        response = self.__get_response(
            DfuTransportSerial.OP_CODE['GetSerialMTU'])

        self.mtu = struct.unpack('<H', bytearray(response))[0]

    def __ping(self):
        self.ping_id = (self.ping_id + 1) % 256

        self.dfu_adapter.send_message(
            [DfuTransportSerial.OP_CODE['Ping'], self.ping_id])
        resp = self.dfu_adapter.get_message(
        )  # Receive raw response to check return code

        if (resp is None):
            logger.debug('Serial: No ping response')
            return False

        if resp[0] != DfuTransportSerial.OP_CODE['Response']:
            logger.debug('Serial: No Response: 0x{:02X}'.format(resp[0]))
            return False

        if resp[1] != DfuTransportSerial.OP_CODE['Ping']:
            logger.debug('Serial: Unexpected Executed OP_CODE.\n' \
                + 'Expected: 0x{:02X} Received: 0x{:02X}'.format(DfuTransportSerial.OP_CODE['Ping'], resp[1]))
            return False

        if resp[2] != DfuTransport.RES_CODE['Success']:
            # Returning an error code is seen as good enough. The bootloader is up and running
            return True
        else:
            if struct.unpack('B', bytearray(resp[3:]))[0] == self.ping_id:
                return True
            else:
                return False

    def __create_command(self, size):
        self.__create_object(0x01, size)

    def __create_data(self, size):
        self.__create_object(0x02, size)

    def __create_object(self, object_type, size):
        self.dfu_adapter.send_message([DfuTransportSerial.OP_CODE['CreateObject'], object_type]\
                                            + list(struct.pack('<L', size)))
        self.__get_response(DfuTransportSerial.OP_CODE['CreateObject'])

    def __calculate_checksum(self):
        self.dfu_adapter.send_message(
            [DfuTransportSerial.OP_CODE['CalcChecSum']])
        response = self.__get_response(
            DfuTransportSerial.OP_CODE['CalcChecSum'])

        if response is None:
            raise NordicSemiException(
                'Did not receive checksum response from DFU target. '
                'If MSD is enabled on the target device, try to disable it ref. '
                'https://wiki.segger.com/index.php?title=J-Link-OB_SAM3U')

        (offset, crc) = struct.unpack('<II', bytearray(response))
        return {'offset': offset, 'crc': crc}

    def __execute(self):
        self.dfu_adapter.send_message([DfuTransportSerial.OP_CODE['Execute']])
        self.__get_response(DfuTransportSerial.OP_CODE['Execute'])

    def __select_command(self):
        return self.__select_object(0x01)

    def __select_data(self):
        return self.__select_object(0x02)

    def __select_object(self, object_type):
        logger.debug("Serial: Selecting Object: type:{}".format(object_type))
        self.dfu_adapter.send_message(
            [DfuTransportSerial.OP_CODE['ReadObject'], object_type])

        response = self.__get_response(
            DfuTransportSerial.OP_CODE['ReadObject'])
        (max_size, offset, crc) = struct.unpack('<III', bytearray(response))

        logger.debug(
            "Serial: Object selected: " +
            " max_size:{} offset:{} crc:{}".format(max_size, offset, crc))
        return {'max_size': max_size, 'offset': offset, 'crc': crc}

    def __get_checksum_response(self):
        resp = self.__get_response(DfuTransportSerial.OP_CODE['CalcChecSum'])

        (offset, crc) = struct.unpack('<II', bytearray(resp))
        return {'offset': offset, 'crc': crc}

    def __stream_data(self, data, crc=0, offset=0):
        logger.debug(
            "Serial: Streaming Data: " +
            "len:{0} offset:{1} crc:0x{2:08X}".format(len(data), offset, crc))

        def validate_crc():
            if (crc != response['crc']):
                raise ValidationException('Failed CRC validation.\n'\
                                + 'Expected: {} Received: {}.'.format(crc, response['crc']))
            if (offset != response['offset']):
                raise ValidationException('Failed offset validation.\n'\
                                + 'Expected: {} Received: {}.'.format(offset, response['offset']))

        current_pnr = 0

        for i in range(0, len(data), (self.mtu - 1) // 2 - 1):
            # append the write data opcode to the front
            # here the maximum data size is self.mtu/2,
            # due to the slip encoding which at maximum doubles the size
            to_transmit = data[i:i + (self.mtu - 1) // 2 - 1]
            to_transmit = struct.pack(
                'B', DfuTransportSerial.OP_CODE['WriteObject']) + to_transmit

            self.dfu_adapter.send_message(list(to_transmit))
            crc = binascii.crc32(to_transmit[1:], crc) & 0xFFFFFFFF
            offset += len(to_transmit) - 1
            current_pnr += 1
            if self.prn == current_pnr:
                current_pnr = 0
                response = self.__get_checksum_response()
                validate_crc()
        response = self.__calculate_checksum()
        validate_crc()
        return crc

    def __get_response(self, operation):
        def get_dict_key(dictionary, value):
            return next(
                (key for key, val in list(dictionary.items()) if val == value),
                None)

        resp = self.dfu_adapter.get_message()

        if resp is None:
            return None

        if resp[0] != DfuTransportSerial.OP_CODE['Response']:
            raise NordicSemiException('No Response: 0x{:02X}'.format(resp[0]))

        if resp[1] != operation:
            raise NordicSemiException('Unexpected Executed OP_CODE.\n' \
                             + 'Expected: 0x{:02X} Received: 0x{:02X}'.format(operation, resp[1]))

        if resp[2] == DfuTransport.RES_CODE['Success']:
            return resp[3:]

        elif resp[2] == DfuTransport.RES_CODE['ExtendedError']:
            try:
                data = DfuTransport.EXT_ERROR_CODE[resp[3]]
            except IndexError:
                data = "Unsupported extended error type {}".format(resp[3])
            raise NordicSemiException('Extended Error 0x{:02X}: {}'.format(
                resp[3], data))
        else:
            raise NordicSemiException('Response Code {}'.format(
                get_dict_key(DfuTransport.RES_CODE, resp[2])))
Example #46
0
class Modem():
    #Serial port settings
    read_buffer_size = 1024

    #Some constants
    linesep = '\r\n'
    ok_response = 'OK'
    error_response = 'ERROR'
    clcc_header = "+CLCC:"
    clip_header = "+CLIP:"
    clcc_enabled = False

    #Status storage variables
    status = {"state": "idle", "type": None}

    #The Caller ID variable - is set when a call is received and cleard when a call ends
    #When set, it looks like this:
    #current_callerid = {"number":"something", "type":"unknown"/"international"/"national"/"network-specific"}
    current_callerid = None

    def __init__(self,
                 serial_path="/dev/ttyAMA0",
                 serial_timeout=0.5,
                 read_timeout=0.2):
        self.serial_path = serial_path
        self.serial_timeout = serial_timeout
        self.read_timeout = read_timeout
        self.executing_command = Event()
        self.should_monitor = Event()
        self.unexpected_queue = Queue()

    def init_modem(self):
        self.port = Serial(self.serial_path,
                           115200,
                           timeout=self.serial_timeout)
        self.at()
        self.enable_verbosity()
        print("Battery voltage is: {}".format(self.get_voltage()))
        self.enable_clcc()
        self.enable_clip()
        self.set_message_mode("pdu")
        #self.at_command("AT+CSSN=1,1")
        self.save_settings()

    def deinit_modem(self):
        try:
            self.port.close()
        except:  #Could be not created or already closed
            pass

#Functions that the user will be calling

    def call(self, number):
        #ATD in CLCC is going to generate CLCC data straight away,
        #so that's going into the queue to be processed separately
        response = self.at_command("ATD{};".format(number), nook=True)
        self.queue_unexpected_data(response)
        return True

    def ussd(self, string):
        result = self.at_command('AT+CUSD=1,"{}"'.format(string))

    def hangup(self):
        return self.at_command("ATH", noresponse=True)

    def answer(self):
        return self.at_command("ATA")

    #Debugging helpers

    def pprint_status(self):
        print("--------------------------")
        print("New state: {}".format(self.status["state"]))
        if self.current_callerid:
            print("Caller ID: {}, type: {}".format(
                self.current_callerid["number"],
                self.current_callerid["type"]))

    def print_callerid(self, callerid):
        if self.current_callerid:
            print("Incoming: {} ({})".format(self.current_callerid["number"],
                                             self.current_callerid["type"]))

    #Call state set function - that also calls a callback

    def set_state(self, key, value):
        self.status[key] = value
        if callable(self.update_state_cb):
            self.update_state_cb(key, value)

    #Callbacks that change the call state and clean state variables
    #Not to be overridden directly as they might have desirable side effects
    #Also, they're called in a hackish way and overriding would fail anyway

    #Call-specific callbacks

    #  "0":on_talking,
    def on_talking(self):
        #Call answered, voice comms established
        self.set_state("state", "talking")
        #self.pprint_status()

    #  "1":on_held,
    def on_held(self):
        #Held call signal
        if self.status["type"] == "incoming":
            self.set_state("state", "held")
        else:
            self.set_state("state", "holding")
        #self.pprint_status()

    #  "2":on_dialing,
    def on_dialing(self):
        assert (self.status["type"] == "outgoing")
        self.set_state("state", "dialing")
        #self.pprint_status()

    #  "3":on_alerting,
    def on_alerting(self):
        assert (self.status["type"] == "outgoing")
        self.set_state("state", "alerting")
        #self.pprint_status()

    #  "4":on_incoming,
    def on_incoming(self):
        assert (self.status["type"] == "incoming")
        self.set_state("state", "incoming_call")
        #self.pprint_status()

    #  "5":on_waiting,
    def on_waiting(self):
        assert (self.status["type"] == "incoming")
        self.set_state("state", "incoming")
        #self.pprint_status()

    #  "6":on_disconnect
    def on_disconnect(self, incoming=True):
        #Either finished or missed call
        if self.status["type"] == "incoming" and self.status["state"] not in [
                "held", "talking"
        ]:
            self.set_state("state", "missed_call")
        else:
            self.set_state("state", "finished")
        Timer(3, self.on_idle).start()
        #self.pprint_status()

    def on_idle(self):
        #Cleans up variables and sets state to "idle"
        #Only runs from threading.Timer since modem sends no "idle" CLCC message
        #Safety check to ensure this doesn't run during a call
        #if call happens right after previous call ends:
        if self.status["state"] not in ["active_call", "held"]:
            self.current_callerid = None
            self.set_state("state", "idle")
            self.set_state("type", None)
            #self.pprint_status()

    #SMS callbacks

    def on_incoming_message(self, cmti_line):
        #New message signal
        print("You've got mail! Line: {}".format(
            cmti_line[len("+CMTI:"):]).strip())
        self.read_all_messages()

    def read_all_messages(self):
        prev_timeout = self.serial_timeout
        self.serial_timeout = 1  #TODO: get message count and base timeout on that
        output = self.at_command("AT+CMGL")
        self.serial_timeout = prev_timeout
        if len(output) % 2 == 1:
            print("CMGL output lines not in pairs?")
            print("PDATA: {}".format(repr(output)))
            return False
        cmgl_header = "+CMGL: "
        for i in range(len(output) / 2):
            header = output[i * 2]
            if not header.startswith(cmgl_header):
                print(
                    "Line presumed to be CMGL doesn't start with CMGL header!")
                continue
            id, x, x, pdu_len = header[len(cmgl_header):].split(",")
            smsc_pdu_str = output[(i * 2) + 1]
            self.decode_message(smsc_pdu_str, pdu_len, id)

    def decode_message(self, smsc_pdu_str, pdu_len, id):
        print("Reading message {}".format(id))
        pdu_len = int(pdu_len)  #Just in case
        smsc_len = len(
            smsc_pdu_str) - pdu_len * 2  #We get PDU length in octets
        if smsc_len == 0:
            print("No SMSC in PDU - seems like it can happen!")
        pdu_str = smsc_pdu_str[smsc_len:]  #Discarding SMSC info
        #SMSC info might actually be useful in the future - maybe its spoofing could be detected? Does it even happen?
        smspdu.pdu.dump(pdu_str)

    #Non-CLCC exclusive callbacks
    #(the non-CLCC path might not even work that well, for what I know)
    def on_ring(self):
        print("Ring ring ring bananaphone!")

    #AT command-controlled modem settings and simple functions

    def get_manufacturer(self):
        return self.at_command("AT+CGMI")

    def get_model(self):
        return self.at_command("AT+CGMM")

    def get_imei(self):
        return self.at_command("AT+GSN")

    def save_settings(self):
        self.at_command("AT&W")

    def enable_verbosity(self):
        return self.at_command('AT+CMEE=1')

    def enable_clcc(self):
        self.clcc_enabled = True
        return self.at_command('AT+CLCC=1')

    def set_message_mode(self, mode_str):
        if mode_str.lower() == "text":
            return self.at_command('AT+CMGF=1')
        elif mode_str.lower() == "pdu":
            return self.at_command('AT+CMGF=0')
        else:
            raise ValueError("Wrong message mode: {}".format(mode_str))

    def enable_clip(self):
        return self.at_command('AT+CLIP=1')

    def at(self):
        response = self.at_command('AT')
        if response is True: return
        raise ATError(expected=self.ok_response, received=response)

    #Auxiliary functions that aren't related to phone functionality
    #TODO: Expose this to an external API of sorts

    def get_voltage(self):
        answer = self.at_command('AT+CBC')
        if not answer.startswith('+CBC'):
            return 0.0  #TODO - this needs to be better!
        voltage_str = answer.split(':')[1].split(',')[2]
        voltage = round(int(voltage_str) / 1000.0, 2)
        return voltage

    #Call status and Caller ID message processing code
    #This is where we get call information info

    def process_clcc(self, clcc_line):
        clcc_line = clcc_line[len(self.clcc_header):]
        clcc_line = clcc_line.strip()
        elements = clcc_line.split(',')
        if len(elements) < 5:
            print("Unrecognized number of CLCC elements!")
            print("PDATA: " + repr(elements))
            return
        elif len(elements) > 8:
            print("Too much CLCC elements!")
            print("PDATA: " + repr(elements))
            elements = elements[:8]
        if len(elements) > 7:  #Elements 5 and 6 are present
            self.set_callerid(elements[5], elements[6])
        call_type = elements[1]
        call_status = elements[2]
        new_state = "incoming" if call_type == "1" else "outgoing"
        self.set_state("type", new_state)
        self.clcc_mapping[call_status](self)

    def process_clip(self, line):
        clip_line = line[len(self.clip_header):]
        clip_line = clip_line.strip()
        elements = clip_line.split(',')
        if len(elements) < 2:
            raise ATError(expected="valid CLIP string with >2 elements",
                          received=line)
        elif len(elements) < 6:
            print("Less than 6 CLIP elements, noting")
            print("PDATA: " + repr(elements))
        elif len(elements) > 6:
            print("Too much CLIP elements, what's wrong?!")
            print("PDATA: " + repr(elements))
            elements = elements[:6]
        number = elements[0]
        type_id = elements[1]
        self.set_callerid(number, type_id)

    def set_callerid(self, number, type_id):
        clip_type_mapping = {
            "129": "unknown",
            "161": "national",
            "145": "international",
            "177": "network-specific"
        }
        if type_id not in clip_type_mapping.keys():
            print("PDATA: CLIP type id {} not found in type mapping!".format(
                type_id))
            type = "unknown"
        else:
            type = clip_type_mapping[type_id]
        #Setting status variable
        self.current_callerid = {"number": number.strip('\"'), "type": type}

    clcc_mapping = {
        "0": on_talking,
        "1": on_held,
        "2": on_dialing,
        "3": on_alerting,
        "4": on_incoming,
        "5": on_waiting,
        "6": on_disconnect
    }

    def on_clcc(self, clcc_line):
        for i in range(4):
            if not has_nonascii(clcc_line) or not is_csv(clcc_line):
                break
            print("Garbled call info line! Try {}, line: {}".format(
                i, clcc_line))
            sleep(1)
            clcc_response = self.at_command("AT+CLCC", nook=True)
            print(repr(lines))
            for line in lines:
                if line.startswith(self.clcc_header):
                    clcc_line = line
                else:
                    self.queue_unexpected_data(line)
        if has_nonascii(clcc_line) or not is_csv(clcc_line):
            print("Still garbled CLCC line!")
            return
        #print("Call info OK, line: {}".format(repr(clcc_line[len(self.clcc_header):])).strip())
        self.process_clcc(clcc_line)

    def on_clip(self, line):
        self.process_clip(line)

    #Low-level functions

    def check_input(self):
        input = self.port.read(self.read_buffer_size)
        if input:
            self.queue_unexpected_data(input)

    def at_command(self, command, noresponse=False, nook=False):
        self.executing_command.set()
        self.check_input()
        self.port.write(command + self.linesep)
        echo = self.port.read(len(command))  #checking for command echo
        if echo != command:
            raise ATError(received=echo, expected=command)
        #print(repr(self.port.read(len(self.linesep)+1)))
        self.port.read(
            len(self.linesep) + 1
        )  #shifting through the line separator - that +1 seems to be necessary when we're reading right after the echo
        if noresponse:
            return True  #one of commands that doesn't need a response
        answer = self.port.read(self.read_buffer_size)
        self.executing_command.clear()
        lines = filter(None, answer.split(self.linesep))
        #print(lines)
        if nook: return lines
        if self.ok_response not in lines:  #expecting OK as one of the elements
            raise ATError(expected=self.ok_response, received=lines)
        #We can have a sudden undervoltage warning, though
        #I'll assume the OK always goes last in the command
        #So we can pass anything after OK to the unexpected line parser
        ok_response_index = lines.index(self.ok_response)
        if ok_response_index + 1 < len(lines):
            self.queue_unexpected_data(lines[(ok_response_index + 1):])
            lines = lines[:(ok_response_index + 1)]
        if len(lines) == 1:  #Single-line response
            if lines[0] == self.ok_response:
                return True
            else:
                return lines[0]
        else:
            lines = lines[:-1]
            if len(lines) == 1:
                return lines[0]
            else:
                return lines

    #Functions for background monitoring of any unexpected input

    def queue_unexpected_data(self, data):
        self.unexpected_queue.put(data)

    def process_incoming_data(self, data):
        logging.debug("Incoming data: {}".format(repr(data)))
        if isinstance(data, str):
            data = data.split(self.linesep)
        lines = filter(None, data)
        for line in lines:
            #print(line)
            #Now onto the callbacks
            #We should ignore some messages if we're using CLIP
            #As those messages will appear anyway, but processing them
            #would be redundant. It could be much prettier, though.
            if line == "OK":
                continue
            if line == "RING":
                if not self.clcc_enabled:
                    self.on_ring()
                continue
            if line == "BUSY":
                if not self.clcc_enabled:
                    self.on_busy()
                continue
            if line == "HANGUP":
                if not self.clcc_enabled:
                    self.on_hangup()
                continue
            if line == "NO ANSWER":
                if not self.clcc_enabled:
                    self.on_noanswer()
                continue
            if line == "NO CARRIER":
                if not self.clcc_enabled:
                    self.on_nocarrier()
                continue
            if line in ["SMS Ready", "Call Ready"]:
                continue  #Modem just reset
            if line.startswith("+CMTI:"):
                self.on_incoming_message(line)
                continue
            if line.startswith(self.clcc_header):
                self.on_clcc(line)
                continue
            if line.startswith(self.clip_header):
                self.on_clip(line)
                continue
            self.parse_unexpected_message(line)

    def parse_unexpected_message(self, data):
        #haaaax
        if self.linesep[::-1] in "".join(data):
            lines = "".join(data).split(self.linesep[::-1])
        logging.debug("Unexpected line: {}".format(data))
        print("Unexpected line: {}".format(data))

    #The monitor thread - it receives data from the modem and calls callbacks

    def monitor(self):
        while self.should_monitor.isSet():
            #print("Monitoring...")
            if not self.executing_command.isSet():
                #First, the serial port
                #print("Reading data through serial!")
                data = self.port.read(self.read_buffer_size)
                if data:
                    print("Got data through serial!")
                    self.process_incoming_data(data)
                #Then, the queue of unexpected messages received from other commands
                #print("Reading data from queue!")
                try:
                    data = self.unexpected_queue.get_nowait()
                except Empty:
                    pass
                else:
                    print("Got data from queue!")
                    self.process_incoming_data(data)
            #print("Got to sleep")
            sleep(self.serial_timeout)
            #print("Returned from sleep")
            #try:
            #    print(modem.at_command("AT+CPAS"))
            #except:
            #    print("CPAS exception")
        print("Stopped monitoring!")

    def start_monitoring(self):
        self.should_monitor.set()
        self.thread = Thread(target=self.monitor)
        self.thread.daemon = True
        self.thread.start()

    def stop_monitoring(self):
        self.should_monitor.clear()
Example #47
0
class Ev3:
    class _MsgType:
        class Mode:
            def __init__(self, first, second):
                self.second = second
                self.first = first

        speed = Mode(10, 165)
        start = Mode(8, 166)
        stop = Mode(9, 163)

    class Motors:
        A = 0b1
        B = 0b10
        C = 0b100
        D = 0b1000

    class Stop:
        FLOAT = 0
        BREAK = 1

    def __init__(self, port_name):
        self._controller = Serial(port_name, baudrate=9600,
                                  stopbits=serial.STOPBITS_ONE,
                                  parity=serial.PARITY_NONE,
                                  bytesize=serial.EIGHTBITS)

        time.sleep(1)
        self._lock = threading.Lock()

    def set_speed(self, motor, val):
        message = self._pack_msg(self._MsgType.speed)
        
        if val > 127:
            val = 127
        if val < -127:
            val = -127
        if val < 0:
            val = 255 - abs(val)

        for i in range(0, 3):
            message.append(0)

        message[9] = motor
        message[10] = 129
        message[11] = val

        self._send(message)

    def start(self, motor):
        message = self._pack_msg(self._MsgType.start)

        for i in range(0, 1):
            message.append(0)

        message[9] = motor

        self._send(message)

    def stop(self, motor, type):
        message = self._pack_msg(self._MsgType.stop)

        for i in range(0, 2):
            message.append(0)

        message[9] = motor
        message[10] = type

        self._send(message)

    def _send(self, message):
        try:
            self._lock.acquire()
            self._controller.write(bytes(message))
        finally:
            self._lock.release()

    @staticmethod
    def _pack_msg(mode):
        msg = [0 for i in range(9)]
        msg[0] = mode.first
        msg[7] = mode.second
        msg[4] = 128

        return msg

    def close(self):
        self._controller.close()

    def __del__(self):
        self.close()
Example #48
0
class SimpleSerialBoard:

    # ************   BEGIN CONSTANTS DEFINITION ****************

    DEBUG = True

    # ************   END CONSTANTS DEFINITION ****************

    # ************   BEGIN PRIVATE FIELDS DEFINITION ****************

    ser_conn = None  # self board uses serial communication
    asip = None  # The client for the aisp protocol
    queue = Queue(
        10)  # Buffer # TODO: use pipe instead of queue for better performances
    #  FIXME: fix Queue dimension?
    _port = ""  #serial port
    _ports = []  #serial ports array
    __running = False

    # ************   END PRIVATE FIELDS DEFINITION ****************

    # self constructor takes the name of the serial port and it creates a Serial object
    # Here the serial listener and the queue reader are started
    def __init__(self):
        # TODO: very simple implementation, need to improve
        #self.ser_conn = Serial()
        #self.serial_port_finder()
        try:
            # old implementation was:
            #self.ser_conn = Serial(port='/dev/cu.usbmodemfd121', baudrate=57600)
            # self.ser_conn = Serial(port=self._port, baudrate=57600)
            self.ser_conn = Serial()
            portIndexToOpen = 0
            self.serial_port_finder(portIndexToOpen)
            sys.stdout.write("attempting to open {}\n".format(
                self._ports[portIndexToOpen]))
            self.open_serial(self._ports[0], 57600)
            sys.stdout.write("port opened\n")
            self.asip = AsipClient(self.SimpleWriter(self))
        except Exception as e:
            sys.stdout.write(
                "Exception: caught {} while init serial and asip protocols\n".
                format(e))

        try:
            self.__running = True
            self.ListenerThread(self.queue, self.ser_conn, self.__running,
                                self.DEBUG).start()
            self.ConsumerThread(self.queue, self.asip, self.__running,
                                self.DEBUG).start()
            self.KeyboardListener(self).start()
            print("****** I am here ******")
            #while self.asip.isVersionOk() == False:  # flag will be set to true when valid version message is received
            #self.request_info()
            #time.sleep(1.0)
            self.request_port_mapping()
            time.sleep(1)
            self.request_port_mapping()
            time.sleep(1)
            while not self.asip.check_mapping():
                self.request_port_mapping()
                time.sleep(0.1)
            print("**** Everything check ****")
        except Exception as e:
            #TODO: improve exception handling
            sys.stdout.write(
                "Exception: caught {} while launching threads\n".format(e))

    # ************ BEGIN PUBLIC METHODS *************

    # The following methods are just a replica from the asip class.
    # TODO: add parameter checikng in each function (raise exception?)
    def digital_read(self, pin):
        return self.asip.digital_read(pin)

    def analog_read(self, pin):
        return self.asip.analog_read(pin)

    def set_pin_mode(self, pin, mode):
        self.asip.set_pin_mode(pin, mode)

    def digital_write(self, pin, value):
        self.asip.digital_write(pin, value)

    def analog_write(self, pin, value):
        self.asip.analog_write(pin, value)

    def request_info(self):
        self.asip.request_info()

    def request_port_mapping(self):
        self.asip.request_port_mapping()

    def set_auto_report_interval(self, interval):
        self.asip.set_auto_report_interval(interval)

    def add_service(self, service_id, asip_service):
        self.asip.add_service(service_id, asip_service)

    def get_asip_client(self):
        return self.asip

    # ************ END PUBLIC METHODS *************

    # ************ BEGIN PRIVATE METHODS *************

    def open_serial(self, port, baudrate):
        if self.ser_conn.isOpen():
            self.ser_conn.close()
        self.ser_conn.port = port
        self.ser_conn.baudrate = baudrate
        # self.ser_conn.timeout = None # 0 or None?
        self.ser_conn.open()
        # Toggle DTR to reset Arduino
        self.ser_conn.setDTR(False)
        time.sleep(1)
        # toss any data already received, see
        self.ser_conn.flushInput()
        self.ser_conn.setDTR(True)

    def close_serial(self):
        self.ser_conn.close()

    # This methods retrieves the operating system and set the Arduino serial port
    """Lists serial ports

    :raises EnvironmentError:
        On unsupported or unknown platforms
    :returns:
        A list of available serial ports
    """

    # TODO: test needed for linux and windows implementation
    def serial_port_finder(self, desiredIndex):
        #system = platform.system()
        # if self.DEBUG:
        #     sys.stdout.write("DEBUG: detected os is {}\n".format(system))
        # if 'linux' in system:
        #     pass
        # elif 'Darwin' == system: # also 'mac' or 'darwin' may work?
        #     for file in os.listdir("/dev"):
        #         if file.startswith("tty.usbmodem"):
        #             self._port = "/dev/" + file
        #             if self.DEBUG:
        #                 sys.stdout.write("DEBUG: serial file is {}\n".format(file))
        #             break
        # elif ('win' in system) or ('Win' in system) or ('cygwin' in system) or ('nt' in system):
        #     pass
        # else:
        #     raise EnvironmentError('Unsupported platform')
        # if self.DEBUG:
        #     sys.stdout.write("DEBUG: port is {}\n".format(self._port))

        system = sys.platform
        if system.startswith('win'):
            temp_ports = ['COM' + str(i + 1) for i in range(255)]
        elif system.startswith('linux'):
            # this is to exclude your current terminal "/dev/tty"
            temp_ports = glob.glob('/dev/tty[A-Za-z]*')
        elif system.startswith('darwin'):
            temp_ports = glob.glob('/dev/tty.usbmodem*')
            cp2104 = glob.glob('/dev/tty.SLAB_USBtoUART'
                               )  # append usb to serial converter cp2104
            ft232rl = glob.glob('/dev/tty.usbserial-A9MP5N37'
                                )  # append usb to serial converter ft232rl
            fth = glob.glob(
                '/dev/tty.usbserial-FTHI5TLH')  # append usb to serial cable
            # new = glob.glob('/dev/tty.usbmodemfa131')
            #temp_ports = glob.glob('/dev/tty.SLAB_USBtoUART')
            #temp_ports = glob.glob('/dev/tty.usbserial-A9MP5N37')
            if cp2104 is not None:
                temp_ports += cp2104
            if ft232rl is not None:
                temp_ports += ft232rl
            if fth is not None:
                temp_ports += fth
            #if new is not None: # FIXME: REMOVE!!! Only used for tests
            #    temp_ports = new
        else:
            raise EnvironmentError('Unsupported platform')

        for port in temp_ports:
            try:
                self.ser_conn.port = port
                s = self.ser_conn.open()
                self.ser_conn.close()
                self._ports.append(port)
                if (len(self._ports) > desiredIndex):
                    return  # we have found the desired port
            except serial.SerialException:
                pass
        if self.DEBUG:
            sys.stdout.write("DEBUG: available ports are {}\n".format(
                self._ports))

    # ************ END PRIVATE METHODS *************

    # ************ BEGIN PRIVATE CLASSES *************

    # As described above, SimpleSerialBoard writes messages to the serial port.
    # inner class SimpleWriter implements abstract class AsipWriter:
    class SimpleWriter(AsipWriter):
        parent = None

        def __init__(self, parent):
            self.parent = parent

        # val is a string
        # TODO: improve try catch
        def write(self, val):
            #print(val),
            if self.parent.ser_conn.isOpen():
                try:
                    temp = val.encode()
                    self.parent.ser_conn.write(temp)
                    if self.parent.DEBUG:
                        sys.stdout.write(
                            "DEBUG: just wrote in serial {}\n".format(temp))
                except (OSError, serial.SerialException):
                    pass
            else:
                raise serial.SerialException

    class KeyboardListener(Thread):
        def __init__(self, parent):
            Thread.__init__(self)
            self.parent = parent
            self.running = True

        # if needed, kill will stops the loop inside run method
        def kill(self):
            self.running = False

        def run(self):
            while self.running:
                if self.heardEnter():
                    sys.stdout.write("*** Closing ***hty\n")
                    self.parent.__running = False
                    time.sleep(0.5)
                    self.parent.close_serial()
                    self.running = False

        def heardEnter(self):
            i, o, e = select.select([sys.stdin], [], [], 0.0001)
            for s in i:
                if s == sys.stdin:
                    input = sys.stdin.readline()
                    return True
                return False

    # ListenerThread and ConsumerThread are implemented following the Producer/Consumer pattern
    # A class for a listener that rad the serial stream and put incoming messages on a queue
    # TODO: implement try catch
    class ListenerThread(Thread):

        queue = None
        ser_conn = None
        running = False
        DEBUG = False

        # overriding constructor
        def __init__(self, queue, ser_conn, running, debug):
            Thread.__init__(self)
            self.queue = queue
            self.ser_conn = ser_conn
            self.running = running
            self.DEBUG = debug
            if self.DEBUG:
                sys.stdout.write("DEBUG: serial thread process created \n")

        # if needed, kill will stops the loop inside run method
        def kill(self):
            self.running = False

        # overriding run method, thread activity
        def run(self):
            temp_buff = ""
            time.sleep(2)
            # TODO: implement ser.inWaiting() >= minMsgLen to check number of char in the receive buffer?
            serBuffer = ""

            while self.running:
                # #if self.DEBUG:
                # #    sys.stdout.write("DEBUG: Temp buff is now {}\n".format(temp_buff))
                # time.sleep(0.1)
                # val = self.ser_conn.readline()
                # #val = self.ser_conn.read()
                # if self.DEBUG:
                #     sys.stdout.write("DEBUG: val value when retrieving from serial is {}\n".format(val))
                # val = val.decode('utf-8', errors= 'ignore')
                # if self.DEBUG:
                #     sys.stdout.write("DEBUG: val value after decode is {}".format(val))
                # if val is not None and val!="\n" and val!=" ":
                #     if "\n" in val:
                #         # If there is at least one newline, we need to process
                #         # the message (the buffer may contain previous characters).
                #
                #         while ("\n" in val and len(val) > 0):
                #             # But remember that there could be more than one newline in the buffer
                #             temp_buff += (val[0:val.index("\n")])
                #             self.queue.put(temp_buff)
                #             if self.DEBUG:
                #                 sys.stdout.write("DEBUG: Serial produced {}\n".format(temp_buff))
                #             temp_buff = ""
                #             val = val[val.index("\n")+1:]
                #             if self.DEBUG:
                #                 sys.stdout.write("DEBUG: Now val is {}\n".format(val))
                #         if len(val)>0:
                #             temp_buff = val
                #         if self.DEBUG:
                #             sys.stdout.write("DEBUG: After internal while buffer is {}\n".format(temp_buff))
                #     else:
                #         temp_buff += val
                #         if self.DEBUG:
                #             sys.stdout.write("DEBUG: else case, buff is equal to val, so they are {}\n".format(temp_buff))
                try:
                    while True:
                        c = self.ser_conn.read(
                        )  # attempt to read a character from Serial
                        c = c.decode('utf-8', errors='ignore')
                        #was anything read?
                        if len(c) == 0:
                            break

                        # check if character is a delimiter
                        if c == '\r':
                            c = ''  # ignore CR
                        elif c == '\n':
                            serBuffer += "\n"  # add the newline to the buffer
                            if self.DEBUG:
                                sys.stdout.write(
                                    "Serial buffer is now {}\n".format(
                                        serBuffer))
                            self.queue.put(serBuffer)
                            serBuffer = ''  # empty the buffer
                        else:
                            #print("Try to print: {}".format(c))
                            serBuffer += c  # add to the buffer
                except (OSError, serial.SerialException):
                    self.running = False
                    sys.stdout.write("Serial Exception in listener\n")

    # A class that reads the queue and launch the processInput method of the AispClient.
    class ConsumerThread(Thread):

        queue = None
        asip = None
        running = False
        DEBUG = False

        # overriding constructor
        def __init__(self, queue, asip, running, debug):
            Thread.__init__(self)
            self.queue = queue
            self.asip = asip
            self.running = running
            self.DEBUG = debug
            if self.DEBUG:
                sys.stdout.write("DEBUG: consumer thread created \n")

        # if needed, kill will stops the loop inside run method
        def kill(self):
            self.running = False

        # overriding run method, thread activity
        def run(self):
            # global _queue
            # global asip
            while self.running:
                temp = self.queue.get()
                self.asip.process_input(temp)
                self.queue.task_done()
Example #49
0
class printcore():
    def __init__(self, port=None, baud=None, dtr=None):
        """Initializes a printcore instance. Pass the port and baud rate to
           connect immediately"""
        self.baud = None
        self.dtr = None
        self.port = None
        self.analyzer = gcoder.GCode()
        # Serial instance connected to the printer, should be None when
        # disconnected
        self.printer = None
        # clear to send, enabled after responses
        # FIXME: should probably be changed to a sliding window approach
        self.clear = 0
        # The printer has responded to the initial command and is active
        self.online = False
        # is a print currently running, true if printing, false if paused
        self.printing = False
        self.mainqueue = None
        self.priqueue = Queue(0)
        self.queueindex = 0
        self.lineno = 0
        self.resendfrom = -1
        self.paused = False
        self.sentlines = {}
        self.log = deque(maxlen=10000)
        self.sent = []
        self.writefailures = 0
        self.tempcb = None  # impl (wholeline)
        self.recvcb = None  # impl (wholeline)
        self.sendcb = None  # impl (wholeline)
        self.preprintsendcb = None  # impl (wholeline)
        self.printsendcb = None  # impl (wholeline)
        self.layerchangecb = None  # impl (wholeline)
        self.errorcb = None  # impl (wholeline)
        self.startcb = None  # impl ()
        self.endcb = None  # impl ()
        self.onlinecb = None  # impl ()
        self.loud = False  # emit sent and received lines to terminal
        self.tcp_streaming_mode = False
        self.greetings = ['start', 'Grbl ']
        self.wait = 0  # default wait period for send(), send_now()
        self.read_thread = None
        self.stop_read_thread = False
        self.send_thread = None
        self.stop_send_thread = False
        self.print_thread = None
        self.readline_buf = []
        self.selector = None
        self.event_handler = PRINTCORE_HANDLER
        # Not all platforms need to do this parity workaround, and some drivers
        # don't support it.  Limit it to platforms that actually require it
        # here to avoid doing redundant work elsewhere and potentially breaking
        # things.
        self.needs_parity_workaround = platform.system(
        ) == "linux" and os.path.exists("/etc/debian")
        for handler in self.event_handler:
            try:
                handler.on_init()
            except:
                logging.error(traceback.format_exc())
        if port is not None and baud is not None:
            self.connect(port, baud)
        self.xy_feedrate = None
        self.z_feedrate = None

    def addEventHandler(self, handler):
        '''
        Adds an event handler.
        
        @param handler: The handler to be added.
        '''
        self.event_handler.append(handler)

    def logError(self, error):
        for handler in self.event_handler:
            try:
                handler.on_error(error)
            except:
                logging.error(traceback.format_exc())
        if self.errorcb:
            try:
                self.errorcb(error)
            except:
                logging.error(traceback.format_exc())
        else:
            logging.error(error)

    @locked
    def disconnect(self):
        """Disconnects from printer and pauses the print
        """
        if self.printer:
            if self.read_thread:
                self.stop_read_thread = True
                if threading.current_thread() != self.read_thread:
                    self.read_thread.join()
                self.read_thread = None
            if self.print_thread:
                self.printing = False
                self.print_thread.join()
            self._stop_sender()
            try:
                if self.selector is not None:
                    self.selector.unregister(self.printer_tcp)
                    self.selector.close()
                    self.selector = None
                if self.printer_tcp is not None:
                    self.printer_tcp.close()
                    self.printer_tcp = None
                self.printer.close()
            except socket.error:
                logger.error(traceback.format_exc())
                pass
            except OSError:
                logger.error(traceback.format_exc())
                pass
        for handler in self.event_handler:
            try:
                handler.on_disconnect()
            except:
                logging.error(traceback.format_exc())
        self.printer = None
        self.online = False
        self.printing = False

    @locked
    def connect(self, port=None, baud=None, dtr=None):
        """Set port and baudrate if given, then connect to printer
        """
        if self.printer:
            self.disconnect()
        if port is not None:
            self.port = port
        if baud is not None:
            self.baud = baud
        if dtr is not None:
            self.dtr = dtr
        if self.port is not None and self.baud is not None:
            # Connect to socket if "port" is an IP, device if not
            host_regexp = re.compile(
                "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$|^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$"
            )
            is_serial = True
            if ":" in self.port:
                bits = self.port.split(":")
                if len(bits) == 2:
                    hostname = bits[0]
                    try:
                        port_number = int(bits[1])
                        if host_regexp.match(
                                hostname) and 1 <= port_number <= 65535:
                            is_serial = False
                    except:
                        pass
            self.writefailures = 0
            if not is_serial:
                self.printer_tcp = socket.socket(socket.AF_INET,
                                                 socket.SOCK_STREAM)
                self.printer_tcp.setsockopt(socket.IPPROTO_TCP,
                                            socket.TCP_NODELAY, 1)
                self.timeout = 0.25
                self.printer_tcp.settimeout(1.0)
                try:
                    self.printer_tcp.connect((hostname, port_number))
                    #a single read timeout raises OSError for all later reads
                    #probably since python 3.5
                    #use non blocking instead
                    self.printer_tcp.settimeout(0)
                    self.printer = self.printer_tcp.makefile('rwb',
                                                             buffering=0)
                    self.selector = selectors.DefaultSelector()
                    self.selector.register(self.printer_tcp,
                                           selectors.EVENT_READ)
                except socket.error as e:
                    if (e.strerror is None): e.strerror = ""
                    self.logError(
                        _("Could not connect to %s:%s:") %
                        (hostname, port_number) + "\n" +
                        _("Socket error %s:") % e.errno + "\n" + e.strerror)
                    self.printer = None
                    self.printer_tcp = None
                    return
            else:
                disable_hup(self.port)
                self.printer_tcp = None
                try:
                    if self.needs_parity_workaround:
                        self.printer = Serial(port=self.port,
                                              baudrate=self.baud,
                                              timeout=0.25,
                                              parity=PARITY_ODD)
                        self.printer.close()
                        self.printer.parity = PARITY_NONE
                    else:
                        self.printer = Serial(baudrate=self.baud,
                                              timeout=0.25,
                                              parity=PARITY_NONE)
                        self.printer.port = self.port
                    try:  #this appears not to work on many platforms, so we're going to call it but not care if it fails
                        self.printer.dtr = dtr
                    except:
                        #self.logError(_("Could not set DTR on this platform")) #not sure whether to output an error message
                        pass
                    self.printer.open()
                except SerialException as e:
                    self.logError(
                        _("Could not connect to %s at baudrate %s:") %
                        (self.port, self.baud) + "\n" +
                        _("Serial error: %s") % e)
                    self.printer = None
                    return
                except IOError as e:
                    self.logError(
                        _("Could not connect to %s at baudrate %s:") %
                        (self.port, self.baud) + "\n" + _("IO error: %s") % e)
                    self.printer = None
                    return
            for handler in self.event_handler:
                try:
                    handler.on_connect()
                except:
                    logging.error(traceback.format_exc())
            self.stop_read_thread = False
            self.read_thread = threading.Thread(target=self._listen,
                                                name='read thread')
            self.read_thread.start()
            self._start_sender()

    def reset(self):
        """Reset the printer
        """
        if self.printer and not self.printer_tcp:
            self.printer.dtr = 1
            time.sleep(0.2)
            self.printer.dtr = 0

    def _readline_buf(self):
        "Try to readline from buffer"
        if len(self.readline_buf):
            chunk = self.readline_buf[-1]
            eol = chunk.find(b'\n')
            if eol >= 0:
                line = b''.join(self.readline_buf[:-1]) + chunk[:(eol + 1)]
                self.readline_buf = []
                if eol + 1 < len(chunk):
                    self.readline_buf.append(chunk[(eol + 1):])
                return line
        return PR_AGAIN

    def _readline_nb(self):
        "Non blocking readline. Socket based files do not support non blocking or timeouting readline"
        if self.printer_tcp:
            line = self._readline_buf()
            if line:
                return line
            chunk_size = 256
            while True:
                chunk = self.printer.read(chunk_size)
                if chunk is SYS_AGAIN and self.selector.select(self.timeout):
                    chunk = self.printer.read(chunk_size)
                #print('_readline_nb chunk', chunk, type(chunk))
                if chunk:
                    self.readline_buf.append(chunk)
                    line = self._readline_buf()
                    if line:
                        return line
                elif chunk is SYS_AGAIN:
                    return PR_AGAIN
                else:
                    #chunk == b'' means EOF
                    line = b''.join(self.readline_buf)
                    self.readline_buf = []
                    self.stop_read_thread = True
                    return line if line else PR_EOF
        else:  # serial port
            return self.printer.readline()

    def _readline(self):
        try:
            line_bytes = self._readline_nb()
            if line_bytes is PR_EOF:
                self.logError(
                    _("Can't read from printer (disconnected?). line_bytes is None"
                      ))
                return PR_EOF
            line = line_bytes.decode('utf-8')

            if len(line) > 1:
                self.log.append(line)
                for handler in self.event_handler:
                    try:
                        handler.on_recv(line)
                    except:
                        logging.error(traceback.format_exc())
                if self.recvcb:
                    try:
                        self.recvcb(line)
                    except:
                        self.logError(traceback.format_exc())
                if self.loud: logging.info("RECV: %s" % line.rstrip())
            return line
        except UnicodeDecodeError:
            self.logError(
                _("Got rubbish reply from %s at baudrate %s:") %
                (self.port, self.baud) + "\n" + _("Maybe a bad baudrate?"))
            return None
        except SelectError as e:
            if 'Bad file descriptor' in e.args[1]:
                self.logError(
                    _("Can't read from printer (disconnected?) (SelectError {0}): {1}"
                      ).format(e.errno, decode_utf8(e.strerror)))
                return None
            else:
                self.logError(
                    _("SelectError ({0}): {1}").format(e.errno,
                                                       decode_utf8(
                                                           e.strerror)))
                raise
        except SerialException as e:
            self.logError(
                _("Can't read from printer (disconnected?) (SerialException): {0}"
                  ).format(decode_utf8(str(e))))
            return None
        except socket.error as e:
            self.logError(
                _("Can't read from printer (disconnected?) (Socket error {0}): {1}"
                  ).format(e.errno, decode_utf8(e.strerror)))
            return None
        except OSError as e:
            if e.errno == errno.EAGAIN:  # Not a real error, no data was available
                return ""
            self.logError(
                _("Can't read from printer (disconnected?) (OS Error {0}): {1}"
                  ).format(e.errno, e.strerror))
            return None

    def _listen_can_continue(self):
        if self.printer_tcp:
            return not self.stop_read_thread and self.printer
        return (not self.stop_read_thread and self.printer
                and self.printer.is_open)

    def _listen_until_online(self):
        while not self.online and self._listen_can_continue():
            self._send("M105")
            if self.writefailures >= 4:
                logging.error(
                    _("Aborting connection attempt after 4 failed writes."))
                return
            empty_lines = 0
            while self._listen_can_continue():
                line = self._readline()
                if line is None: break  # connection problem
                # workaround cases where M105 was sent before printer Serial
                # was online an empty line means read timeout was reached,
                # meaning no data was received thus we count those empty lines,
                # and once we have seen 15 in a row, we just break and send a
                # new M105
                # 15 was chosen based on the fact that it gives enough time for
                # Gen7 bootloader to time out, and that the non received M105
                # issues should be quite rare so we can wait for a long time
                # before resending
                if not line:
                    empty_lines += 1
                    if empty_lines == 15: break
                else: empty_lines = 0
                if line.startswith(tuple(self.greetings)) \
                   or line.startswith('ok') or "T:" in line:
                    self.online = True
                    for handler in self.event_handler:
                        try:
                            handler.on_online()
                        except:
                            logging.error(traceback.format_exc())
                    if self.onlinecb:
                        try:
                            self.onlinecb()
                        except:
                            self.logError(traceback.format_exc())
                    return

    def _listen(self):
        """This function acts on messages from the firmware
        """
        self.clear = True
        if not self.printing:
            self._listen_until_online()
        while self._listen_can_continue():
            line = self._readline()
            if line is None:
                logging.debug('_readline() is None, exiting _listen()')
                break
            if line.startswith('DEBUG_'):
                continue
            if line.startswith(tuple(self.greetings)) or line.startswith('ok'):
                self.clear = True
            if line.startswith('ok') and "T:" in line:
                for handler in self.event_handler:
                    try:
                        handler.on_temp(line)
                    except:
                        logging.error(traceback.format_exc())
                if self.tempcb:
                    # callback for temp, status, whatever
                    try:
                        self.tempcb(line)
                    except:
                        self.logError(traceback.format_exc())
            elif line.startswith('Error'):
                self.logError(line)
            # Teststrings for resend parsing       # Firmware     exp. result
            # line="rs N2 Expected checksum 67"    # Teacup       2
            if line.lower().startswith("resend") or line.startswith("rs"):
                for haystack in ["N:", "N", ":"]:
                    line = line.replace(haystack, " ")
                linewords = line.split()
                while len(linewords) != 0:
                    try:
                        toresend = int(linewords.pop(0))
                        self.resendfrom = toresend
                        break
                    except:
                        pass
                self.clear = True
        self.clear = True
        logging.debug('Exiting read thread')

    def _start_sender(self):
        self.stop_send_thread = False
        self.send_thread = threading.Thread(target=self._sender,
                                            name='send thread')
        self.send_thread.start()

    def _stop_sender(self):
        if self.send_thread:
            self.stop_send_thread = True
            self.send_thread.join()
            self.send_thread = None

    def _sender(self):
        while not self.stop_send_thread:
            try:
                command = self.priqueue.get(True, 0.1)
            except QueueEmpty:
                continue
            while self.printer and self.printing and not self.clear:
                time.sleep(0.001)
            self._send(command)
            while self.printer and self.printing and not self.clear:
                time.sleep(0.001)

    def _checksum(self, command):
        return reduce(lambda x, y: x ^ y, map(ord, command))

    def startprint(self, gcode, startindex=0):
        """Start a print, gcode is an array of gcode commands.
        returns True on success, False if already printing.
        The print queue will be replaced with the contents of the data array,
        the next line will be set to 0 and the firmware notified. Printing
        will then start in a parallel thread.
        """
        if self.printing or not self.online or not self.printer:
            return False
        self.queueindex = startindex
        self.mainqueue = gcode
        self.printing = True
        self.lineno = 0
        self.resendfrom = -1
        if not gcode or not gcode.lines:
            return True

        self.clear = False
        self._send("M110", -1, True)

        resuming = (startindex != 0)
        self.print_thread = threading.Thread(target=self._print,
                                             name='print thread',
                                             kwargs={"resuming": resuming})
        self.print_thread.start()
        return True

    def cancelprint(self):
        self.pause()
        self.paused = False
        self.mainqueue = None
        self.clear = True

    # run a simple script if it exists, no multithreading
    def runSmallScript(self, filename):
        if not filename: return
        try:
            with open(filename) as f:
                for i in f:
                    l = i.replace("\n", "")
                    l = l.partition(';')[0]  # remove comments
                    self.send_now(l)
        except:
            pass

    def pause(self):
        """Pauses the print, saving the current position.
        """
        if not self.printing: return False
        self.paused = True
        self.printing = False

        # ';@pause' in the gcode file calls pause from the print thread
        if not threading.current_thread() is self.print_thread:
            try:
                self.print_thread.join()
            except:
                self.logError(traceback.format_exc())

        self.print_thread = None

        # saves the status
        self.pauseX = self.analyzer.abs_x
        self.pauseY = self.analyzer.abs_y
        self.pauseZ = self.analyzer.abs_z
        self.pauseE = self.analyzer.abs_e
        self.pauseF = self.analyzer.current_f
        self.pauseRelative = self.analyzer.relative
        self.pauseRelativeE = self.analyzer.relative_e

    def resume(self):
        """Resumes a paused print."""
        if not self.paused: return False
        # restores the status
        self.send_now("G90")  # go to absolute coordinates

        xyFeed = '' if self.xy_feedrate is None else ' F' + str(
            self.xy_feedrate)
        zFeed = '' if self.z_feedrate is None else ' F' + str(self.z_feedrate)

        self.send_now("G1 X%s Y%s%s" % (self.pauseX, self.pauseY, xyFeed))
        self.send_now("G1 Z" + str(self.pauseZ) + zFeed)
        self.send_now("G92 E" + str(self.pauseE))

        # go back to relative if needed
        if self.pauseRelative:
            self.send_now("G91")
        if self.pauseRelativeE:
            self.send_now('M83')
        # reset old feed rate
        self.send_now("G1 F" + str(self.pauseF))

        self.paused = False
        self.printing = True
        self.print_thread = threading.Thread(target=self._print,
                                             name='print thread',
                                             kwargs={"resuming": True})
        self.print_thread.start()

    def send(self, command, wait=0):
        """Adds a command to the checksummed main command queue if printing, or
        sends the command immediately if not printing"""

        if self.online:
            if self.printing:
                self.mainqueue.append(command)
            else:
                self.priqueue.put_nowait(command)
        else:
            self.logError(_("Not connected to printer."))

    def send_now(self, command, wait=0):
        """Sends a command to the printer ahead of the command queue, without a
        checksum"""
        if self.online:
            self.priqueue.put_nowait(command)
        else:
            self.logError(_("Not connected to printer."))

    def _print(self, resuming=False):
        self._stop_sender()
        try:
            for handler in self.event_handler:
                try:
                    handler.on_start(resuming)
                except:
                    logging.error(traceback.format_exc())
            if self.startcb:
                # callback for printing started
                try:
                    self.startcb(resuming)
                except:
                    self.logError(
                        _("Print start callback failed with:") + "\n" +
                        traceback.format_exc())
            while self.printing and self.printer and self.online:
                self._sendnext()
            self.sentlines = {}
            self.log.clear()
            self.sent = []
            for handler in self.event_handler:
                try:
                    handler.on_end()
                except:
                    logging.error(traceback.format_exc())
            if self.endcb:
                # callback for printing done
                try:
                    self.endcb()
                except:
                    self.logError(
                        _("Print end callback failed with:") + "\n" +
                        traceback.format_exc())
        except:
            self.logError(
                _("Print thread died due to the following error:") + "\n" +
                traceback.format_exc())
        finally:
            self.print_thread = None
            self._start_sender()

    def process_host_command(self, command):
        """only ;@pause command is implemented as a host command in printcore, but hosts are free to reimplement this method"""
        command = command.lstrip()
        if command.startswith(";@pause"):
            self.pause()

    def _sendnext(self):
        if not self.printer:
            return
        while self.printer and self.printing and not self.clear:
            time.sleep(0.001)
        # Only wait for oks when using serial connections or when not using tcp
        # in streaming mode
        if not self.printer_tcp or not self.tcp_streaming_mode:
            self.clear = False
        if not (self.printing and self.printer and self.online):
            self.clear = True
            return
        if self.resendfrom < self.lineno and self.resendfrom > -1:
            self._send(self.sentlines[self.resendfrom], self.resendfrom, False)
            self.resendfrom += 1
            return
        self.resendfrom = -1
        if not self.priqueue.empty():
            self._send(self.priqueue.get_nowait())
            self.priqueue.task_done()
            return
        if self.printing and self.mainqueue.has_index(self.queueindex):
            (layer, line) = self.mainqueue.idxs(self.queueindex)
            gline = self.mainqueue.all_layers[layer][line]
            if self.queueindex > 0:
                (prev_layer,
                 prev_line) = self.mainqueue.idxs(self.queueindex - 1)
                if prev_layer != layer:
                    for handler in self.event_handler:
                        try:
                            handler.on_layerchange(layer)
                        except:
                            logging.error(traceback.format_exc())
            if self.layerchangecb and self.queueindex > 0:
                (prev_layer,
                 prev_line) = self.mainqueue.idxs(self.queueindex - 1)
                if prev_layer != layer:
                    try:
                        self.layerchangecb(layer)
                    except:
                        self.logError(traceback.format_exc())
            for handler in self.event_handler:
                try:
                    handler.on_preprintsend(gline, self.queueindex,
                                            self.mainqueue)
                except:
                    logging.error(traceback.format_exc())
            if self.preprintsendcb:
                if self.mainqueue.has_index(self.queueindex + 1):
                    (next_layer,
                     next_line) = self.mainqueue.idxs(self.queueindex + 1)
                    next_gline = self.mainqueue.all_layers[next_layer][
                        next_line]
                else:
                    next_gline = None
                gline = self.preprintsendcb(gline, next_gline)
            if gline is None:
                self.queueindex += 1
                self.clear = True
                return
            tline = gline.raw
            if tline.lstrip().startswith(";@"):  # check for host command
                self.process_host_command(tline)
                self.queueindex += 1
                self.clear = True
                return

            # Strip comments
            tline = gcoder.gcode_strip_comment_exp.sub("", tline).strip()
            if tline:
                self._send(tline, self.lineno, True)
                self.lineno += 1
                for handler in self.event_handler:
                    try:
                        handler.on_printsend(gline)
                    except:
                        logging.error(traceback.format_exc())
                if self.printsendcb:
                    try:
                        self.printsendcb(gline)
                    except:
                        self.logError(traceback.format_exc())
            else:
                self.clear = True
            self.queueindex += 1
        else:
            self.printing = False
            self.clear = True
            if not self.paused:
                self.queueindex = 0
                self.lineno = 0
                self._send("M110", -1, True)

    def _send(self, command, lineno=0, calcchecksum=False):
        # Only add checksums if over serial (tcp does the flow control itself)
        if calcchecksum and not self.printer_tcp:
            prefix = "N" + str(lineno) + " " + command
            command = prefix + "*" + str(self._checksum(prefix))
            if "M110" not in command:
                self.sentlines[lineno] = command
        if self.printer:
            self.sent.append(command)
            # run the command through the analyzer
            gline = None
            try:
                gline = self.analyzer.append(command, store=False)
            except:
                logging.warning(
                    _("Could not analyze command %s:") % command + "\n" +
                    traceback.format_exc())
            if self.loud:
                logging.info("SENT: %s" % command)

            for handler in self.event_handler:
                try:
                    handler.on_send(command, gline)
                except:
                    logging.error(traceback.format_exc())
            if self.sendcb:
                try:
                    self.sendcb(command, gline)
                except:
                    self.logError(traceback.format_exc())
            try:
                self.printer.write((command + "\n").encode('ascii'))
                if self.printer_tcp:
                    try:
                        self.printer.flush()
                    except socket.timeout:
                        pass
                self.writefailures = 0
            except socket.error as e:
                if e.errno is None:
                    self.logError(
                        _("Can't write to printer (disconnected ?):") + "\n" +
                        traceback.format_exc())
                else:
                    self.logError(
                        _("Can't write to printer (disconnected?) (Socket error {0}): {1}"
                          ).format(e.errno, decode_utf8(e.strerror)))
                self.writefailures += 1
            except SerialException as e:
                self.logError(
                    _("Can't write to printer (disconnected?) (SerialException): {0}"
                      ).format(decode_utf8(str(e))))
                self.writefailures += 1
            except RuntimeError as e:
                self.logError(
                    _("Socket connection broken, disconnected. ({0}): {1}").
                    format(e.errno, decode_utf8(e.strerror)))
                self.writefailures += 1
Example #50
0
class UBXStreamer:
    """
    UBXStreamer class.
    """
    def __init__(self, port, baudrate, timeout=5):
        """
        Constructor.
        """

        self._serial_object = None
        self._serial_thread = None
        self._ubxreader = None
        self._connected = False
        self._reading = False
        self._port = port
        self._baudrate = baudrate
        self._timeout = timeout

    def __del__(self):
        """
        Destructor.
        """

        self.stop_read_thread()
        self.disconnect()

    def connect(self):
        """
        Open serial connection.
        """

        try:
            self._serial_object = Serial(self._port,
                                         self._baudrate,
                                         timeout=self._timeout)
            self._ubxreader = UBXReader(BufferedReader(self._serial_object),
                                        False)
            self._connected = True
        except (SerialException, SerialTimeoutException) as err:
            print(f"Error connecting to serial port {err}")

    def disconnect(self):
        """
        Close serial connection.
        """

        if self._connected and self._serial_object:
            try:
                self._serial_object.close()
            except (SerialException, SerialTimeoutException) as err:
                print(f"Error disconnecting from serial port {err}")
        self._connected = False

    def start_read_thread(self):
        """
        Start the serial reader thread.
        """

        if self._connected:
            self._reading = True
            self._serial_thread = Thread(target=self._read_thread, daemon=True)
            self._serial_thread.start()

    def stop_read_thread(self):
        """
        Stop the serial reader thread.
        """

        if self._serial_thread is not None:
            self._reading = False

    def send(self, data):
        """
        Send data to serial connection.
        """

        self._serial_object.write(data)

    def flush(self):
        """
        Flush input buffer
        """

        self._serial_object.reset_input_buffer()

    def waiting(self):
        """
        Check if any messages remaining in the input buffer
        """

        return self._serial_object.in_waiting

    def _read_thread(self):
        """
        THREADED PROCESS
        Reads and parses UBX message data from stream
        """

        while self._reading and self._serial_object:
            if self._serial_object.in_waiting:
                try:
                    (_, parsed_data) = self._ubxreader.read()
                    if parsed_data:
                        print(parsed_data)
                except (
                        ube.UBXStreamError,
                        ube.UBXMessageError,
                        ube.UBXTypeError,
                        ube.UBXParseError,
                ) as err:
                    print(f"Something went wrong {err}")
                    continue

    def poll_uart(self, layer=0):
        """
        Poll the current BBR UART1/2 configuration
        """

        position = 0
        keys = ["CFG_UART1_BAUDRATE", "CFG_UART2_BAUDRATE"]
        msg = UBXMessage.config_poll(layer, position, keys)
        ubp.send(msg.serialize())

    def set_uart(self, layers=1):
        """
        Set the current BBR UART1/2 configuration
        """

        transaction = 0
        cfgData = [("CFG_UART1_BAUDRATE", 115200),
                   ("CFG_UART2_BAUDRATE", 57600)]
        msg = UBXMessage.config_set(layers, transaction, cfgData)
        ubp.send(msg.serialize())

    def unset_uart(self, layers=1):
        """
        Unset (del) the current BBR UART1/2 configuration
        """

        transaction = 0
        keys = ["CFG_UART1_BAUDRATE", "CFG_UART2_BAUDRATE"]
        msg = UBXMessage.config_del(layers, transaction, keys)
        ubp.send(msg.serialize())
Example #51
0
class Serial_instrument(Instrument):
    def __init__(self):
        # Initialize shared Instrument superclass attributes...
        super().__init__()

        self.ser = Serial()
        self.ser.baudrate = self.baudrate
        self.ser.timeout = self.timeout
        self.port = None
        self.capfile = "save/Serial_instrument.log"  # Default should be overridden in instrument-specific module
        self.echo = False  # Flag to enable printing to user display whatever is written to capfile

    def set_timeout(self, t):
        self.ser.timeout = t

    def set_baudrate(self, b):
        self.ser.baudrate = b

    def set_serialport(self):
        ports = [port for port in list_ports.comports()]
        portmenu = [
            "%s - %s" % (port.device, port.description) for port in ports
        ]

        # Present port selection menu to user...
        userselection = common.dynamicmenu_get("Select an available port",
                                               portmenu,
                                               lastitem=('C', 'Cancel'))
        if not userselection:
            # Cancelled by user...
            return False

        port_id = int(userselection)
        self.port = ports[port_id]
        self.ser.port = self.port[0]
        return True

    def serialport_open(self):
        """Open connection to a serial port and initialize a log file."""
        while not self.port:
            # No port chosen, try to choose one...
            if not self.set_serialport():
                again = input("Would you like to try to connect again? y/[n] ")
                if again.lower() != "y":
                    # Cancelled by user...
                    return False
        try:
            #print("Setting a %d sec timeout..." % self.ser.timeout)
            self.ser.open()
        except BaseException as msg:
            input("\nError! %s [Press ENTER to continue]..." % msg)
            return False
        print("Connected to %s." % self.port)
        with open(self.capfile, "w") as capfile:
            self.capfileheader = " ".join(
                ("=" * 22,
                 "Session log - %s" % dt.now().strftime("%Y/%m/%d %H:%M:%S"),
                 "=" * 22, "\r\n"))
            capfile.write(self.capfileheader)
        return True

    def cap_cmd(self, cmd):
        """
		Send a single commmand cmd to an instrument. Write the reply to the
		capture file. If instrument echoes the command, the command will also
		be captured.
		"""
        self.ser.reset_input_buffer()
        self.send_cmd(cmd)
        self.cap_buf()
        return True

    def get_cmd(self, cmd):
        """
		Use this to send a command to an instrument using cap_cmd, then return
		the contents of the reply buffer
		"""
        self.cap_cmd(cmd)
        return self.buf

    def send_cmd(self, cmd):
        return self.ser.write((cmd + '\r\n').encode('ascii'))

    def read_reply(self):
        # Read incoming serial input and store in a buffer until no new bytes are
        # received for duration of the timeout.
        self.buf = self.ser.read(self.ser.in_waiting).decode('ascii')
        while True:
            cur = self.buf
            self.buf += self.ser.read(1).decode('ascii')
            if cur == self.buf:
                return True

    def cap_buf(self):
        # Read serial input and append to the capture file.
        self.read_reply()
        self.capfile_append(self.buf)
        return True

    def connect(self):
        # Wrapper to open a serial connection.
        while not self.connected():
            if not self.serialport_open():
                common.usercancelled()
                return True
        return True

    def connected(self):
        # Wrapper to test for open serial port. Returns True of False.
        return self.ser.is_open

    def disconnect(self):
        # Wrapper to close a serial connection. Returns True or False.
        self.ser.close()
        return not self.ser.is_open

    def capfile_append(self, lines):
        # Append text to a capture file. Pass text to append as lines.
        with open(self.capfile, 'a') as capfile:
            capfile.write(lines)
        if self.echo:
            print(lines)

    def buffer_empty(self):
        # Check for unread bytes in serial input buffer. Returns True of False.
        if not self.ser.in_waiting:
            return True
        else:
            return False

    def rename_capfile(self, dst):
        # Renames the active capture file. Useful when title is not known at the time
        # the capture file is first opened. This will silently clobber the destination
        # file if it already exists.
        if common.rename_file(self.capfile, dst):
            return True
        else:
            return False
Example #52
0
from serial import Serial
import time

serial_port = Serial(port='/dev/cu.usbmodem143101', baudrate=9600)
if serial_port.isOpen():
    serial_port.close()
serial_port.open()

time.sleep(1)
lu = serial_port.readline()
chaine = lu.decode('ascii')
print(chaine)

serial_port.write(b'HELLO \r')

time.sleep(1)
lu = serial_port.readline()
chaine = lu.decode('ascii')
print(chaine)
print("entrer quit pour quitter")
while 1:
    commande = input("Entrez une commande : ")
    if commande == 'quit':
        break

    commande += "\r"
    serial_port.write(commande.encode())

serial_port.close()
Example #53
0
class ComConnection(object):
    """Serial wrapper which can be instantiated using serial number"""

    def __init__(self, serial_number=None, command=None, baudrate=9600):
        """
        Constructor

        Parameters
        ----------
        serial_number: string
            The usb-serial's serial number
        command: string
            Command to be send
        baudrate: int
            Baud rate such as 9600 or 115200 etc. Default is 9600
        """
        self.serial_number = serial_number
        self.command = command
        self.serial = Serial()
        self.serial.baudrate = baudrate

    def __del__(self):
        """Destructor"""
        try:
            self.close()
        except:
            pass  # errors on shutdown

    def __str__(self):
        return "SRN: {} Command: {}".format(self.serial_number, self.command)

    def get_device_name(self, serial_number):
        """
        Get full device name/path from serial number

        Parameters
        ----------
        serial_number: string
            The usb-serial's serial number

        Returns
        -------
        string
            Full device name/path, e.g. /dev/ttyUSBx (on *.nix system or COMx on Windows)

        Raises
        ------
        IOError
            When not found device with this serial number

        """
        serial_numbers = []
        for pinfo in comports():
            if str(pinfo.serial_number).strip() == str(serial_number).strip():
                return pinfo.device
            # save list of serial numbers for user reference
            serial_numbers.append(pinfo.serial_number.encode('utf-8'))
        raise IOError('Could not find device with provided serial number {}Found devices with following serial numbers: {}{}'.format(linesep, linesep, serial_numbers))

    def connect(self):
        """
        Open/connect to serial port

        """
        # open serial port
        try:
            device = self.get_device_name(self.serial_number)
            self.serial.port = device
            # Set RTS line to low logic level
            self.serial.rts = False
            self.serial.open()
        except Exception as ex:
            self.handle_serial_error(ex)

    def send_command(self):
        """
        Send data/command to serial port
        """
        if self.serial.is_open:
            try:
                # Unicode strings must be encoded
                data = self.command.encode('utf-8')
                self.serial.write(data)
            except Exception as ex:
                self.handle_serial_error(ex)
        else:
            raise IOError('Try to send data when the connection is closed')

    def receive_command(self):
        """Receive command from serial port"""
        if self.serial.is_open:
            return self.serial.read_all()

    def close(self):
        """Close all resources"""
        self.serial.close()

    def handle_serial_error(self, error=None):
        """Serial port error"""
        # terminate connection
        self.close()
        # forward exception
        if isinstance(error, Exception):
            raise error  # pylint: disable-msg=E0702
Example #54
0
class UBXStreamer:
    """
    UBXStreamer class.
    """
    def __init__(self, port, baudrate, timeout=5):
        """
        Constructor.
        """

        self._serial_object = None
        self._serial_thread = None
        self._ubxreader = None
        self._connected = False
        self._reading = False
        self._port = port
        self._baudrate = baudrate
        self._timeout = timeout

    def __del__(self):
        """
        Destructor.
        """

        self.stop_read_thread()
        self.disconnect()

    def connect(self):
        """
        Open serial connection.
        """

        try:
            self._serial_object = Serial(self._port,
                                         self._baudrate,
                                         timeout=self._timeout)
            self._ubxreader = UBXReader(BufferedReader(self._serial_object),
                                        False)
            self._connected = True
        except (SerialException, SerialTimeoutException) as err:
            print(f"Error connecting to serial port {err}")

    def disconnect(self):
        """
        Close serial connection.
        """

        if self._connected and self._serial_object:
            try:
                self._serial_object.close()
            except (SerialException, SerialTimeoutException) as err:
                print(f"Error disconnecting from serial port {err}")
        self._connected = False

    def start_read_thread(self):
        """
        Start the serial reader thread.
        """

        if self._connected:
            self._reading = True
            self._serial_thread = Thread(target=self._read_thread,
                                         daemon=False)
            self._serial_thread.start()

    def stop_read_thread(self):
        """
        Stop the serial reader thread.
        """

        if self._serial_thread is not None:
            self._reading = False
            self._serial_thread.join()

    def send(self, data):
        """
        Send data to serial connection.
        """

        self._serial_object.write(data)

    def flush(self):
        """
        Flush input buffer
        """

        self._serial_object.reset_input_buffer()

    def waiting(self):
        """
        Check if any messages remaining in the input buffer
        """

        return self._serial_object.in_waiting

    def _read_thread(self):
        """
        THREADED PROCESS
        Reads and parses UBX message data from stream
        """

        while self._reading and self._serial_object:
            if self._serial_object.in_waiting:
                try:
                    (raw_data, parsed_data) = self._ubxreader.read()
                    #                     if raw_data:
                    #                         print(raw_data)
                    if parsed_data:
                        print(parsed_data)
                except (
                        ube.UBXStreamError,
                        ube.UBXMessageError,
                        ube.UBXTypeError,
                        ube.UBXParseError,
                ) as err:
                    print(f"Something went wrong {err}")
                    continue
Example #55
0
class SerialSensors:
    def __init__(self):

        self.serial = Serial()
        self.lastReading = "No Data=0\n"
        self.getParams()
        self.portSem = Semaphore()
        self.varSem = Semaphore()
        self.recThread = Thread(target=self.recieve)
        self.txThread = Thread(target=self.transmit)

    def getParams(self):

        try:
            f = open("serialParams.config", "r")
            lines = f.readlines()
            f.close()

            lines = [line.replace("\n", "") for line in lines]
            lines = [line.split("=") for line in lines]

            params = {}

            for line in lines:
                params.update({line[0].lower(): line[1]})

            self.serial.port = "COM1" if "port" not in params else params[
                "port"]
            self.serial.baud = 9600 if "baud" not in params else int(
                params["baud"])
            self.serial.timeout = 3 if "timeout" not in params else int(
                params["timeout"])

        except:
            self.serial.port = "COM1"
            self.serial.baud = 9600
            self.serial.timeout = 3

    def recieve(self):

        while self.run:
            try:

                self.portSem.acquire()
                result = self.serial.readline().decode("utf-8").replace(
                    "\n", "")
                self.portSem.release()

                if "=" in result:
                    self.varSem.acquire()
                    self.lastReading = result
                    self.varSem.release()

                sleep(0.5)

            except:
                sleep(0.5)

    def transmit(self):

        while self.run:

            try:
                self.portSem.acquire()
                self.serial.write(b".")
                self.portSem.release()
            except:
                pass

            sleep(2)

        try:
            self.portSem.acquire()
            self.serial.write(b"*")
            self.portSem.release()
        except:
            pass

    def getData(self):
        self.varSem.acquire()
        result = self.lastReading
        self.varSem.release()
        return result

    def start(self):
        self.serial.open()
        self.run = True
        self.recThread.start()
        self.txThread.start()

    def stop(self):
        self.run = False
        self.txThread.join()
        self.recThread.join()
        self.serial.close()
Example #56
0
class USBSerial:
    def __init__(self, port, baudrate, timeout = 0.1, write_timeout = 0.11, open = False):
        '''
        init method
        if open is set True then call open_serial()
        '''
        self._port = port
        self._baudrate = baudrate
        self._timeout = timeout
        self._write_timeout = write_timeout
        self.serial = None
        if open:
            self.open_serial()

    @property
    def port(self):
        return self._port

    @port.setter
    def port(self, port):
        '''
        port setter method
        if serial was opened
        - Close serial
        - Open serial
        '''
        self._port = port
        if not self.serial:
            self.close_serial()
            self.open_serial()
    
    @property
    def baudrate(self):
        return self._baudrate
    
    @property
    def timeout(self):
        return self._timeout

    def open_serial(self):
        if not self.serial:
            self.close_serial()
        try:
            self.serial = Serial(port = self._port, baudrate = self._baudrate, timeout = self._timeout)

        except Exception as inst:
            print(type(inst))    # the exception instance
            print(inst.args)     # arguments stored in .args
            print(inst)   
            print('Error : Can not open Serial, Retry!')
            return False
        return True

    def close_serial(self):
        if self.serial:
            self.serial.close()
        self.serial = None

    def write(self, message):
        if self.serial:
            if type(message) is not str:
                message = str(message)
            message += '\n'
            self.serial.write(bytes(message.encode()))
    
    def readline(self):
        if not self.serial:
            if not self.open_serial():
                return

        return self.serial.readline().decode('utf-8').strip()
        
    def read(self, size = 1):
        if not self.serial:
            if not self.open_serial():
                return

        return self.serial.read(size)

    def flush(self):
        self.serial.flush()

    def test(self):
        '''
        Print out status
        '''
        if self:
            if self.serial:
                print('> Serial is opened')
            else:
                print('> Serial is not opened')
            if self.port:
                print('Port : %s'%(self.port))
            if self._baudrate:
                print('Baudrate : %s'%(self._baudrate))
            if self._timeout:
                print('Timeout : %s'%(self._timeout))
Example #57
0
class SerialTNC(APRSPacketSource):
    """
    listens for raw APRS frames being sent over USB `in ASCII text`

    An example of this is the Kenwood TNC.

    >>> tnc = SerialTNC(serial_port='COM5')
    >>> print(tnc.packets)

    alternatively, set to `'auto'` to connect to the first open serial port

    >>> tnc = SerialTNC(serial_port='auto')
    >>> print(tnc.packets)
    """

    def __init__(self, serial_port: str = None, callsigns: List[str] = None):
        """
        Connect to TNC over given serial port.

        :param serial_port: port name
        :param callsigns: list of callsigns to return from source
        """

        if serial_port is None or serial_port == "" or serial_port == "auto":
            try:
                serial_port = next_open_serial_port()
            except ConnectionError:
                raise ConnectionError("could not find TNC connected to serial")
        else:
            serial_port = serial_port.strip('"')

        self.serial_connection = Serial(serial_port, baudrate=9600, timeout=1)
        super().__init__(self.serial_connection.port, callsigns)
        self.__last_access_time = None

    @property
    def packets(self) -> List[APRSPacket]:
        if self.__last_access_time is not None and self.interval is not None:
            interval = datetime.now() - self.__last_access_time
            if interval < self.interval:
                raise TimeIntervalError(
                    f"interval {interval} less than minimum interval {self.interval}"
                )
        packets = []
        for line in self.serial_connection.readlines():
            try:
                packet = APRSPacket.from_frame(line, source=self.location)
                packets.append(packet)
            except Exception as error:
                logging.error(f"{error.__class__.__name__} - {error}")
        if self.callsigns is not None:
            packets = [
                packet for packet in packets if packet.from_callsign in self.callsigns
            ]
        self.__last_access_time = datetime.now()
        return packets

    def close(self):
        self.serial_connection.close()

    def __repr__(self):
        return (
            f"{self.__class__.__name__}({repr(self.location)}, {repr(self.callsigns)})"
        )
Example #58
0
class Arduino:
    ''' Configuration Parameters
    '''
    N_ANALOG_PORTS = 6
    N_DIGITAL_PORTS = 12

    def __init__(self, port="/dev/ttyUSB0", baudrate=57600, timeout=0.5):

        self.PID_RATE = 30  # Do not change this!  It is a fixed property of the Arduino PID controller.
        self.PID_INTERVAL = 1000 / 30

        self.port = port
        self.baudrate = baudrate
        self.timeout = timeout
        self.encoder_count = 0
        self.writeTimeout = timeout
        self.interCharTimeout = timeout / 30.

        # Keep things thread safe
        self.mutex = thread.allocate_lock()

        # An array to cache analog sensor readings
        self.analog_sensor_cache = [None] * self.N_ANALOG_PORTS

        # An array to cache digital sensor readings
        self.digital_sensor_cache = [None] * self.N_DIGITAL_PORTS

    def connect(self):
        try:
            print "Connecting to Arduino on port", self.port, "..."
            self.port = Serial(port=self.port,
                               baudrate=self.baudrate,
                               timeout=self.timeout,
                               writeTimeout=self.writeTimeout)
            # The next line is necessary to give the firmware time to wake up.
            time.sleep(1)
            test = self.get_baud()
            if test != self.baudrate:
                time.sleep(1)
                test = self.get_baud()
                if test != self.baudrate:
                    raise SerialException
            print "Connected at", self.baudrate
            print "Arduino is ready."

        except SerialException:
            print "Serial Exception:"
            print sys.exc_info()
            print "Traceback follows:"
            traceback.print_exc(file=sys.stdout)
            print "Cannot connect to Arduino!"
            os._exit(1)

    def open(self):
        ''' Open the serial port.
        '''
        self.port.open()

    def close(self):
        ''' Close the serial port.
        '''
        self.port.close()

    def send(self, cmd):
        ''' This command should not be used on its own: it is called by the execute commands
            below in a thread safe manner.
        '''
        self.port.write(cmd + '\r')

    def recv(self, timeout=0.5):
        timeout = min(timeout, self.timeout)
        ''' This command should not be used on its own: it is called by the execute commands   
            below in a thread safe manner.  Note: we use read() instead of readline() since
            readline() tends to return garbage characters from the Arduino
        '''
        c = ''
        value = ''
        attempts = 0
        while c != '\r':
            c = self.port.read(1)
            value += c
            attempts += 1
            if attempts * self.interCharTimeout > timeout:
                return None

        value = value.strip('\r')

        return value

    def recv_ack(self):
        ''' This command should not be used on its own: it is called by the execute commands
            below in a thread safe manner.
        '''
        ack = self.recv(self.timeout)
        return ack == 'OK'

    def recv_int(self):
        ''' This command should not be used on its own: it is called by the execute commands
            below in a thread safe manner.
        '''
        value = self.recv(self.timeout)
        try:
            return int(value)
        except:
            return None

    def recv_array(self):
        ''' This command should not be used on its own: it is called by the execute commands
            below in a thread safe manner.
        '''
        try:
            values = self.recv(self.timeout * self.N_ANALOG_PORTS).split()
            return map(int, values)
        except:
            return []

    def execute(self, cmd):
        ''' Thread safe execution of "cmd" on the Arduino returning a single integer value.
        '''
        self.mutex.acquire()

        try:
            self.port.flushInput()
        except:
            pass

        ntries = 1
        attempts = 0

        try:
            self.port.write(cmd + '\r')
            value = self.recv(self.timeout)
            while attempts < ntries and (value == ''
                                         or value == 'Invalid Command'
                                         or value == None):
                try:
                    self.port.flushInput()
                    self.port.write(cmd + '\r')
                    value = self.recv(self.timeout)
                except:
                    print "Exception executing command: " + cmd
                attempts += 1
        except:
            self.mutex.release()
            print "Exception executing command: " + cmd
            value = None

        self.mutex.release()
        return int(value)

    def execute_array(self, cmd):
        ''' Thread safe execution of "cmd" on the Arduino returning an array.
        '''
        self.mutex.acquire()

        try:
            self.port.flushInput()
        except:
            pass

        ntries = 1
        attempts = 0

        try:
            self.port.write(cmd + '\r')
            values = self.recv_array()
            while attempts < ntries and (values == ''
                                         or values == 'Invalid Command'
                                         or values == [] or values == None):
                try:
                    self.port.flushInput()
                    self.port.write(cmd + '\r')
                    values = self.recv_array()
                except:
                    print("Exception executing command: " + cmd)
                attempts += 1
        except:
            self.mutex.release()
            print "Exception executing command: " + cmd
            raise SerialException
            return []

        try:
            values = map(int, values)
        except:
            values = []

        self.mutex.release()
        return values

    def execute_ack(self, cmd):
        ''' Thread safe execution of "cmd" on the Arduino returning True if response is ACK.
        '''
        self.mutex.acquire()

        try:
            self.port.flushInput()
        except:
            pass

        ntries = 1
        attempts = 0

        try:
            self.port.write(cmd + '\r')
            #print cmd
            ack = self.recv(self.timeout)
            while attempts < ntries and (ack == '' or ack == 'Invalid Command'
                                         or ack == None):
                try:
                    self.port.flushInput()
                    self.port.write(cmd + '\r')
                    ack = self.recv(self.timeout)
                except:
                    print "Exception executing command: " + cmd
            attempts += 1
        except:
            self.mutex.release()
            print "execute_ack exception when executing", cmd
            print sys.exc_info()
            return 0

        self.mutex.release()
        return ack == 'OK'

    #def update_pid(self, Kp, Kd, Ki, Ko):
    #''' Set the PID parameters on the Arduino
    #'''
    #print "Updating PID parameters"
    #cmd = 'u ' + str(Kp) + ':' + str(Kd) + ':' + str(Ki) + ':' + str(Ko)
    #self.execute_ack(cmd)

    def update_pid(self, left_Kp, left_Kd, left_Ki, left_Ko, right_Kp,
                   right_Kd, right_Ki, right_Ko):
        ''' Set the PID parameters on the Arduino
        '''
        print "Updating PID parameters"
        cmd = 'u ' + str(left_Kp) + ':' + str(left_Kd) + ':' + str(
            left_Ki) + ':' + str(left_Ko) + ':' + str(right_Kp) + ':' + str(
                right_Kd) + ':' + str(right_Ki) + ':' + str(right_Ko)
        #print "update_pid command: " + cmd
        self.execute_ack(cmd)

    def get_baud(self):
        ''' Get the current baud rate on the serial port.
        '''
        return int(self.execute('b'))

    def get_encoder_counts(self):
        values = self.execute_array('e')
        if len(values) not in [2, 4]:
            print "Encoder count was not 2 or 4 for 4wd"
            raise SerialException
            return None
        else:
            return values

    def reset_encoders(self):
        ''' Reset the encoder counts to 0
        '''
        return self.execute_ack('r')

    def drive(self, right, left):
        ''' Speeds are given in encoder ticks per PID interval
        '''
        return self.execute_ack('m %d %d' % (right, left))

    def drive_m_per_s(self, right, left):
        ''' Set the motor speeds in meters per second.
        '''
        left_revs_per_second = float(left) / (self.wheel_diameter * PI)
        right_revs_per_second = float(right) / (self.wheel_diameter * PI)

        left_ticks_per_loop = int(left_revs_per_second *
                                  self.encoder_resolution * self.PID_INTERVAL *
                                  self.gear_reduction)
        right_ticks_per_loop = int(right_revs_per_second *
                                   self.encoder_resolution *
                                   self.PID_INTERVAL * self.gear_reduction)

        self.drive(right_ticks_per_loop, left_ticks_per_loop)

    def stop(self):
        ''' Stop both motors.
        '''
        self.drive(0, 0)

    def analog_read(self, pin):
        return self.execute('a %d' % pin)

    def analog_write(self, pin, value):
        return self.execute_ack('x %d %d' % (pin, value))

    def digital_read(self, pin):
        return self.execute('d %d' % pin)

    def digital_write(self, pin, value):
        return self.execute_ack('w %d %d' % (pin, value))

    def pin_mode(self, pin, mode):
        return self.execute_ack('c %d %d' % (pin, mode))

    def servo_write(self, id, pos):
        ''' Usage: servo_write(id, pos)
            Position is given in radians and converted to degrees before sending
        '''
        return self.execute_ack(
            's %d %d' %
            (id, int(min(SERVO_MAX, max(SERVO_MIN, degrees(pos))))))

    def servo_read(self, id):
        ''' Usage: servo_read(id)
            The returned position is converted from degrees to radians
        '''
        return radians(self.execute('t %d' % id))

    def ping(self, pin):
        ''' The srf05/Ping command queries an SRF05/Ping sonar sensor
            connected to the General Purpose I/O line pinId for a distance,
            and returns the range in cm.  Sonar distance resolution is integer based.
        '''
        return self.execute('p %d' % pin)

    def get_pidin(self):
        values = self.execute_array('i')
        print("pidin_raw_data: " + str(values))
        if len(values) not in [2, 4]:
            print "pidin was not 2 or 4 for 4wd"
            raise SerialException
            return None
        else:
            return values

    def get_pidout(self):
        values = self.execute_array('f')
        print("pidout_raw_data: " + str(values))
        if len(values) not in [2, 4]:
            print "pidout was not 2 or 4 for 4wd"
            raise SerialException
            return None
        else:
            return values
def list_ports():
    """ Lists serial port names

        :raises EnvironmentError:
            On unsupported or unknown platforms
        :returns:
            A list of the serial ports available on the system
    """
    if sys.platform.startswith('win'):
        ports = ['COM%s' % (i + 1) for i in range(256)]
    elif sys.platform.startswith('linux') or sys.platform.startswith('cygwin'):
        # this excludes your current terminal "/dev/tty"
        ports = glob.glob('/dev/tty[A-Za-z]*')
    elif sys.platform.startswith('darwin'):
        ports = glob.glob('/dev/tty.*')
    else:
        raise EnvironmentError('Unsupported platform')

    result = []
    for port in ports:
        try:
            s = Serial(port)
            s.close()
            result.append(port)
        except (OSError, SerialException):
            pass
    return result
Example #60
-1
  def update(self, red, green, blue, time = 10):
    """ Change the device to the requested color for the period specified.

      @param red the red component of the color (0 to 255)
      @param green the green component of the color (0 to 255)
      @param blue the blue component of the color (0 to 255)
      @param time the time (in seconds) to hold the color.

      @return true if the command was sucessfuly sent to the device.
    """
    # Set up the serial port
    port = None
    try:
      port = Serial(self._port, baudrate = 57600, timeout = 0.2)
    except:
      return False
    # Write the data
    data = "!%c%c%c%c\n" % (
      trimValue(red),
      trimValue(green),
      trimValue(blue),
      trimValue(time)
      )
    for ch in data:
      port.write(ch)
      sleep(0.01)
    # All done
    port.close()
    return True