def send(message):
    ser = Serial("COM3", baudrate=57600)
    ser.flush()
    ser.write(message.encode())
    sleep(0.1)
    if ser.inWaiting():
        print(ser.readline().decode().rstrip('\r\n').split(",")[0])
Example #2
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 #3
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
Example #4
0
class Arduino:

	def __init__(self, serialport):
		"""Takes the string of the serial port
		and connects to that port, binding the
		Arduino object to it.
		"""
		print('Instanciado Arduino dispositivo %s' % serialport)
		try:
			self.serialport = Serial(serialport, 9600)
			self.error = False
			self.id = None
		except:
			self.error = True
			self.id = -666
			raise

	def read_byte(self, block=False):
		"""Lee un byte.
		Si block=True lee con espera activa hasta
		que exista algún byte que leer, porque no
		funciona sin espera activa.
		"""
		if block == False and self.serialport.inWaiting() < 1:
			return None
		return self.serialport.read(1);


	def read_until(self, until):
		buffer = []
		while buffer[-1] != until:
			if self.serialport.inWaiting() < 1:
				return buffer
			buffer += self.serialport.read(1);
		return buffer

	def write(self, str):
		return self.serialport.write(str)

	def write_byte(self, byte):
		return self.serialport.write(chr(byte))

	def get_id(self):
		if self.error:
			return self.id

		if self.id != None:
			return self.id

		# Consume all bytes for this query
		self.serialport.flushInput()
		print 'Lendo o ID..'
		while self.id == None:
			self.write_byte(QUERY_IDENT)
			self.id = self.serialport.read(1)
			self.id = ord(self.id)
			self.serialport.flush()
			self.serialport.flushInput()
		return self.id
Example #5
0
class SrfStickCommunication:
    def __init__(self, usb_port_number):
        port = '/dev/ttyACM{}'.format(usb_port_number)
        baudrate = 115200
        timeout = 1

        print("opening connection...")
        self.connection = Serial(port=port, baudrate=baudrate, timeout=timeout)
        self.flush_input_buffer()
        self.connection.flush()

    def __enter__(self):
        return self

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

    def close(self):
        print("closing connection...")
        self.connection.close()

    def flush_input_buffer(self):
        timeout = False
        while not timeout:
            response = self.connection.read(1)
            if response == '':
                timeout = True

    def set_frequency(self, frequency):
        if not self.send_srf_commands(["+++", "ATCN{}\r".format(frequency), "ATAC\r", "ATDN\r"]):
            sys.stderr.write("ERROR: Failed to set frequency.\n")
            self.close()

    def send_srf_commands(self, commands):
        for command in commands:
            print(command)
            if not self.send_srf_command(command):
                return False
        return True

    def send_srf_command(self, command):
        self.connection.write(command)
        self.connection.flush()

        response = self.connection.read(2)
        if not response:
            sleep(3)
            response = self.connection.read(2)

        self.connection.reset_input_buffer()
        if response == "OK":
            return True
        else:
            if command[-1] == '\r':
                command = command[:-1]
            sys.stderr.write("ERROR: command '{}' returned '{}'.\n".format(command, response))
            return False
Example #6
0
class LightStrip(object):
    def __init__(self, port='/dev/ttyUSB0'):
        self.ser = Serial(port=port, baudrate=115200, timeout=1)
        time.sleep(0)  # wait for a arduino reset to pass
        self.ser.flush()
    def send(self, rgbs):
        assert len(rgbs) == 15, rgbs
        packet = "\x60" + ''.join(chr(int(r))+chr(int(g))+chr(int(b)) for r,g,b in rgbs)
        self.ser.write(packet)
Example #7
0
class EEPROM():
    def __init__(self, rom_size=8192):
        self.RECSIZE = 16
        self.port = None
        self.rom_size = rom_size

    def open_port(self, tty_port="/dev/tty.usbserial-1420"):
        if isinstance(tty_port, str):
            try:
                self.port = Serial(tty_port, timeout=0.1, dsrdtr=True)
            except SerialException as err:
                raise EEPROMException(err)
        else:
            self.port = tty_port

    def __del__(self):
        self.close()

    def close(self):
        if self.port:
            self.port.close()

    def read(self, addr):
        cmd = str.encode("R" + address_field(addr) + chr(10))
        self.send_cmd(cmd)
        response = self.port.readline().upper()
        self.wait_okay()
        return response

    def write(self, addr, data):
        cmd = str.encode("W" + address_field(addr) + ":" + data_field(data) +
                         chr(10))
        self.send_cmd(cmd)
        self.wait_okay()
        return cmd

    def wait_okay(self):
        retries = 0
        resp = self.port.readline()
        while resp != OK:
            print("RESP:", resp)
            retries += 1
            if retries > 5:
                self.port.close()
                sys.exit("Didn't receive OK back from programmer.\n")
            resp = self.port.readline()

    def version(self):
        cmd = str.encode("V" + chr(10))
        self.send_cmd(cmd)
        response = self.port.readline().upper()
        return response.decode('UTF-8')

    def send_cmd(self, cmd):
        self.port.write(cmd)
        self.port.flush()
Example #8
0
class Iridium(Device):
    PORT = '/dev/serial0'
    BAUDRATE = 19200

    def __init__(self):
        super().__init__('Iridium')
        self.serial: Serial = None

    def flush(self):
        """
        Clears the serial buffer
        :return: (None)
        """
        self.serial.flushInput()
        self.serial.flushOutput()

    def functional(self) -> bool:
        """
        Checks the state of the serial port (initializing it if needed)
        :return: (bool) serial connection is working
        """
        if self.serial is None:
            try:
                self.serial = Serial(port=self.PORT, baudrate=self.BAUDRATE, timeout=1)
                self.serial.flush()
                return True
            except:
                return False

        if self.serial.is_open:
            return True

        try:
            self.serial.open()
            self.serial.flush()
            return True
        except:
            return False

    def write(self, command: str) -> bool:
        """
        Write a command to the serial port.
        :param command: (str) Command to write
        :return: (bool) if the serial write worked
        """
        if not self.functional():
            return False
     
		command = command + "\r\n"
        try:
            self.serial.write(command.encode("UTF-8"))
        except:
            return False

        return True
Example #9
0
class LightStrip(object):
    def __init__(self, port='/dev/ttyUSB0'):
        self.ser = Serial(port=port, baudrate=115200, timeout=1)
        time.sleep(0)  # wait for a arduino reset to pass
        self.ser.flush()

    def send(self, rgbs):
        assert len(rgbs) == 15, rgbs
        packet = "\x60" + ''.join(
            chr(int(r)) + chr(int(g)) + chr(int(b)) for r, g, b in rgbs)
        self.ser.write(packet)
Example #10
0
def sendParam(serialConnection: serial.Serial, ba):
    """
    send params to arduino
    """
    #  TODO try
    serialConnection.write(ba)
    serialConnection.flush()

    # TODO timeout
    line = serialConnection.readline()

    return decodeStepperLine(line)
Example #11
0
    def handle(self, *args, **options):
        conf = options['config']
        config = Configurator().set_watch(False).read(conf)

        serial_com = config.get_kv("serial/device")
        serial_speed = config.get_kv("serial/speed", 9600)

        ser = Serial(serial_com, serial_speed)

        ser.write(bytes('1/11/1/', 'utf-8'))
        ser.flush()
        time.sleep(1)
        ser.close()
Example #12
0
class ServoController(object):
    def __init__(self):
        rospy.init_node('servo_controller')

        try:
            self.__serial = Serial('/dev/ttyACM0', 9600)
            rospy.sleep(1)

            #for i in range(32):
            #	self.__move(i, 90)

            #rospy.sleep(1)
        except SerialException as e:
            rospy.logfatal("Could not open serial port.")
            exit(1)

        rospy.Subscriber('direct', ServoCommand, self.move_callback)
        rospy.spin()

    ################################################################################################

    def move_callback(self, data):
        if data.angle < 0 or data.angle > 180:
            rospy.logerr('Tried to set servo #' + str(data.index) +
                         ' out of bounds (' + str(data.angle) + ' degrees).')
            return

        self.__move(data.index, data.angle, data.duration)

    ################################################################################################

    def __move(self, index, angle, duration=0.1):
        move_string = ServoController.__move_string(index, angle, duration)

        self.__serial.write(move_string)
        self.__serial.flush()
        rospy.sleep(0.003)

    ################################################################################################

    @staticmethod
    def __move_string(index, angle, duration):
        if duration < 0.1:
            duration = 0.1

        pulse_duration = int(((angle / 180.0) * (2500 - 500))) + 500
        move_time = int(duration * 1000)

        return '#' + str(index + 1) + 'P' + str(pulse_duration) + 'T' + str(
            move_time) + '\r\n'
Example #13
0
class SerialDriver(Driver):
    """
    An implementation of a serial ANT+ device driver
    """
    def __init__(self,
                 device: str,
                 baudRate: int = 115200,
                 logger: Logger = None):
        super().__init__(logger=logger)
        self._device = device
        self._baudRate = baudRate
        self._serial = None

    def __str__(self):
        if self.isOpen():
            return self._device + " @ " + str(self._baudRate)
        return None

    def _isOpen(self) -> bool:
        return self._serial is not None

    def _open(self) -> None:
        try:
            self._serial = Serial(port=self._device, baudrate=self._baudRate)
        except SerialException as e:
            raise DriverException(str(e))

        if not self._serial.isOpen():
            raise DriverException("Could not open specified device")

    def _close(self) -> None:
        self._serial.close()
        self._serial = None

    def _read(self, count: int, timeout=None) -> bytes:
        return self._serial.read(count)

    def _write(self, data: bytes) -> None:
        try:
            self._serial.write(data)
            self._serial.flush()
        except SerialTimeoutException as e:
            raise DriverException(str(e))

    def _abort(self) -> None:
        if self._serial is not None:
            self._serial.cancel_read()
            self._serial.cancel_write()
            self._serial.reset_input_buffer()
            self._serial.reset_output_buffer()
Example #14
0
class ServoController(object):
	def __init__(self):
		rospy.init_node('servo_controller')

		try:
			self.__serial = Serial('/dev/ttyACM0', 9600)
			rospy.sleep(1)

			#for i in range(32):
			#	self.__move(i, 90)

			#rospy.sleep(1)
		except SerialException as e:
			rospy.logfatal("Could not open serial port.")
			exit(1)

		rospy.Subscriber('direct', ServoCommand, self.move_callback)
		rospy.spin()

	################################################################################################

	def move_callback(self, data):
		if data.angle < 0 or data.angle > 180:
			rospy.logerr('Tried to set servo #' + str(data.index) + ' out of bounds (' + 
				str(data.angle) + ' degrees).')
			return

		self.__move(data.index, data.angle, data.duration)

	################################################################################################

	def __move(self, index, angle, duration = 0.1):
		move_string = ServoController.__move_string(index, angle, duration)

		self.__serial.write(move_string)
		self.__serial.flush()
		rospy.sleep(0.003)

	################################################################################################

	@staticmethod
	def __move_string(index, angle, duration):
		if duration < 0.1:
			duration = 0.1

		pulse_duration = int(((angle / 180.0) * (2500 - 500))) + 500
		move_time = int(duration * 1000)

		return '#' + str(index + 1) + 'P' + str(pulse_duration) + 'T' + str(move_time) + '\r\n'
Example #15
0
class MeerstetterTEC_USB(MeerstetterTEC):
    """
    Discrete implementation of the MeerstetterTEC class on an USB based interface
    """
    def __init__(self,
                 port,
                 timeout=1,
                 baudrate=57600,
                 tec_address=0,
                 check_crc=True):
        super().__init__(tec_address=tec_address, check_crc=check_crc)

        self.port = port
        self.timeout = timeout
        self.baudrate = baudrate

        self.ser = Serial(
            port=self.port,
            timeout=self.timeout,
            baudrate=self.baudrate,
        )

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.ser.__exit__(exc_type, exc_val, exc_tb)

    def __enter__(self):
        return self

    def stop(self):
        self.ser.flush()
        self.ser.close()

    def _sendAndReceive(self, frame):
        byte_arr = frame + b'\r'

        #clear all remaining buffers
        self.ser.reset_output_buffer()
        self.ser.reset_input_buffer()

        #send and flush
        self.ser.write(byte_arr)
        self.ser.flush()

        #read all in
        answer_arr = self.ser.read_until(terminator=b'\r')
        return answer_arr[0:-1]
Example #16
0
class SerialTransport(Transport):
    """
    This transports the messages over a Serial Port.
    """
    def __init__(self):
        Transport.__init__(self)
        self.port = None
        self.baudrate = None

    def _open(self):
        self.serial = Serial(**self.settings)

    def read(self):
        return self.serial.read(size=1)

    def flush(self):
        self.serial.flush()
class TraceTerminal(object):
    serial = None  # Serial() object
    port = None
    baudrate = None
    echo = None

    def __init__(self, port, baudrate=9600, echo=True, timeout=10):
        self.port = port
        self.baudrate = int(baudrate)
        self.timeout = int(timeout)
        self.echo = False if str(echo).lower() == 'off' else True

        try:
            from serial import Serial, SerialException
            self.serial = Serial(self.port,
                                 baudrate=self.baudrate,
                                 timeout=self.timeout)
            self.serial.flush()
            self.serial.reset_input_buffer()
        except (IOError, ImportError, OSError, Exception):
            self.serial = None
            return

    def terminal(self):
        try:
            import serial.tools.miniterm as miniterm
        except (IOError, ImportError, OSError) as e:
            print(repr(e))
            return False

        term = miniterm.Miniterm(self.serial, echo=self.echo)
        term.exit_character = '\x03'
        term.menu_character = '\x14'
        term.set_rx_encoding('UTF-8')
        term.set_tx_encoding('UTF-8')

        term.rx_transformations += [CalliopeDebugTransform()]

        term.start()

        try:
            term.join(True)
        except KeyboardInterrupt:
            pass
        term.join()
        term.close()
Example #18
0
def open_upy(port, baud):
    log.debug("Entering")
    log.info("Opening port and resetting ESP into run mode.")
    upy = Serial(port, baud)
    upy.reset_input_buffer()
    upy.rts=1
    upy.dtr=0
    upy.rts=0
    log.info("Sending ^c after 500ms.")
    sleep(0.5)
    upy.write(b'\x03')
    upy.flush()
    log.debug(upy.read_until(b'>>> ').decode(errors='ignore'))
    sleep(0.01)
    if upy.in_waiting:
        log.debug(upy.read_until(b'>>> ').decode(errors='ignore'))
    return upy
class SerialTransport(Transport):
    """
    This transports the messages over a Serial Port.
    """
    def __init__(self):
        Transport.__init__(self)
        self.port = None
        self.baudrate = None

    def _open(self):
        self.serial = Serial(**self.settings)

    def read(self):
        return self.serial.read(size=1)

    def flush(self):
        self.serial.flush()
Example #20
0
class TagReader:
    def __init__(self, port):
        self.serial_port = Serial(port, baudrate=9600, timeout=0.01)
        self.serial_port.close()
        self.serial_port.open()
        self.serial_port.flush()  # Flush any old data
        self.should_do_checksum = True

    def getBufferSize(self):
        return self.serial_port.inWaiting()

    """
    RFID Tag is 16 characters: STX(02h) DATA (10 ASCII) CHECK SUM (2 ASCII) CR LF ETX(03h)
    1 char of junk, 10 of hexadecimal data, 2 of hexadecimal check sum, 3 of junk
    XOR-ing 5 1-byte hex values will give the 1-byte check sum - if requested
    """

    def readTag(self):
        #  run the while loop since it may read a tag twice.
        #  May not be necessary
        while (self.getBufferSize() >= 16):
            junk = self.serial_port.read(1)  # Junk byte 1
            tag = self.serial_port.read(10)  # tag bytes 10
            check_sum = self.serial_port.read(2)  # check sum 2 bytes
            junk = self.serial_port.read(3)  # Last 3 bytes are junk

            if (self.should_do_checksum):
                self.doCheckSum(tag, check_sum)

        return int(tag, base=16)  # Convert the tag to an integer.

    def doCheckSum(self, tag, check_sum):
        try:
            checked_val = 0
            for i in range(0, 5):
                checked_val = checked_val ^ int(tag[(2 * i):(2 * (i + 1))], 16)

            if checked_val != int(check_sum, 16):
                print("Tag reader checksum error. Tag was not read fully...")
        except ValueError:
            print("Error reading the tag properly.")
            print("Tag: " + tag)

    def close(self):
        self.serial_port.close()
Example #21
0
class MockControll:
    def openSerial(self, delay=0.5):
        i = 0
        while True:
            try:
                self.serial = Serial('/dev/ttyACM' + str(i), 512000)
                print("Opened port /dev/ttyACM" + str(i) + " successfully!")
                break
            except:
                self.serial = None
                print("Couldn't open port /dev/ttyACM" + str(i) + "!")
                time.sleep(delay)
                i += 1
                if (i >= 10): i = 0

    def waitSign(self):
        print("Esperando sinal...")
        self.serial.flush()
        c = b''
        while c != b'\x40':
            c = self.serial.read()
            print(c)

        print("Got sign...")

    def sendGoal(self):
        print("Sending goal...\n")
        data = [
            1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
            20
        ]
        cs = reduce(
            lambda x, y: x ^ y,
            struct.unpack('>42b', struct.pack('>2b20h', *([3, 45] + data))))
        header = [-3599, 3, 45, cs]
        msg = struct.pack('>h3b20h', *(header + data))
        self.serial.write(msg)

    def readResponse(self):
        print("Waiting for response...")
        c = self.serial.read()
        while c != b'\x24':
            stdout.write(c.decode())
            c = self.serial.read()
        stdout.write('\n\n')
Example #22
0
class PlasmaSerial(Plasma):
    def __init__(self, light_count, port='/dev/ttyAMA0', baudrate=115200):
        self._serial_port = port
        self._serial = Serial(port, baudrate=baudrate)
        Plasma.__init__(self, light_count)

    def show(self):
        """Display current buffer on LEDs."""
        sof = b"LEDS"
        eof = b"\x00\x00\x00\xff"

        pixels = []
        for pixel in self._pixels:
            for channel in pixel:
                pixels += [channel]

        self._serial.write(sof + bytearray(pixels) + eof)
        self._serial.flush()
Example #23
0
    def __init__(self):
        self.serial = None

        for port in comports():
            try:
                serial = Serial(port[0], baudrate=BAUD_RATE, timeout=2)
                serial.write("V\n")
                result = serial.readline()
                if "SERVOTOR" in result:
                    log.info("Connected on port: %s" % port[0])
                    serial.flush()
                    self.serial = serial
                    break
            except SerialException:
                log.warning("Could not connect on port: %s" % port[0])

        if not self.serial:
            raise ConnectionException
def initialize_com(baud):

    active_ports = comports()
    # if there is only one com port, use that one
    if (len(active_ports) == 1):
        port_id = active_ports[0].name
    # if there are multiple com ports, ask user which to use
    else:
        print('Active ports: ')
        for port in active_ports:
            print(' - ' + port.name)
        port_id = input('What port would you like to use? ')
    print('Using port: ' + port_id)

    ser = Serial(port_id, baud, timeout=1)
    ser.flush()

    return ser
Example #25
0
class ArduinoCommunication:
    def __init__(self, device, baud):
        self.device = device
        self.baud_rate = baud
        self.serial_comm = Serial(device, baud)

    def send(self, payload):
        bytes_payload = []
        for fl in payload:
            bytes_payload += struct.pack('f', fl)

        print(bytes_payload)
        print(payload)
        self.serial_comm.write(bytes_payload)
        self.serial_comm.flush()

    def receive(self):
        return self.serial_comm.read()
Example #26
0
def main():
    parser = argparse.ArgumentParser(description='Send a byte over UART')
    parser.add_argument('-r',
                        '--rx',
                        dest='rx',
                        action='store_true',
                        default=False,
                        help='Wait for RX data and print it back')
    parser.add_argument('val',
                        type=str,
                        help='Byte to send, in hexadecimal format')

    args = parser.parse_args()

    rx = args.rx
    val = int(args.val, 16)

    if not 0 <= val <= 255:
        raise ValueError('Value is out of range: min 0x00 max 0xFF')

    data = bytes([val])

    ser = Serial('/dev/cu.usbserial-FT94JP1H', baudrate=57600, timeout=1)
    print(ser.write(data))
    ser.flush()

    if rx is not True:
        ser.close()

        return

    data = []

    while True:
        try:
            data.append(ord(ser.read(size=1)))
        except TypeError:
            break

    print(data)

    ser.close()

    return
Example #27
0
class SRFThread:
    def __init__(self, port):
        # Serial connection to Arduino
        self.port = port
        print("Connecting to arduino...")
        self.arduinoSerial = Serial(port=self.port,
                                    baudrate=ARDU_BAUD,
                                    timeout=1)
        sleep(3)
        print("Arduino connected")
        self.prevDistance = 0.01

        # SRF Threading
        self.qSRF = Queue()
        tSRF = Thread(target=self._distance)
        tSRF.daemon = True
        tSRF.start()

    def _distance(self):
        while True:
            self.arduinoSerial.flush()
            self.arduinoSerial.write(b'a')
            srf_distance = self.arduinoSerial.readline().decode(
                'ascii').strip()

            try:
                distance = int(srf_distance) / 100.0
                if not self.qSRF.empty():
                    try:
                        self.qSRF.get_nowait()
                    except:
                        pass
                self.qSRF.put(distance)
            except:
                pass

    def readSRF(self):
        distance = self.qSRF.get()
        if distance is None or distance is 0:
            return self.prevDistance
        else:
            self.prevDistance = distance
            return distance
Example #28
0
    def readThread(self):
        ser = Serial('COM3')
        ser.flush()
        i = 0
        rgb = 'rgb'
        color = [Qt.red, Qt.green, Qt.blue]
        while True:
            data = ser.read(2).decode('utf-8')
            print(data)

            if data[0] == '1' and self.me.left() - 10 >= 0:
                self.me.moveTo(self.me.left() - 10, self.me.top())
            elif data[0] == '2' and self.me.left() + 10 <= 400:
                self.me.moveTo(self.me.left() + 10, self.me.top())
            
            self.bul.moveTo(self.bul.left(), self.bul.top() - 30)
            if data[1] == '1' and self.bul.top() < 0:
                self.bul.setRect(self.me.left() + 50,self.me.top(),10,10)
                i += 1
                self.color = color[i % 3]
                ser.write(rgb[i % 3].encode())
        
            for ship, _ in self.ships:
                ship.moveTo(ship.left(), ship.top() + 10)

                if ship.contains(self.bul):
                    self.ships.remove((ship, _))
                    self.bul.moveTo(-100, -100)

                if (ship.contains(self.me.center())):
                    self.msg = 'You Died!!'
                    self.update()
                    return

                if (ship.top() > 1000):
                    ship.moveTo(ship.left(), -randrange(50, 300))
            
            if len(self.ships) == 0:
                self.msg = 'You Win!!'
                self.update()
                return

            self.update()
Example #29
0
class SerialWorker(QtCore.QObject):
    """
        Serial Worker that reads lines from the serial port
    """
    readline = QtCore.pyqtSignal(str)

    def __init__(self):
        super(SerialWorker, self).__init__()
        self.active = True
        self.serial = None
        self.sendNewLine = True

    def openSerial(self, port, baudRate, timeout, sendNewLine=True):
        """ Opens the serial port """
        if self.serial is not None:
            raise Exception("Cannot read multiple serial")
        self.serial = Serial(port = port, baudrate = baudRate, timeout = timeout)
        self.sendNewLine = sendNewLine

    def closeSerial(self):
        """ Closes the serial port """
        if self.serial is not None:
            self.serial.close()
        self.serial = None

    def workerStart(self):
        """ Runs in a loop reading from the serial port """
        while(self.active):
            if self.serial is not None:
                try:
                    if self.sendNewLine:
                        self.serial.write(b"\n")
                        self.serial.flush()
                    line = self.serial.readline()
                except Exception as e:
                    print("Error Reading Serial Port")
                self.readline[str].emit(line)
            else:
                QtCore.QThread.msleep(500)

    def workerStop(self):
        self.closeSerial()
Example #30
0
class Link:
    def __init__(self, port="/dev/ttyACM0", baudrate=115200):
        self.ser = Serial(port, baudrate, timeout=0.5)
        self.ser.flush()
        self.data = ""
        self.new_data = False
        self.start_marker = "<"
        self.end_marker = ">"
        self.incoming_in_process = False
        self.incoming_data = ""

    def read(self):
        try:
            while self.ser.inWaiting() > 0:
                data = self.ser.read().decode()
                if (data == self.start_marker):
                    self.incoming_in_process = True
                    #self.new_data = False
                    self.incoming_data = ""
                elif (data == self.end_marker):
                    self.incoming_in_process = False
                    self.data = self.incoming_data
                    self.incoming_data = ""
                    self.new_data = True
                elif (self.incoming_in_process == True):
                    self.incoming_data += data
        except Exception as e:
            print(e)

    def get_name(self):
        self.ser.write(b"#")

    def write(self, msg):
        self.ser.write(b"" + self.start_marker.encode())
        self.ser.write(b"" + msg.encode())
        self.ser.write(b"" + self.end_marker.encode())

    def get_data(self):
        if self.new_data:
            self.new_data = False
            return self.data
        return ""
Example #31
0
 def get_port(self):
     test_port = None
     current_ports = Ports.comports()
     for port in current_ports:
         if 'USB' in port.device:
             try:
                 test_port = Serial(port.device, 9600)
             except Exception as e:
                 print('opening port failed: {}'.format(e))
                 continue
             test_port.write(b'\r\n\r\n')
             test_port.flush()
             while test_port.in_waiting > 0:
                 line = test_port.readline()
                 if b'Vin: ' in line:
                     test_port.flush()
                     return test_port
             test_port.close()
     raise HydraNotConnectedError(
         'Hydra not found.  Please connect Hydra and try again.')
Example #32
0
    def apply(self):
        # Init Uart
        _LOGGER.info("Execute: %s", self.cmd)
        uart = Serial(self.port, self.baudrate, timeout=self.timeout)
        # Execute Command
        time_start = time.time()
        time_escape = time.time() - time_start
        uart.write(self.cmd + self.eol)
        uart.flush()
        rawdata = ""
        while time_escape <= self.cmd_timeout:
            rawdata += uart.read(self.read_size)
            if self.recv != None and len(rawdata) >= self.recv:
                break

            find_endmark = False
            for endmark in self.endmarks:
                sret = re.search(endmark, rawdata)
                if sret != None:
                    find_endmark = True
                    break
            if find_endmark == True:
                break
            time_escape = time.time() - time_start
        uart.close()
        # Print rawdata
        lines = rawdata.split("\n")
        for line in lines:
            _LOGGER.info("%s", line)
        ## Check Error
        find_error = False
        for error_filter in self.error_filters:
            try:
                error_filter.determine(rawdata)
            except ValueError, err:
                _LOGGER.error("%s", err)
                find_error = True
            if find_error == True:
                # Raise this error again so that SESCommandItem can catch it.
                _LOGGER.info("ERROR: read value with error!")
                break
Example #33
0
def serial_open(port, baudrate, read_timeout=None, write_timeout=None):
    '''Try to open a Serial Port.'''
    ser = None
    print_log(LOG.INFO,
              "Opening Serial port {} at {}bps...".format(port, str(baudrate)))
    try:
        ser = Serial(port=None)
        ser.port = port
        ser.baudrate = baudrate
        ser.timeout = read_timeout
        ser.write_timeout = write_timeout
        if not ser.isOpen():
            ser.open()
        ser.flush()
        print_log(LOG.INFO, "Port successfully open.")
    except Exception as e:
        print_log(LOG.ERROR, str(e))
    if (ser is None) or (not ser.isOpen()):
        ser = None
        print_log(LOG.ERROR, "Can't open serial port.")
    return ser
Example #34
0
class UartDevice(IODevice):
    def __init__(self, port: str = "/dev/ttyUSB0", baudrate: int = 9600):
        self.uart = Serial(port, baudrate, xonxoff=False)

    def ReadByte(self):
        return self.uart.read_all()

    def ReadAll(self):
        return self.uart.read_all()

    def Write(self, arr: bytes):
        assert (type(arr) is bytes)
        self.uart.write(arr)

    def Flush(self):
        self.uart.flush()

    def SetBaudrate(self, baudrate: int) -> None:
        self.uart.baudrate = baudrate

    def GetBaudrate(self):
        return self.uart.baudrate
Example #35
0
class Device():
    def __init__(self):  #linkage is probably screwing something up
        port = find_port()
        if port is None:
            raise Exception('cannot find device')
        self.serial = Serial(port, BAUD_RATE, timeout=TIMEOUT)
        # self.flush()
        self.pos = 0

# he made his own flush? why? the below just fills the serial buffer with zeroes... maybe
# def flush(self):
# for i in range(10):
# self.move(0, 0, 0)

    def readline(self):
        return self.serial.readline().decode('utf-8').strip(
        )  # He doesn't care what it looks for but this function will lock up the program until it reads soemthing (probably not certain)

# called by move - step 3 THIS IS THE MOST IMPORTANT PART

    def send(self, cmd):
        print(cmd.strip()
              )  # gets rid of spaces (which don't exist) but good practice
        self.serial.write(
            cmd.encode('utf-8')
        )  # converts to something for serial with python AND SENDS AS WELL THIS IS THE SEND DAVE
        self.serial.flush()  # clears buffer (library)
        print(
            self.readline()
        )  # this is waiting for Drew's "OK" called above - doesn't do anything with this but print

# called by step_to - step 2

    def move(self, pos):
        cmd = 'STEP %d\n' % (
            pos
        )  # cmd is a variable that's a string! It's what's sent over serial
        # cmd = 'JOG %f %f %d\n' % (da1, da2, ms) #this says make a float, a float, and a decimal, a linebreak and the stuff in parenthesis is what gets filled in
        self.send(cmd)
class ArduinoController():
    def __init__(self, port: str, steppers: dict, **kwargs):
        self.port = port
        self.steppers = steppers
        self.baudrate = kwargs.get('baudrate', 9600)
        self.timeout = kwargs.get('timeout', 1)
        self.serial = Serial(self.port, self.baudrate, timeout=self.timeout)

    def confirmContact(self):
        byte_received = False
        while not byte_received:
            byte = self.serial.read()
            if byte == b'A':
                print('first contact attempt received')
                byte_received = True
        self.serial.flush()
        self.serial.write(b'A')
        self.serial.write(b'Mooie test gek')

        while True:
            self.serial.flush()
            print(self.serial.readline())
Example #37
0
class Rangefinder(object):
    def __init__(self):
        #self.serialDevice = "/dev/ttyAMA0" # default for RaspberryPi
        self.serialDevice = "/dev/serial0"
        self.connection = Serial(self.serialDevice)
        #self.node = rospy.init_node('rangeFinder', anonymous=True)
        self.pub = rospy.Publisher('range', Int16, queue_size=10)

    def getRange(self):
        b = self.connection.read(1)
        while b != b'R':
            b = self.connection.read(1)
        b = self.connection.read(1)
        num = b''
        while b != b'\r':
            num += b
            b = self.connection.read(1)
        if self.connection.in_waiting > 10:
            self.connection.flush()

        val = int(num.decode()) // 10
        print('MASSIVE FARTS!!!' + str(val))
        return val

    def pubRange(self):
        b = self.connection.read(1)
        while b != b'R':
            b = self.connection.read(1)
        b = self.connection.read(1)
        num = b''
        while b != b'\r':
            num += b
            b = self.connection.read(1)
        if self.connection.in_waiting > 10:
            self.connection.flush()

        val = int(num.decode()) // 10
        #print(val)
        self.pub.publish(val)
Example #38
0
class EchoApplication(WebSocketApplication):
    def on_open(self):
        print "Connection opened"
        self.serialPort = Serial(serialPortFile, 9600, timeout = 1)

    def on_message(self, message):
        if message == None:
            return

        print "Got message: ", message
        if message == "LED On":
            self.serialPort.write('l')
            self.serialPort.flush()
        if message == "LED Off":
            self.serialPort.write('k')
            self.serialPort.flush()

        self.ws.send(message)

    def on_close(self, reason):
        self.serialPort.close()
        print "Closing", reason
Example #39
0
def connect():
	#Initiate a connection
	print("initializing..")
	arduino = Serial('/dev/ttyACM0', 115200)
	#Read confirmation from Arduino
	print("Done initializing...")
	arduino.flushInput()
	arduino.flushOutput()
	arduino.flush()
	count = 0
	try:
		while True:
			if count == 0:
				print('about to write..')
				arduino.write("H".encode('utf-8'))
				print('wrote..')
				count = count + 1
			if arduino.inWaiting() > 0:
				
				#read the message from the Arduino
				print('about to read.')
				time.sleep(0.2)
				raw_message = str(arduino.read(1))
				print('reading..')
				
				#remove EOL characters from string
				message = raw_message.rstrip()
				print(message)
				count = count + 1
				if count >= 100:
					count = 0
				print ("count " + str(count))
	except: 
		arduino.flushInput()
		arduino.flushOutput()
		arduino.flush()
		arduino.close()
		print('closed')
Example #40
0
class Arduino:
    def __init__(self, device):
        super().__init__()
        self.logger = Log.instance('Arduino')
        try:
            self.port = Serial(device, baudrate=9600, timeout=1.0)
        except Exception as e:
            self.logger.error(e)

    def freight_ready(self):
        if self.port.in_waiting > 0:
            c = self.port.read()
            self.logger.info('read "{}"'.format(c))
            return c.decode() == 'L'
        else:
            return False

    def write(self, cmd):
        self.port.write(cmd.encode())
        self.port.flush()
        self.logger.info('sent command: "{}"'.format(cmd))

    def move_off(self):
        self.write('G')

    def pick_up(self, height):
        cmd = 'S{};'.format(height)
        self.write(cmd)

    def decelerate(self):
        self.write('D')

    def drop_freight(self, height):
        cmd = 'S{};'.format(height)
        self.write(cmd)

    def halt(self):
        self.write('H')
Example #41
0
class SRFNoThread:
    def __init__(self, port):
        # Serial connection to Arduino
        self.port = port
        print("Connecting to arduino...")
        self.arduinoSerial = Serial(port=self.port,
                                    baudrate=ARDU_BAUD,
                                    timeout=1)
        sleep(3)
        print("Arduino connected")

    def distance(self):
        while True:
            self.arduinoSerial.flush()
            self.arduinoSerial.write(b'a')
            srf_distance = self.arduinoSerial.readline().decode(
                'ascii').strip()

            try:
                distance = int(srf_distance) / 100.0
                return distance
            except:
                continue
Example #42
0
class SAMBA(object):
    def __init__(self, port_name, progress=None, application_name='Brick Viewer'):
        self.r_command_bug = False
        self.sam_series = None
        self.current_mode = None
        self.progress = progress

        try:
            self.port = Serial(port_name, 115200, timeout=5)
        except SerialException as e:
            if '[Errno 13]' in str(e):
                if sys.platform.startswith('linux'):
                    raise SAMBAException("No permission to open serial port, try starting {0} as root".format(application_name))
                else:
                    raise SAMBAException("No permission to open serial port")
            else:
                raise e

        try:
            self.change_mode('T')
            self.change_mode('N')
        except:
            raise SAMBAException('No Brick in Bootloader found')

        chipid_cidr = self.read_uint32(CHIPID_CIDR)
        chipid_exid = self.read_uint32(CHIPID_EXID)

        # SAM3
        if chipid_cidr == CHIPID_CIDR_ATSAM3S2B_A:
            self.sam_series = 3
            self.flash_base = 0x400000
            self.flash_page_count = 512
            self.flash_page_size = 256
            self.flash_lockbit_count = 8
        elif chipid_cidr == CHIPID_CIDR_ATSAM3S4C_A:
            self.sam_series = 3
            self.flash_base = 0x400000
            self.flash_page_count = 1024
            self.flash_page_size = 256
            self.flash_lockbit_count = 16

        # SAM4S
        elif chipid_cidr in [CHIPID_CIDR_ATSAM4S2B_A, CHIPID_CIDR_ATSAM4S2B_B]:
            self.sam_series = 4
            self.flash_base = 0x400000
            self.flash_page_count = 256
            self.flash_page_size = 512
            self.flash_lockbit_count = 16
        elif chipid_cidr in [CHIPID_CIDR_ATSAM4S4C_A, CHIPID_CIDR_ATSAM4S4C_B]:
            self.sam_series = 4
            self.flash_base = 0x400000
            self.flash_page_count = 512
            self.flash_page_size = 512
            self.flash_lockbit_count = 32

        # SAM4E
        elif chipid_cidr in [CHIPID_CIDR_ATSAM4E8C_A, CHIPID_CIDR_ATSAM4E8C_B] and \
             chipid_exid in [CHIPID_EXID_ATSAM4E8C_A, CHIPID_EXID_ATSAM4E8C_B]:
            self.sam_series = 4
            self.flash_base = 0x400000
            self.flash_page_count = 1024
            self.flash_page_size = 512
            self.flash_lockbit_count = 64
        elif chipid_cidr in [CHIPID_CIDR_ATSAM4E16E_A, CHIPID_CIDR_ATSAM4E16E_B] and \
             chipid_exid in [CHIPID_EXID_ATSAM4E16E_A, CHIPID_EXID_ATSAM4E16E_B]:
            self.sam_series = 4
            self.flash_base = 0x400000
            self.flash_page_count = 2048
            self.flash_page_size = 512
            self.flash_lockbit_count = 128

        # unknown
        else:
            raise SAMBAException('Brick has unknown CHIPID: 0x%08X / 0x%08X' % (chipid_cidr, chipid_exid))

        self.flash_size = self.flash_page_count * self.flash_page_size
        self.flash_lockregion_size = self.flash_size // self.flash_lockbit_count
        self.flash_pages_per_lockregion = self.flash_lockregion_size // self.flash_page_size

    def change_mode(self, mode):
        if self.current_mode == mode:
            return

        try:
            self.port.write((mode + '#').encode('ascii'))
        except:
            raise SAMBAException('Write error during mode change')

        if mode == 'T':
            while True:
                try:
                    response = self.port.read(1)
                except:
                    raise SAMBAException('Read error during mode change')

                if len(response) == 0:
                    raise SAMBAException('Read timeout during mode change')

                if response == b'>':
                    break
        else:
            try:
                response = self.port.read(2)
            except:
                raise SAMBAException('Read error during mode change')

            if len(response) == 0:
                raise SAMBAException('Read timeout during mode change')

            if response != b'\n\r':
                raise SAMBAException('Protocol error during mode change')

        self.current_mode = mode

    def read_uid64(self):
        self.write_flash_command(EEFC_FCR_FCMD_STUI, 0)
        self.wait_for_flash_ready('while reading UID', ready=False)

        uid1 = self.read_uint32(self.flash_base + 8)
        uid2 = self.read_uint32(self.flash_base + 12)

        self.write_flash_command(EEFC_FCR_FCMD_SPUI, 0)
        self.wait_for_flash_ready('after reading UID')

        return uid2 << 32 | uid1

    def flash(self, firmware, imu_calibration, lock_imu_calibration_pages):
        # Split firmware into pages
        firmware_pages = []
        offset = 0

        while offset < len(firmware):
            page = firmware[offset:offset + self.flash_page_size]

            if len(page) < self.flash_page_size:
                page += b'\xff' * (self.flash_page_size - len(page))

            firmware_pages.append(page)
            offset += self.flash_page_size

        if self.sam_series == 3:
            # SAM3S flash programming erata: FWS must be 6
            self.write_uint32(EEFC_FMR, 0x06 << 8)

        # Unlock
        self.reset_progress('Unlocking flash pages', 0)
        self.wait_for_flash_ready('before unlocking flash pages')

        for region in range(self.flash_lockbit_count):
            page_num = (region * self.flash_page_count) // self.flash_lockbit_count
            self.write_flash_command(EEFC_FCR_FCMD_CLB, page_num)
            self.wait_for_flash_ready('while unlocking flash pages')

        # Erase All
        self.reset_progress('Erasing flash pages', 0)
        self.write_flash_command(EEFC_FCR_FCMD_EA, 0)
        self.wait_for_flash_ready('while erasing flash pages', timeout=10000, update_progress=True)

        # Write firmware
        self.write_pages(firmware_pages, 0, 'Writing firmware')

        # Write IMU calibration
        if imu_calibration is not None:
            self.reset_progress('Writing IMU calibration', 0)

            ic_relative_address = self.flash_size - 0x1000 * 2 - 12 - 0x400
            ic_prefix_length = ic_relative_address % self.flash_page_size
            ic_prefix_address = self.flash_base + ic_relative_address - ic_prefix_length
            ic_prefix = ''
            offset = 0

            while len(ic_prefix) < ic_prefix_length:
                ic_prefix += self.read_word(ic_prefix_address + offset)
                offset += 4

            prefixed_imu_calibration = ic_prefix + imu_calibration

            # Split IMU calibration into pages
            imu_calibration_pages = []
            offset = 0

            while offset < len(prefixed_imu_calibration):
                page = prefixed_imu_calibration[offset:offset + self.flash_page_size]

                if len(page) < self.flash_page_size:
                    page += b'\xff' * (self.flash_page_size - len(page))

                imu_calibration_pages.append(page)
                offset += self.flash_page_size

            # Write IMU calibration
            page_num_offset = (ic_relative_address - ic_prefix_length) // self.flash_page_size

            self.write_pages(imu_calibration_pages, page_num_offset, 'Writing IMU calibration')

        # Lock firmware
        self.reset_progress('Locking flash pages', 0)
        self.lock_pages(0, len(firmware_pages))

        # Lock IMU calibration
        if imu_calibration is not None and lock_imu_calibration_pages:
            first_page_num = (ic_relative_address - ic_prefix_length) // self.flash_page_size
            self.lock_pages(first_page_num, len(imu_calibration_pages))

        # Verify firmware
        self.verify_pages(firmware_pages, 0, 'firmware', imu_calibration is not None)

        # Verify IMU calibration
        if imu_calibration is not None:
            page_num_offset = (ic_relative_address - ic_prefix_length) // self.flash_page_size
            self.verify_pages(imu_calibration_pages, page_num_offset, 'IMU calibration', True)

        # Set Boot-from-Flash flag
        self.reset_progress('Setting Boot-from-Flash flag', 0)

        self.wait_for_flash_ready('before setting Boot-from-Flash flag')
        self.write_flash_command(EEFC_FCR_FCMD_SGPB, 1)
        self.wait_for_flash_ready('after setting Boot-from-Flash flag')

        # Boot
        try:
            self.reset()
        except SAMBAException as e:
            raise SAMBARebootError(str(e))

    def reset_progress(self, title, length):
        if self.progress != None:
            self.progress.reset(title, length)

    def update_progress(self, value):
        if self.progress != None:
            self.progress.update(value)

    def write_pages(self, pages, page_num_offset, title):
        self.reset_progress(title, len(pages))

        page_num = 0

        for page in pages:
            # FIXME: the S command used by the write_bytes function doesn't
            #        write the data correctly. instead use the write_word function
            if False:
                address = self.flash_base + (page_num_offset + page_num) * self.flash_page_size
                self.write_bytes(address, page)
            else:
                offset = 0

                while offset < len(page):
                    address = self.flash_base + (page_num_offset + page_num) * self.flash_page_size + offset
                    self.write_word(address, page[offset:offset + 4])
                    offset += 4

            self.wait_for_flash_ready('while writing flash pages')
            self.write_flash_command(EEFC_FCR_FCMD_WP, page_num_offset + page_num)
            self.wait_for_flash_ready('while writing flash pages')

            page_num += 1
            self.update_progress(page_num)

    def verify_pages(self, pages, page_num_offset, title, title_in_error):
        self.reset_progress('Verifying written ' + title, len(pages))

        offset = page_num_offset * self.flash_page_size
        page_num = 0

        for page in pages:
            read_page = self.read_bytes(self.flash_base + offset, len(page))
            offset += len(page)

            if read_page != page:
                if title_in_error:
                    raise SAMBAException('Verification error ({0})'.format(title))
                else:
                    raise SAMBAException('Verification error')

            page_num += 1
            self.update_progress(page_num)

    def lock_pages(self, page_num, page_count):
        start_page_num = page_num - (page_num % self.flash_pages_per_lockregion)
        end_page_num = page_num + page_count

        if (end_page_num % self.flash_pages_per_lockregion) != 0:
            end_page_num += self.flash_pages_per_lockregion - (end_page_num % self.flash_pages_per_lockregion)

        self.wait_for_flash_ready('before locking flash pages')

        for region in range(start_page_num // self.flash_pages_per_lockregion,
                            end_page_num // self.flash_pages_per_lockregion):
            page_num = (region * self.flash_page_count) // self.flash_lockbit_count
            self.write_flash_command(EEFC_FCR_FCMD_SLB, page_num)
            self.wait_for_flash_ready('while locking flash pages')

    def read_word(self, address): # 4 bytes
        self.change_mode('N')

        try:
            self.port.write(('w%X,4#' % address).encode('ascii'))
        except:
            raise SAMBAException('Write error while reading from address 0x%08X' % address)

        try:
            response = self.port.read(4)
        except:
            raise SAMBAException('Read error while reading from address 0x%08X' % address)

        if len(response) == 0:
            raise SAMBAException('Timeout while reading from address 0x%08X' % address)

        if len(response) != 4:
            raise SAMBAException('Length error while reading from address 0x%08X' % address)

        return response

    def write_word(self, address, value): # 4 bytes
        self.write_uint32(address, struct.unpack('<I', value)[0])

    def read_uint32(self, address):
        return struct.unpack('<I', self.read_word(address))[0]

    def write_uint32(self, address, value):
        self.change_mode('N')

        try:
            self.port.write(('W%X,%X#' % (address, value)).encode('ascii'))
        except:
            raise SAMBAException('Write error while writing to address 0x%08X' % address)

    def read_bytes(self, address, length):
        # according to the BOSSA flash program, SAM-BA can have a bug regarding
        # reading more than 32 bytes at a time if the amount to be read is a
        # power of 2. to work around this split the read operation in two steps
        prefix = b''

        if self.r_command_bug and length > 32 and length & (length - 1) == 0:
            prefix = self.read_word(address)
            address += 4
            length -= 4

        self.change_mode('T')

        try:
            self.port.write(('R%X,%X#' % (address, length)).encode('ascii'))
        except:
            raise SAMBAException('Write error while reading from address 0x%08X' % address)

        try:
            response = self.port.read(length + 3)
        except:
            raise SAMBAException('Read error while reading from address 0x%08X' % address)

        if len(response) == 0:
            raise SAMBAException('Timeout while reading from address 0x%08X' % address)

        if len(response) != length + 3:
            raise SAMBAException('Length error while reading from address 0x%08X' % address)

        if not response.startswith(b'\n\r') or not response.endswith(b'>'):
            raise SAMBAException('Protocol error while reading from address 0x%08X' % address)

        return prefix + response[2:-1]

    def write_bytes(self, address, bytes_):
        self.change_mode('T')

        # FIXME: writes '33337777BBBBFFFF' instead of '0123456789ABCDEF'
        try:
            # according to the BOSSA flash program, SAM-BA can get confused if
            # the command and the data to be written is received in the same USB
            # packet. to work around this, flush the serial port in between the
            # command and the data
            self.port.write(('S%X,%X#' % (address, len(bytes_))).encode('ascii'))
            self.port.flush()
            self.port.write(bytes_)
        except:
            raise SAMBAException('Write error while writing to address 0x%08X' % address)

        try:
            response = self.port.read(3)
        except:
            raise SAMBAException('Read error while writing to address 0x%08X' % address)

        if len(response) == 0:
            raise SAMBAException('Timeout while writing to address 0x%08X' % address)

        if response != b'\n\r>':
            raise SAMBAException('Protocol error while writing to address 0x%08X' % address)

    def reset(self):
        self.reset_progress('Triggering Brick reset', 0)

        try:
            self.write_uint32(RSTC_MR, (RSTC_MR_KEY << RSTC_MR_KEY_OFFSET) | (10 << RSTC_MR_ERSTL_OFFSET) | RSTC_MR_URSTEN)
            self.write_uint32(RSTC_CR, (RSTC_CR_KEY << RSTC_CR_KEY_OFFSET) | RSTC_CR_EXTRST | RSTC_CR_PERRST | RSTC_CR_PROCRST)
        except:
            raise SAMBAException('Write error while triggering reset')

    def go(self, address):
        self.change_mode('N')

        try:
            # according to the BOSSA flash program, SAM-BA can get confused if
            # another command is received in the same USB packet as the G
            # command. to work around this, flush the serial port afterwards
            self.port.write(('G%X#' % address).encode('ascii'))
            self.port.flush()
        except:
            raise SAMBAException('Write error while executing code at address 0x%08X' % address)

    def wait_for_flash_ready(self, message, timeout=2000, ready=True, update_progress=False):
        for i in range(timeout):
            fsr = self.read_uint32(EEFC_FSR)

            if (fsr & EEFC_FSR_FLOCKE) != 0:
                raise SAMBAException('Flash locking error ' + message)

            if (fsr & EEFC_FSR_FCMDE) != 0:
                raise SAMBAException('Flash command error ' + message)

            if self.sam_series == 4 and (fsr & EEFC_FSR_FLERR) != 0:
                raise SAMBAException('Flash memory error ' + message)

            if ready:
                if (fsr & EEFC_FSR_FRDY) != 0:
                    break
            else:
                if (fsr & EEFC_FSR_FRDY) == 0:
                    break

            time.sleep(0.001)

            if update_progress:
                self.update_progress(0)
        else:
            raise SAMBAException('Flash timeout ' + message)

    def write_flash_command(self, command, argument):
        self.write_uint32(EEFC_FCR, (EEFC_FCR_FKEY << 24) | (argument << 8) | command)
Example #43
0
print ports
command=command+"\n\r"
print command
com = Serial(
  port=ports,
  baudrate=9600,
  bytesize=8,
  parity='N',
  stopbits=1,
  timeout=1,#None,
  xonxoff=0,
  rtscts=0,
  writeTimeout=1,#None,
  dsrdtr=None)

#print com.portstr
#com.write("%01#RDD0000000015**\r")
com.flush()

i=0
com.write(command)
#res=com.read
com.close()

#print len(res)
#print res
#with open('res.txt', 'w+b') as file:
#  file.write(res)

Example #44
0
class FieldforceTCM:
    Component = namedtuple('Component', [
        'name', 'struct'
    ])
    ModInfo   = namedtuple('ModInfo', [
        'Type', 'Revision'
    ])
    CalScores = namedtuple('CalScores', [
        'MagCalScore', 'CalParam2', 'AccelCalScore', 'DistError',
        'TiltError', 'TiltRange'
    ])
    AcqParams = namedtuple('AcqParams', [
        'PollingMode', 'FlushFilter', 'SensorAcqTime', 'IntervalRespTime'
    ])
    Datum     = namedtuple('Datum', [
        'Heading', 'Temperature', 'Distortion', 'CalStatus',
        'PAligned', 'RAligned', 'IZAligned',
        'PAngle', 'RAngle', 'XAligned', 'YAligned', 'ZAligned'
    ])

    good_cal_score = CalScores('< 1', 'ignore (pni reserved)', '< 1',
            '< 1', '< 1', 'angle of tilt' )


    components = {
        5:  Component('Heading',     _struct_float32),
        7:  Component('Temperature', _struct_float32),
        8:  Component('Distortion',  _struct_boolean),
        9:  Component('CalStatus',   _struct_boolean),
        21: Component('PAligned',    _struct_float32),
        22: Component('RAligned',    _struct_float32),
        23: Component('IZAligned',   _struct_float32),
        24: Component('PAngle',      _struct_float32),
        25: Component('RAngle',      _struct_float32),
        27: Component('XAligned',    _struct_float32),
        28: Component('YAligned',    _struct_float32),
        29: Component('ZAligned',    _struct_float32)
    }

    config = {
        1:  Component('Declination',         _struct_float32),
        2:  Component('TrueNorth',           _struct_boolean),
        6:  Component('BigEndian',           _struct_boolean),
        10: Component('MountingRef',         _struct_uint8),
        12: Component('UserCalNumPoints',    _struct_uint32),
        13: Component('UserCalAutoSampling', _struct_boolean),
        14: Component('BaudRate',            _struct_uint8),
        15: Component('MilOutput',           _struct_boolean),
        16: Component('DataCal',             _struct_boolean),
        18: Component('CoeffCopySet',        _struct_uint32),
        19: Component('AccelCoeffCopySet',   _struct_uint32)
    }

    fir_defaults = {
        0:  [ ],
        4:  [ 4.6708657655334e-2, 4.5329134234467e-1,
              4.5329134234467e-1, 4.6708657655334e-2 ],
        8:  [ 1.9875512449729e-2, 6.4500864832660e-2,
              1.6637325898141e-1, 2.4925036373620e-1,
              2.4925036373620e-1, 1.6637325898141e-1,
              6.4500864832660e-2, 1.9875512449729e-2 ],
        16: [ 7.9724971069144e-3, 1.2710056429342e-2,
              2.5971390034516e-2, 4.6451949792704e-2,
              7.1024151197772e-2, 9.5354386848804e-2,
              1.1484431942626e-1, 1.2567124916369e-1,
              1.2567124916369e-1, 1.1484431942626e-1,
              9.5354386848804e-2, 7.1024151197772e-2,
              4.6451949792704e-2, 2.5971390034516e-2,
              1.2710056429342e-2, 7.9724971069144e-3 ],
        32: [ 1.4823725958818e-3, 2.0737124095482e-3,
              3.2757326624196e-3, 5.3097803863757e-3,
              8.3414139286254e-3, 1.2456836057785e-2,
              1.7646051430536e-2, 2.3794805168613e-2,
              3.0686505921968e-2, 3.8014333463472e-2,
              4.5402682509802e-2, 5.2436112653103e-2,
              5.8693165018301e-2, 6.3781858267530e-2,
              6.7373451424187e-2, 6.9231186101853e-2,
              6.9231186101853e-2, 6.7373451424187e-2,
              6.3781858267530e-2, 5.8693165018301e-2,
              5.2436112653103e-2, 4.5402682509802e-2,
              3.8014333463472e-2, 3.0686505921968e-2,
              2.3794805168613e-2, 1.7646051430536e-2,
              1.2456836057785e-2, 8.3414139286254e-3,
              5.3097803863757e-3, 3.2757326624196e-3,
              2.0737124095482e-3, 1.4823725958818e-3 ]
    }

    def reader(self):
        """
        factory which returns a callable object suitable (for example)
        to pass to threading.Thread(target=reader()).
        """
        def do_it():
            while True:
                self._wait_and_read_all()
                rdy_pkts = self._decode()
                if rdy_pkts:
                    #for pkt in rdy_pkts:
                    #    fid = ord(pkt[0])
                    #    print 'new pkt: {0} {1}'.format(FrameID.invert[fid], fid)

                    self._notify_listeners(rdy_pkts)
        return do_it

    def _wait_and_read_all(self):
        s = self.fp
        b = self.recv_buf
        b.append(s.read())
        wait_ct = s.inWaiting()
        if wait_ct > 0:
            b.extend(s.read(wait_ct))

    def _notify_listeners(self, rdy_pkts):
        cbs = self.recv_cbs
        lock = self.cb_lock
        lock.acquire()
        x = []
        for i in range(0, len(cbs)):
            if cbs[i](rdy_pkts):
                # A callback returning true is removed.
                # XXX: Can't remove while iterating over it.
                x.append(i)
        for it in x:
            del cbs[it]
        lock.release()

    def _decode(self):
        """
        Given self.recv_buf and self.crc, attempts to decode a valid packet,
        advancing by a single byte on each decoding failure.
        """
        b = self.recv_buf
        crc_fn = self.crc
        decode_pos  = 0
        discard_amt = 0
        good_pos    = 0 # discard before this
        decode_len  = len(b)
        rdy_pkts = []

        # min packet = 2 (byte_count) + 1 (frame id) + 2 (crc) = 5
        #attempt_ct = 0
        #print decode_len
        while decode_len >= 5:
            #attempt_ct += 1
            #print '--decode attempt {0}'.format(attempt_ct)
            (byte_count, ) = struct.unpack('>H', bytes(b[decode_pos:decode_pos+2]))
            frame_size = byte_count - 4

            # max frame = 4092, min frame = 1
            if frame_size < 1 or frame_size > 4092:
                #print '-- fail 1 {0}'.format(frame_size)
                decode_pos += 1
                decode_len -= 1
                continue

            # not enough in buffer for this decoding
            if decode_len < byte_count:
                #print '-- fail 2'
                decode_pos += 1
                decode_len -= 1
                continue

            frame_pos = decode_pos + 2
            frame_id = b[frame_pos]

            # invalid frame id
            if frame_id not in FrameID.__dict__.itervalues():
                #print '-- fail 3'
                decode_pos += 1
                decode_len -= 1
                continue

            crc_pos   = frame_pos  + frame_size
            crc = b[crc_pos:crc_pos + 2]
            entire_pkt = b[decode_pos:frame_pos + frame_size + 2]

            # CRC failure
            crc_check = crc_fn(bytes(entire_pkt))
            if crc_check != 0:
                #print '-- fail 4'
                decode_pos += 1
                decode_len -= 1
                continue

            # valid packet? wow.
            rdy_pkts.append(b[frame_pos:frame_pos + frame_size])

            # number of invalid bytes discarded to make this work.
            discard_amt += decode_pos - good_pos

            # advance to right after the decoded packet.
            decode_pos += byte_count
            decode_len -= byte_count

            # the decode position that will be started from next time
            good_pos     = decode_pos

        # discard this packet from buffer. also discard everything prior.
        del b[0:good_pos]
        self.discard_stat += discard_amt

        return rdy_pkts

    def remove_listener(self, r):
        c = self.recv_cbs
        l = self.cb_lock
        l.acquire()
        try:
            # FIXME: linear search.
            c.remove(r)
        except Exception:
            pass
        l.release()

    def add_listener(self, cb):
        c = self.recv_cbs
        l = self.cb_lock
        l.acquire()
        c.append(cb)
        l.release()
        return cb

    def _recv_msg_prep(self, *expected_frame_id):
        s = _one_msg_stall(*expected_frame_id)
        t = self.add_listener(s.cb())

        return (s, t)

    def _recv_msg_wait(self, w, timeout = _DEFAULT_TIMEOUT):
        s, t = w
        r = s.wait(timeout)

        self.remove_listener(t)

        if (r == None):
            raise TimeoutException('Did not recv frame_id {0} within {1} seconds.'.format(s.frame_ids, timeout), timeout)
        else:
            return (ord(r[0]), r[1:])

    def _recvSpecificMessage(self, *expected_frame_id, **only_timeout):
        w = self._recv_msg_prep(self, *expected_frame_id)
        return self._recv_msg_wait(w, **only_timeout)

    def _send_msg_w_resp(self, send_frame_id, payload, recv_frame_id, timeout=_DEFAULT_TIMEOUT):
        """ Send a full message (with payload) and wait for a responce """
        w = self._recv_msg_prep(self, recv_frame_id)
        self._sendMessage(send_frame_id, payload)
        return self._recv_msg_wait(w, timeout=timeout)

    def _send_s_msg_w_resp(self, send_frame_id, recv_frame_id, timeout=_DEFAULT_TIMEOUT):
        """ Send a simple message (only frame id) and wait for a responce. """
        w = self._recv_msg_prep(self, recv_frame_id)
        self._sendMessage(send_frame_id)
        return self._recv_msg_wait(w, timeout=timeout)

    def __init__(self, path, baud):
        self.fp = Serial(
            port     = path,
            baudrate = baud,
            bytesize = serial.EIGHTBITS,
            parity   = serial.PARITY_NONE,
            stopbits = serial.STOPBITS_ONE
        )
        # CRC-16 with generator polynomial X^16 + X^12 + X^5 + 1.
        self.crc = crcmod.mkCrcFun(0b10001000000100001, 0, False)
        self.recv_cbs = []
        self.cb_lock = threading.Lock()

        self.decode_pos = 0
        self.discard_stat = 0
        self.recv_buf = bytearray()

        self.read_th = rt = threading.Thread(target=self.reader())
        rt.daemon = True
        rt.start()

    def close(self):
        self.fp.flush()
        self.fp.close()

    def _send(self, fmt):
        self.fp.write(fmt)

    def _sendMessage(self, frame_id, payload=b''):
        count = len(payload) + 5
        head = struct.pack('>HB{0}s'.format(len(payload)), count, frame_id, payload)
        tail = struct.pack('>H', self.crc(head))
        self._send(head + tail)

    def _createDatum(self, data):
        for component in self.Datum._fields:
            if component not in data.keys():
                data[component] = None
        return self.Datum(**data)

    def getModelInfo(self):
        """
        Query the module's type and firmware revision number.
        """
        (_, payload) = self._send_s_msg_w_resp(FrameID.kGetModInfo, FrameID.kGetModInfo)
        return self.ModInfo(*struct.unpack('>4s4s', payload))
    
    def readData(self, timeout=None):
        """
        Read a single DataResp frame
        """
        (_, payload) = self._recvSpecificMessage(FrameID.kDataResp, timeout=timeout)

        (comp_count, ) = struct.unpack('>B', payload[0])
        comp_index = 0
        offset = 1
        data = dict()

        while comp_index < comp_count:
            (component_id, ) = struct.unpack('>B', payload[offset])
            component        = self.components[component_id]

            datum = payload[(offset + 1):(offset + component.struct.size + 1)]
            (value, ) = component.struct.unpack(datum)
            data[component.name] = value

            offset     += 1 + component.struct.size
            comp_index += 1

        return self._createDatum(data)

    def getData(self, timeout=None):
        """
        Query a single packet of data that containing the components specified
        by setDataComponents(). All other components are set to zero.
        """
        # FIXME: race condition: data may already have passed us by before we are listening.
        self._sendMessage(FrameID.kGetData)
        return self.readData(timeout)

    def setConfig(self, config_id, value):
        """
        Sets a single configuration value based on the config_id, which must be
        one of the values in Configuration. Acceptable values deend upon the
        configuration option being set.
        """
        payload_id    = _struct_uint8.pack(config_id)
        payload_value = self.config[config_id].struct.pack(value)

        self._send_msg_w_resp(FrameID.kSetConfig, payload_id + payload_value, FrameID.kSetConfigDone)

    def setOrientation(self, orientation):
        """
        Set the orientation of the compass
        """
        self.setConfig(Configuration.kMountingRef, orientation)

    def takeUserCalSample(self):
        """
        Commands the module to take a sample during user calibration.
        """
        self._sendMessage(FrameID.kTakeUserCalSample)

    def getConfig(self, config_id):
        """
        Get the value of a single configuration value based on config_id.
        """
        payload_id = self._struct_uint8.pack(config_id)
        (_, response) = self._send_msg_w_resp(FrameID.kGetConfig, payload_id, FrameID.kConfigResp)
        (response_id, ) = self._struct_uint8.unpack(response[0])

        if response_id == config_id:
            (value, ) = self.config[config_id].struct.unpack(response[1:])
            return value
        else:
            raise IOError('Response has unexpected configuration id: {0}.'
                           .format(response_id))

    def setFilter(self, count, values=None):
        """
        Configure the number of taps and weights of the on-board finite impulse
        response (FIR) filter. The number of taps must be zero (i.e. disabled),
        4, 8, 16, or 32. If values is omitted or is set to None, the weights
        default to PNI's recommended values. See the Fieldforce TCM User Manual
        for details.
        """
        assert count in [ 0, 4, 8, 16, 32 ]

        if values == None:
            values = self.fir_defaults[count]
        else:
            assert len(values) == count

        payload = struct.pack('>BBB{0}d'.format(count), 3, 1, count, *values)
        self._send_msg_w_resp(FrameID.kSetParam, payload, FrameID.kSetParamDone)

    def getFilter(self):
        """
        Gets the current finite impulse response (FIR) filter weights. See
        setFilter() for more information.
        """
        payload_request  = struct.pack('>BB', 3, 1)

        (_, payload_response) = self._send_msg_w_resp(FrameID.kGetParam, payload_request, FrameID.kParamResp)

        param_id, axis_id, count = struct.unpack('>BBB', payload_response[0:3])

        if param_id != 3:
            raise IOError('Expected param ID of 3, got {0}'.format(param_id))
        elif axis_id != 1:
            raise IOError('Expected axis ID of 1, got {0}'.format(axis_id))

        fir = struct.unpack('>{0}d'.format(count), payload_response[3:])
        return list(fir)

    def setDataComponents(self, components):
        """
        Specify which data components, specified as a list of component IDs,
        will be returned with each sample. An arbitrary number of IDs is
        supported.
        """
        count = len(components)
        payload_counts  = struct.pack('>B', count)
        payload_content = struct.pack('>{0}B'.format(count), *components)
        payload = payload_counts + payload_content
        self._sendMessage(FrameID.kSetDataComponents, payload)

    def setAcquisitionParams(self, mode, flush_filter, acq_time, resp_time):
        """
        Set the acquisition mode, including:
         - PollingMode: poll if true, push if false
         - FlushFilter: flush the FIR filter registers after each sample
         - SensorAcqTime: time between sample in seconds
         - IntervalRespTime: time delay between sending subsequent samples
        Even if polling is enabled here, it must be explicitly started using
        startStreaming().
        """
        payload = struct.pack('>BBff', mode, flush_filter, acq_time, resp_time)

        self._send_msg_w_resp(FrameID.kSetAcqParams, payload, FrameID.kAcqParamsDone)

    def getAcquisitionParams(self):
        """
        Gets the current acquisition mode. See setAcquisitionParams() for more
        information.
        """
        (_, payload) = self._send_s_msg_w_resp(FrameID.kGetAcqParams, kAcqParamsResp)
        response = struct.unpack('>BBff', payload)
        return self.AcqParams(*response)

    def startStreaming(self):
        """
        Start streaming data. See setAcquisitionParams() for more information
        and use stopStreaming() when done. Streaming must be stopped before any
        other commands can be used.
        """
        self._sendMessage(FrameID.kStartIntervalMode)

    def stopAll(self):
        """
        Stop all modes which result in periodic messages
        """
        self.stopStreaming()
        self.stopCalibration()

    def stopStreaming(self):
        """
        Stops streaming data; companion of startStreaming(). Streaming must be
        stopped before any other commands can be used.
        """
        self._sendMessage(FrameID.kStopIntervalMode)
    
    def stopCalibration(self):
        """
        Stops calibration;
        """
        self._sendMessage(FrameID.kStopCal)

    def powerUp(self):
        """
        Power up the sensor after a powerDown(). This has undefined results if
        the sensor is already powered on.
        """
        w = self._recv_msg_prep(FrameID.kPowerUp)
        self._send(b'\xFF')
        self._recv_msg_wait(w)

    def powerDown(self):
        """
        Power down the sensor down.
        """
        self._send_s_msg_w_resp(FrameID.kPowerDown, FrameID.kPowerDownDone)

    def save(self):
        """
        Write the current configuration to non-volatile memory. Note that this
        is the only command that writes to non-volatile memory, so it should be
        paired with any configuration options (e.g. calibration) that are
        intended to be persistant.
        """
        (_, response) = self._send_s_msg_w_resp(FrameID.kSave, FrameID.kSaveDone)
        (code, ) = _struct_uint16.unpack(response)

        if code != 0:
            raise IOError('Save failed with error code {0}.'.format(code))

    def startCalibration(self, mode=None):
        """
        Starts calibration. See the FieldForce TCM User Manual for details
        about the necessary setup for each calibration mode.
        When mode = None, the last calibration mode used is repeated.
        """
        if mode == None:
            self._sendMessage(FrameID.kStartCal)
        else:
            payload_mode = _struct_uint32.pack(mode)
            self._sendMessage(FrameID.kStartCal, payload_mode)


    def getCalibrationStatus(self, timeout=15):
        """
        Blocks waiting for a calibration update from the sensor. This returns a
        tuple where the first elements is a boolean that indicates whether the
        calibration is complete.
        """
        frame_id, message = self._recvSpecificMessage(FrameID.kUserCalSampCount, FrameID.kUserCalScore, timeout=timeout)

        # One UserCalSampCount message is generated for each recorded
        # sample. This continues until the calibration has converged or the
        # maximum number of points have been collected.
        if frame_id == FrameID.kUserCalSampCount:
            (sample_num, ) = _struct_uint32.unpack(message)
            return (False, sample_num)
        # Calibration accuracy is reported in a single UserCalScore message
        # once calibration is complete.
        elif frame_id == FrameID.kUserCalScore:
            scores_raw = struct.unpack('>6f', message)
            scores     = self.CalScores(*scores_raw)
            return (True, scores)
        else:
            raise IOError('Unexpected frame id: {0}.'.format(frame_id))

    def resetMagCalibration(self):
        self._send_s_msg_w_resp(FrameID.kFactoryUserCal, FrameID.kFactoryUserCalDone)

    def resetAccelCalibration(self):
        self._send_s_msg_w_resp(FrameID.kFactoryInclCal, FrameID.kFactoryInclCalDone)
Example #45
0
    def handle_send_break_cmd(self, port, disk, reset_type=None, baudrate=115200, timeout=1, verbose=False):
        """! Resets platforms and prints serial port output
            @detail Mix with switch -r RESET_TYPE and -p PORT for versatility
        """
        from serial import Serial

        if not reset_type:
            reset_type = 'default'

        port_config = port.split(':')
        if len(port_config) == 2:
            # -p COM4:115200
            port = port_config[0]
            baudrate = int(port_config[1])
        elif len(port_config) == 3:
            # -p COM4:115200:0.5
            port = port_config[0]
            baudrate = int(port_config[1])
            timeout = float(port_config[2])

        if verbose:
            print "mbedhtrun: serial port configuration: %s:%s:%s"% (port, str(baudrate), str(timeout))

        try:
            serial_port = Serial(port, baudrate=baudrate, timeout=timeout)
        except Exception as e:
            print "mbedhtrun: %s" % (str(e))
            print json.dumps({
                "port" : port,
                "disk" : disk,
                "baudrate" : baudrate,
                "timeout" : timeout,
                "reset_type" : reset_type,
                }, indent=4)
            return False

        serial_port.flush()
        # Reset using one of the plugins
        result = host_tests_plugins.call_plugin('ResetMethod', reset_type, serial=serial_port, disk=disk)
        if not result:
            print "mbedhtrun: reset plugin failed"
            print json.dumps({
                "port" : port,
                "disk" : disk,
                "baudrate" : baudrate,
                "timeout" : timeout,
                "reset_type" : reset_type
                }, indent=4)
            return False

        print "mbedhtrun: serial dump started (use ctrl+c to break)"
        try:
            while True:
                test_output = serial_port.read(512)
                if test_output:
                    sys.stdout.write('%s'% test_output)
                if "{end}" in test_output:
                    if verbose:
                        print
                        print "mbedhtrun: stopped (found '{end}' terminator)"
                    break
        except KeyboardInterrupt:
            print "ctrl+c break"

        serial_port.close()
        return True
class CommunicationGroup10:
    def __init__(self, usb_port_number):
        """communication interface for sending commands and receiving sensor info to/from the Arduino

        :param usb_port_number: the USB port number for the SRF stick - normally either 1 or 0, found by finding X in
                the /dev/ttyACMX corresponding to the SRF stick (numbered by the order of USB devices connected)
        """
        self.closed = True
        self.connection = None
        self.sender = None
        self.port = '/dev/ttyACM{}'.format(usb_port_number)
        self.baudrate = 115200
        self.has_ball = False
        self.timeout = 5

        # start the router thread
        self.router_thread = None
        self.router_thread_alive = False
        self.list = []

    def __enter__(self):
        return self

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

    def open(self, handle_message):
        self.handle_message = handle_message

        print("[COMMS GROUP 10] opening connection...")
        self.router_thread = Thread(target=self.router, name="Communication Group 10 Thread")
        self.connection = Serial(port=self.port, baudrate=self.baudrate, timeout=self.timeout)
        self.sender = Sender(self.connection)
        self.connection.flush()
        self.router_thread_alive = True
        self.router_thread.start()

        self.closed = False

    # shortcut functions for commands that can be sent
    def configure_command(self, bearing, heading, grabbing=0, kicking=0):
        self.list.append("{}{}{}{}".format(self.bearing_to_byte_string(bearing), self.bearing_to_byte_string(heading),
                                           chr(grabbing+33), chr(kicking+33)))

    @staticmethod
    def bearing_to_byte_string(angle):
        # range  0 to 180
        angle_one = int(angle/2)
        angle_two = angle - angle_one
        return "{}{}".format(chr(int(angle_one+33)), chr(angle_two+33))

    def router(self):
        """separate thread for routing received bytes to sender/receiver, and handling them appropriately"""
        while self.router_thread_alive:
            try:
                tm.sleep(0.1)
                d = None
                if len(self.list) > 0:
                    self.connection.write(self.list[-1])
                    self.list = self.list[:-1]
                d = self.connection.read(1)
                if d == 't':
                    self.handle_message("B")
                    print "[COMMS GROUP 10] ball acquired"
                else:
                    self.handle_message("G")
            except Exception as e:
                self.close()
                raise e

    def close(self):
        """must be called to kill the router thread and exit cleanly"""
        if not self.closed:
            self.closed = True
            print("[COMMS GROUP 10] closing connection")
            self.router_thread_alive = False  # kill the router thread
            self.connection.close()  # kill the serial connection

    def restart(self):
        self.close()
        self.open(self.handle_message)
Example #47
0
from serial import Serial
import pynmea2

GPS = Serial(port = '/dev/ttyUSB0', baudrate = 4800)
GPS.flush()

for i in range(10):
	inp_data = GPS.readline()
	msg = pynmea2.parse(inp_data)
	print msg
	try:
		print msg.timestamp
		print "Longitude: {}".format(msg.longitude)
		print "Latitude: {}".format(msg.latitude)
		print "Speed: {}".format(msg.spd_over_grnd)
		print msg
	except:
		pass
	
class Teensy:

	def __init__(self, device):
		self.errorCount = 0
		self.initSerial(device)

	def __del__(self):
		if self.serial is not None:
			self.serial.close()
			#logging.debug("Teensy close")

	def initSerial(self, device):
		self.serial = Serial(device, 115200, timeout=1)
		self.serial.write("l 0")
		self.serial.flushInput()
		self.initDevice()

	def initDevice(self):
		response = self.sendCommand("i", seperator="|")
		self.name = None
		try:
			name = response[0]
			if name:
				self.name = name
		except:
			print "InitDevice Error"
			pass

	def write(self, data):
		self.serial.write(data)

	def read(self, numBytes):
		return self.serial.read(numBytes)

	def readWaiting(self):
		if self.serial.inWaiting() > 0:
			return self.read(self.serial.inWaiting())
		return ""

	def sendCommand(self, strCommand, seperator=None):
		# sende Kommando und liefere Ergebnis, besserer Name
		try:
			#self.serial.flush()
			self.serial.write(strCommand)
			#self.serial.flush()
			response = self.serial.readline().strip()
			if seperator is not None:
				response = response.split(seperator)
			return response
		except SerialException as e:
			print "Error sendCommand", type(e), e.message
			self.reCover()
			raise
			# device reports readiness to read but returned no data (device disconnected or multiple access on port?)
			# Attempting to use a port that is not open
			# write failed: [Errno 6] Device not configured

	def reCover(self):
		self.errorCount += 1
		if self.errorCount > 10:
			self.serial.close()
			print "Reinit Serial"
			self.initSerial(self.serial.name)
			self.serial.flush()
			self.errorCount = 0
			time.sleep(1)

	def sendQuick(self, strCommand):
		# sende Kommando, besserer Name
		try:
			self.serial.flush()
			self.serial.write(strCommand)
			#self.serial.flush()
		except:
			raise
Example #49
0
class Ostrich2(object):

    def __init__(self, device):
        self.channel = Serial(device, 921600, timeout = 5, writeTimeout = 5)
        self.channel.flushInput()


    def disconnect(self):
        '''
        '''
        self.channel.close()
    
    @staticmethod
    def default_device():
        if platform.system() == 'Windows':
            return 'COM3'
        elif platform.system() == 'Darwin':
            serial_devices = glob.glob('/dev/tty.usbserial-*')
            return serial_devices[0] if len(serial_devices) else '?'
        else:
            return '/dev/ttyUSB0'

    ###########################################################################
    ##
    ## IO operations
    ##
    ###########################################################################

    def write(self, data):
        '''
        Write a sequence of bytes
        '''
        if isinstance(data, int):
            data = bytes((data,))
        result = self.channel.write(data)
        if result != len(data):
            raise Exception('write timeout')
        self.channel.flush()

    def write_with_checksum(self, data):
        self.write(data)
        self.write(make_checksum(data))

    def read_with_checksum(self, size):
        data = self.read(size)
        checksum = self.read(1)
        if checksum != make_checksum(data):
            pass # TODO raise Exception('Read checksum does not match')
        return data

    def read(self, size = 1):
        '''
        Read a sequence of bytes
        '''
        if size == 0:
            return

        result = self.channel.read(size)
        if len(result) != size:
            raise Exception('I/O error')
        return result

    def read_byte(self):
        '''
        Read a single byte
        '''
        return int(self.read()[0])

    ##
    ## Protocol
    ##

    def version(self):
        self.write(b'VV')
        device_type = self.read_byte()
        version = self.read_byte()
        device_id = chr(self.read_byte())
        return (device_type, version, device_id)

    def serial_number(self):
        '''
        returns (vendor ID, serial number)
        '''
        self.write_with_checksum(b'NS')
        result = self.read_with_checksum(9)
        vendor_id = int(result[0])
        serial_number = ''.join(hex(b)[2:] for b in result[1:])
        return (vendor_id, serial_number)

    def write_memory(self, data, start_address, chunk_size = 0x1000):
        if (len(data) & 0xff) or (start_address & 0xff):
            raise Exception('Can only write 0x0100 byte blocks')

        for address in range(start_address, start_address + len(data), chunk_size):
                offset = address - start_address
                block = data[offset:offset + chunk_size]
                block_count = len(block) >> 8
                mmsb = (address >> 16) & 0x07
                msb = (address >> 8) & 0xff

                message = bytearray(b'ZW')
                message += bytes((block_count,))
                message += bytes((mmsb,))
                message += bytes((msb,))
                message += block
                self.write_with_checksum(message)
                self.expect_ok()
                yield len(block)

    def read_memory(self, start, end, chunk_size = 0x1000):
        # Can only read full 0x100 byte pages
        read_start = start & 0x7ff00
        read_end = (end & 0x7ff00) + 0x0100

        block_count = chunk_size >> 8
        for address in range(read_start, read_end, chunk_size):

            this_chunk_size = chunk_size
            trim_start = start - address
            if trim_start > 0:
                this_chunk_size -= trim_start & 0x7ff00
                trim_start &= 0xff

            trim_end = (address + this_chunk_size) - end - 1
            if trim_end > 0:
                this_chunk_size -= trim_end & 0x7ff00
                trim_end &= 0xff
            
            mmsb = (address >> 16) & 0x07
            msb = (address >> 8) & 0xff
            message = bytearray(b'ZR')
            message += bytes((block_count,))
            message += bytes((mmsb,))
            message += bytes((msb,))
            self.write_with_checksum(message)
            data = self.read_with_checksum(this_chunk_size)

            if trim_start > 0:
                data = data[trim_start:]
            if trim_end > 0:
                data = data[:-trim_end]
            yield data

    def expect_ok(self):
        response = self.read()
        if response != b'O':
            raise Exception('Write error')

    def set_io_bank(self, bank):
        message = bytearray(b'BR')
        message += bytes((bank,))
        self.write_with_checksum(message)
        self.expect_ok()

    def get_io_bank(self):
        self.write_with_checksum(b'BRR')
        return self.read_byte()

    def set_emulation_bank(self, bank, persistent = False):
        if persistent:
            message = bytearray(b'BS')
        else:
            message = bytearray(b'BE')
        message += bytes((bank,))
        self.write_with_checksum(message)
        self.expect_ok()

    def get_emulation_bank(self, persistent = False):
        if persistent:
            message = b'BES'
        else:
            message = b'BER'
        self.write_with_checksum(message)
        return self.read_byte()
Example #50
0
class Stk500v2(ispBase.IspBase):
	def __init__(self):
		self.serial = None
		self.seq = 1
		self.lastAddr = -1
		self.progressCallback = None
	
	def connect(self, port = 'COM22', speed = 115200):
		if self.serial != None:
			self.close()
		try:
			self.serial = Serial(port, speed, timeout=1, writeTimeout=10000)
		except SerialException as e:
			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
		self.serial.setDTR(1)
		time.sleep(0.1)
		self.serial.setDTR(0)
		time.sleep(0.2)
		
		self.sendMessage([1])
		if self.sendMessage([0x10, 0xc8, 0x64, 0x19, 0x20, 0x00, 0x53, 0x03, 0xac, 0x53, 0x00, 0x00]) != [0x10, 0x00]:
			self.close()
			raise ispBase.IspError("Failed to enter programming mode")

	def close(self):
		if self.serial != 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 != 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 != None
	
	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, flashData):
		#Set load addr to 0, in case we have more then 64k flash we need to enable the address extension
		pageSize = self.chip['pageSize'] * 2
		flashSize = pageSize * self.chip['pageCount']
		if flashSize > 0xFFFF:
			self.sendMessage([0x06, 0x80, 0x00, 0x00, 0x00])
		else:
			self.sendMessage([0x06, 0x00, 0x00, 0x00, 0x00])
		
		loadCount = (len(flashData) + pageSize - 1) / pageSize
		for i in xrange(0, loadCount):
			recv = self.sendMessage([0x13, pageSize >> 8, pageSize & 0xFF, 0xc1, 0x0a, 0x40, 0x4c, 0x20, 0x00, 0x00] + flashData[(i * pageSize):(i * pageSize + pageSize)])
			if self.progressCallback != None:
				self.progressCallback(i + 1, loadCount*2)
	
	def verifyFlash(self, flashData):
		#Set load addr to 0, in case we have more then 64k flash we need to enable the address extension
		flashSize = self.chip['pageSize'] * 2 * self.chip['pageCount']
		if flashSize > 0xFFFF:
			self.sendMessage([0x06, 0x80, 0x00, 0x00, 0x00])
		else:
			self.sendMessage([0x06, 0x00, 0x00, 0x00, 0x00])
		
		loadCount = (len(flashData) + 0xFF) / 0x100
		for i in xrange(0, loadCount):
			recv = self.sendMessage([0x14, 0x01, 0x00, 0x20])[2:0x102]
			if self.progressCallback != None:
				self.progressCallback(loadCount + i + 1, loadCount*2)
			for j in xrange(0, 0x100):
				if i * 0x100 + j < len(flashData) and flashData[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 ^= ord(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
			#print(hex(b))
			if state == 'Start':
				if b == 0x1B:
					state = 'GetSeq'
					checksum = 0x1B
			elif state == 'GetSeq':
				state = 'MsgSize1'
			elif state == 'MsgSize1':
				msgSize = b << 8
				state = 'MsgSize2'
			elif state == 'MsgSize2':
				msgSize |= b
				state = 'Token'
			elif state == 'Token':
				if b != 0x0E:
					state = 'Start'
				else:
					state = 'Data'
					data = []
			elif state == 'Data':
				data.append(b)
				if len(data) == msgSize:
					state = 'Checksum'
			elif state == 'Checksum':
				if checksum != 0:
					state = 'Start'
				else:
					return data
Example #51
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()
        if self.sendMessage([0x10, 0xc8, 0x64, 0x19, 0x20, 0x00, 0x53, 0x03, 0xac, 0x53, 0x00, 0x00]) != [0x10, 0x00]:
            self.close()
            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
        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 #52
0
Continuously read the serial port and process IO data received from a remote XBee.
"""

# This version is for the pi

import time
from xbee import XBee
from serial import Serial

ser = Serial('/dev/tty.usbserial-A7025WZ6', 57600)
#ser = Serial('/dev/xbee', 57600)

xbee = XBee(ser)

data = 1
# Continuously send
while data == 1:
    try:
        
        signal = ['up', 'down', 'right', 'left']
        #print signal
        #send = xbee.send("str(signal")
        xbee.send("at", frame="A", command='MY', parameter=None)
        ser.flush()
        #send = ser.writelines("testing API\n")
        time.sleep(.5)
        data += 1
    except KeyboardInterrupt:
        break
        
ser.close()
Example #53
0
class SuperSimon:
    def __init__(self, configuration):
        self.__conf = configuration
        self._init_port()
        self.__readDumpTimeout = 250  # ms
        self.__magicTimeout = 250  # ms
        self.players = []
        self.__queue = EventQueue()

    def _init_port(self):
        self.__port = Serial(self.__conf.device, baudrate=9600)

    def check_joins(self):
        self.__queue.enqueue(self.__protocol_join_state)

    def discover_clients(self):
        self.__queue.enqueue(self.__protocol_discover)

    def check_game_info(self, address):
        self.__queue.enqueue(self.__protocol_game_info_request, [address])

    def send_sequence(self, address, sequence):
        self.__queue.enqueue(self.__protocol_send_sequence, [address, sequence])

    def start_game(self, address):
        self.__queue.enqueue(self.__protocol_start_game, [address])

    def exit(self):
        print("Stopping communication...")
        self.__queue.stop()
        self.__port.close()

    def _find_or_create_player(self, address):
        for player in self.players:
            if player.address == address:
                return player
        player = Player(address)
        self.players.append(player)
        return player

    @staticmethod
    def _format_byte(b):
        if b is None:
            return '<None>'
        return b.encode('hex')

    # ==========================================================================
    # BELOW HERE ARE THE PROTOCOL HELPERS / THREAD TARGETS
    # ==========================================================================

    # noinspection PyMethodMayBeStatic
    def __protocol_request_turn(self):
        return

    def __protocol_end_turn(self):
        self.__port.flush()
        sleep(0.01)  # Sleep for 10ms to allow things to calm down
        return

    def __protocol_discover(self):
        self.__protocol_request_turn()
        maximum_discover = 255
        if self.__conf.discoverMaximum > -1:
            maximum_discover = min(self.__conf.discoverMaximum, 255)
        for addr in range(0, maximum_discover):
            print("Sending discover to address " + str(addr) + "...")
            discovered = self.__protocol_send_discover(addr)
            player = self._find_or_create_player(addr)
            player.online = discovered
            # print("Address " + str(addr) + " discovered = " + str(discovered))
        self.__protocol_end_turn()

    def __protocol_join_state(self):
        self.__protocol_request_turn()
        for player in self.players:
            if player.online and not player.joined:
                print("Sending join state request to address " + str(player.address) + "...")
                joined = self.__protocol_request_join_state(player.address)
                if joined is None:
                    player.online = False
                    player.reset()
                    print("Address " + str(player.address) + " has been considered as offline")
                else:
                    player.joined = joined
                    # print("Address " + str(player.address) + " joined = " + str(joined))
        self.__protocol_end_turn()

    def __protocol_game_info_request(self, address):
        player = self._find_or_create_player(address)
        if player.checkingGameInfo:
            return
        player.checkingGameInfo = True  # Before protocol lockout to avoid duplicate locks
        self.__protocol_request_turn()
        print("Sending game info request to address " + str(address) + "...")
        game_info = None
        try:
            game_info = self.__protocol_request_game_info(address)
        except ValueError as e:
            print(str(e))
            player.online = False
            player.reset()
            print("Address " + str(address) + " has been considered as offline")
        if game_info is not None:
            player.lastGameInfo = game_info
            player.roundCompleted = True
        self.__protocol_end_turn()
        player.checkingGameInfo = False

    def __protocol_send_sequence(self, address, sequence):
        self.__protocol_request_turn()
        print("Sending sequence to address " + str(address) + "...")
        player = self._find_or_create_player(address)
        try:
            self.__protocol_send_game_info(address, sequence)
        except ValueError as e:
            print(str(e))
            player.online = False
            player.reset()
            print("Address " + str(address) + " has been considered offline")
        self.__protocol_end_turn()

    def __protocol_start_game(self, address):
        self.__protocol_request_turn()
        print("Sending start game...")
        self.__protocol_send_start_game(address)
        self.__protocol_end_turn()

    # ==========================================================================
    # BELOW HERE ARE THE PROTOCOL IMPLEMENTATIONS
    # ==========================================================================

    def __protocol_read(self, throw_ex=False):
        v = self.__port.read()
        if v == '':
            if throw_ex:
                raise ValueError("Failed to read from serial port: Timeout?")
            return None
        return v

    def __protocol_send_magic(self):
        sequence = '\xDE\xAD\xBE\xEF'
        self.__port.write(sequence)

    def __protocol_read_magic(self):
        sequence = ['\xCA', '\xFE', '\xBA', '\xBE']
        curr_index = 0
        last_read = millis()
        while curr_index < len(sequence):
            b = self.__protocol_read()
            if b is None:
                raise ValueError('Could not read magic value: Timeout')
            now = millis()
            if (now - last_read) > self.__readDumpTimeout:
                curr_index = 0
            if b == sequence[curr_index]:
                curr_index += 1

    def __protocol_read_int(self):
        byte_str = ""
        byte_str += self.__protocol_read(True)
        byte_str += self.__protocol_read(True)
        byte_str += self.__protocol_read(True)
        byte_str += self.__protocol_read(True)
        return struct.unpack(">L", byte_str)[0]

    def __protocol_read_short(self):
        byte_str = ""
        byte_str += self.__protocol_read(True)
        byte_str += self.__protocol_read(True)
        return struct.unpack(">H", byte_str)[0]

    def __protocol_write_int(self, i):
        self.__port.write(struct.pack(">I", i))

    def __protocol_read_ack(self):
        self.__protocol_read_magic()
        b = self.__protocol_read()
        if b != '\x00':
            raise ValueError("Failed to read acknowledge: Invalid byte received (got " + self._format_byte(b) + ")")

    def __protocol_read_join_response(self):
        self.__protocol_read_magic()
        b = self.__protocol_read()
        if b == '\x07':
            return False
        elif b == '\x08':
            return True
        else:
            raise ValueError("Failed to read join response: Invalid byte received (got " + self._format_byte(b) + ")")

    def __protocol_read_game_info_request(self):
        self.__protocol_read_magic()
        b = self.__protocol_read()
        if b == '\x04':
            return None  # No game info
        elif b == '\x05':
            # Has game information
            # noinspection PyUnusedLocal
            address = self.__protocol_read(True)  # Ignored address - not important
            length = self.__protocol_read_int()
            i = 0
            game_info = []
            expecting_button = True
            last_button = None
            while i < length:
                if expecting_button:
                    last_button = ord(self.__protocol_read(True))
                    expecting_button = False
                    i += 1  # Button is 1 byte
                else:
                    ms = self.__protocol_read_short()
                    expecting_button = True
                    i += 2  # Shorts are 2 bytes
                    game_info.append(PressedButton(last_button, ms))
            return game_info
        else:
            raise ValueError(
                "Failed to read game information response: Invalid byte received (got " + self._format_byte(b) + ")")

    def __protocol_send_discover(self, address):
        self.__protocol_send_magic()
        self.__port.write('\x09')
        self.__port.write(chr(address))
        prev_timeout = self.__port.timeout
        self.__port.timeout = self.__magicTimeout / 1000.0
        received = True
        try:
            self.__protocol_read_ack()
        except ValueError as e:
            print(str(e))
            received = False
        self.__port.timeout = prev_timeout
        return received

    def __protocol_request_join_state(self, address):
        self.__protocol_send_magic()
        self.__port.write('\x06')
        self.__port.write(chr(address))
        prev_timeout = self.__port.timeout
        self.__port.timeout = self.__magicTimeout / 1000.0
        try:
            joining = self.__protocol_read_join_response()
        except ValueError as e:
            print(str(e))
            joining = None
        self.__port.timeout = prev_timeout
        return joining

    def __protocol_request_game_info(self, address):
        self.__protocol_send_magic()
        self.__port.write('\x03')
        self.__port.write(chr(address))
        prev_timeout = self.__port.timeout
        self.__port.timeout = self.__magicTimeout / 1000.0
        val = None
        err = None
        try:
            val = self.__protocol_read_game_info_request()
        except ValueError as e:
            err = e
        self.__port.timeout = prev_timeout
        if err:
            raise err
        return val

    def __protocol_send_game_info(self, address, sequence):
        self.__protocol_send_magic()
        self.__port.write('\x01')
        self.__port.write(chr(address))
        self.__protocol_write_int(len(sequence))
        for i in sequence:
            self.__port.write(chr(i))
        prev_timeout = self.__port.timeout
        self.__port.timeout = self.__magicTimeout / 1000.0
        err = None
        try:
            self.__protocol_read_ack()
        except ValueError as e:
            err = e
        self.__port.timeout = prev_timeout
        if err is not None:
            raise err

    def __protocol_send_start_game(self, address):
        self.__protocol_send_magic()
        self.__port.write('\x02')
        self.__port.write(chr(address))
Example #54
0
class printcore():
    def __init__(self, port = None, baud = None):
        """Initializes a printcore instance. Pass the port and baud rate to
           connect immediately"""
        self.baud = None
        self.port = None
        self.analyzer = GCodeAnalyzer()
        self.printer = None  # Serial instance connected to the printer,
                             # should be None when disconnected
        self.clear = 0  # clear to send, enabled after responses
        self.online = False  # The printer has responded to the initial command
                             # and is active
        self.printing = False  # is a print currently running, true if printing
                               # , false if paused
        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.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
        self.pronterface = None

    @locked
    def disconnect(self):
        """Disconnects from printer and pauses the print
        """
        if self.printer:
            if self.read_thread:
                self.stop_read_thread = True
                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):
        """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 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.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:
                    print _("Could not connect to %s:%s:") % (hostname, port)
                    self.printer = None
                    self.printer_tcp = None
                    print _("Socket error %s:") % e.errno,
                    print e.strerror
                    return
            else:
                disable_hup(self.port)
                self.printer_tcp = None
                try:
                    self.printer = Serial(port = self.port,
                                          baudrate = self.baud,
                                          timeout = 0.25)
                except SerialException as e:
                    print _("Could not connect to %s at baudrate %s:") % (self.port, self.baud)
                    self.printer = None
                    print _("Serial error: %s") % e
                    return
            self.stop_read_thread = False
            self.read_thread = 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: pass
                if self.loud: print "RECV:", line.rstrip()
            return line
        except SelectError as e:
            if 'Bad file descriptor' in e.args[1]:
                print _(u"Can't read from printer (disconnected?) (SelectError {0}): {1}").format(e.errno, decode_utf8(e.strerror))
                return None
            else:
                print _(u"SelectError ({0}): {1}").format(e.errno, decode_utf8(e.strerror))
                raise
        except SerialException as e:
            print _(u"Can't read from printer (disconnected?) (SerialException): {0}").format(decode_utf8(str(e)))
            return None
        except socket.error as e:
            print _(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 ""
            print _(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:
                print _("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:
                    if self.onlinecb:
                        try: self.onlinecb()
                        except: pass
                    self.online = True
                    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: pass
            elif line.startswith('Error'):
                if self.errorcb:
                    #callback for errors
                    try: self.errorcb(line)
                    except: pass
            # 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
                        #print str(toresend)
                        break
                    except:
                        pass
                self.clear = True
        self.clear = True

    def _start_sender(self):
        self.stop_send_thread = False
        self.send_thread = 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.printing = True
        self.mainqueue = gcode
        self.lineno = 0
        self.queueindex = startindex
        self.resendfrom = -1
        self._send("M110", -1, True)
        if not gcode.lines:
            return True
        self.clear = False
        resuming = (startindex != 0)
        self.print_thread = Thread(target = self._print,
                                   kwargs = {"resuming": resuming})
        self.print_thread.start()
        return 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:
            pass

        self.print_thread = None

        # saves the status
        self.pauseX = self.analyzer.x - self.analyzer.xOffset
        self.pauseY = self.analyzer.y - self.analyzer.yOffset
        self.pauseZ = self.analyzer.z - self.analyzer.zOffset
        self.pauseE = self.analyzer.e - self.analyzer.eOffset
        self.pauseF = self.analyzer.f
        self.pauseRelative = self.analyzer.relative

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

            xyFeedString = ""
            zFeedString = ""
            if self.xy_feedrate is not None:
                xyFeedString = " F" + str(self.xy_feedrate)
            if self.z_feedrate is not None:
                zFeedString = " F" + str(self.z_feedrate)

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

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

        self.paused = False
        self.printing = True
        self.print_thread = Thread(target = self._print,
                                   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:
            print "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:
            print "Not connected to printer."

    def _print(self, resuming = False):
        self._stop_sender()
        try:
            if self.startcb:
                #callback for printing started
                try: self.startcb(resuming)
                except:
                    print "Print start callback failed with:"
                    traceback.print_exc(file = sys.stdout)
            while self.printing and self.printer and self.online:
                self._sendnext()
            self.sentlines = {}
            self.log.clear()
            self.sent = []
            if self.endcb:
                #callback for printing done
                try: self.endcb()
                except:
                    print "Print end callback failed with:"
                    traceback.print_exc(file = sys.stdout)
        except:
            print "Print thread died due to the following error:"
            traceback.print_exc(file = sys.stdout)
        finally:
            self.print_thread = None
            self._start_sender()

    #now only "pause" is implemented as host command
    def processHostCommand(self, command):
        command = command.lstrip()
        if command.startswith(";@pause"):
            if self.pronterface is not None:
                self.pronterface.pause(None)
            else:
                self.pause()

    def _sendnext(self):
        if not self.printer:
            return
        while self.printer and self.printing and not self.clear:
            time.sleep(0.001)
        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.queueindex < len(self.mainqueue):
            (layer, line) = self.mainqueue.idxs(self.queueindex)
            gline = self.mainqueue.all_layers[layer][line]
            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: traceback.print_exc()
            if self.preprintsendcb:
                if self.queueindex + 1 < len(self.mainqueue):
                    (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.processHostCommand(tline)
                self.queueindex += 1
                self.clear = True
                return

            tline = tline.split(";")[0]
            if len(tline) > 0:
                self._send(tline, self.lineno, True)
                self.lineno += 1
                if self.printsendcb:
                    try: self.printsendcb(gline)
                    except: traceback.print_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):
        if calcchecksum:
            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
            try: self.analyzer.Analyze(command)
            except:
                print "Warning: could not analyze command %s:" % command
                traceback.print_exc(file = sys.stdout)
            if self.loud:
                print "SENT:", command
            if self.sendcb:
                try: self.sendcb(command)
                except: pass
            try:
                self.printer.write(str(command + "\n"))
                if self.printer_tcp: self.printer.flush()
                self.writefailures = 0
            except socket.error as e:
                print _(u"Can't write to printer (disconnected?) (Socket error {0}): {1}").format(e.errno, decode_utf8(e.strerror))
                self.writefailures += 1
            except SerialException as e:
                print _(u"Can't write to printer (disconnected?) (SerialException): {0}").format(decode_utf8(str(e)))
                self.writefailures += 1
            except RuntimeError as e:
                print _(u"Socket connection broken, disconnected. ({0}): {1}").format(e.errno, decode_utf8(e.strerror))
                self.writefailures += 1
Example #55
0
class CopyNES(object):
    '''
    Interface to a CopyNES device
    '''

    ###########################################################################
    ##
    ## Status operations
    ##
    ###########################################################################

    def __init__(self, data_device, control_device):
        '''
        Connects to a USB CopyNES
        '''

        self.data_channel = Serial(data_device, 115200, timeout = 5)
        self.control_channel = Serial(control_device, 115200, timeout = 5)

        # Empty the read buffer
        time.sleep(0.1)
        self.data_channel.flushInput()

    def disconnect(self):
        '''
        Disconnects from the CopyNES device and frees up all resources
        '''
        self.data_channel.close()
        self.control_channel.close()

    def power(self):
        '''
        Returns True if the CopyNES is powered on
        '''
        return not self.control_channel.getCD()

    def reset(self):
        '''
        Resets the CopyNES CPU.
        In "play" mode, this runs the cartridge program
        In "copy" mode, the CopyNES will be waiting for commands
        '''
        self.control_channel.setDTR(False)
        self.control_channel.setDTR(True)

    def play_mode(self):
        '''
        Resets the CopyNES and puts it in "play" mode
        This disables the BIOS, so no I/O operations will be available
        until "copy" mode is enabled again
        '''
        self.control_channel.setRTS(False)
        self.reset()

    def copy_mode(self):
        '''
        Resets the CopyNES and puts it in "copy" mode
        '''
        self.control_channel.setRTS(True)
        self.reset()

    ###########################################################################
    ##
    ## IO operations
    ##
    ###########################################################################

    def write(self, data):
        '''
        Writes a sequence of bytes to the CopyNES
        '''
        if isinstance(data, int):
            data = bytes((data,))
        result = self.data_channel.write(data)
        self.data_channel.flush()
        return result

    def wait_for_data(self, timeout):
        '''
        Wait until data is available for reading
        '''
        while self.data_channel.inWaiting() == 0 and timeout > 0:
            time.sleep(0.1)
            timeout -= 0.1 # XXX Not very exact method of waiting
        return self.data_channel.inWaiting() > 0

    def read(self, size = 1):
        '''
        Reads a sequence of bytes transferred from the CopyNES
        '''
        if size == 0:
            return

        result = self.data_channel.read(size)
        if len(result) != size:
            raise Exception("timeout")
        return result

    def read_int(self):
        '''
        Reads a single byte transferred from the CopyNES
        '''
        return int(self.read()[0])

    def read_string(self):
        '''
        Reads a zero terminated string
        '''
        result = bytearray()
        byte = self.read()
        while ord(byte) != 0x00:
            result += byte
            byte = self.read()
        return result.decode()

    def flush(self):
        self.data_channel.flush()

    ###########################################################################
    ##
    ## BIOS operations
    ##
    ###########################################################################

    def version_string(self):
        '''
        Returns the CopyNES firmware version string
        '''
        self.write(0xa1)
        return self.read_string()

    def version(self):
        '''
        Returns the CopyNES firmware version number
        '''
        self.write(0xa2)
        return self.read_int()

    def __send_command(self, prolog, address, length, epilog):
        '''
        Send a CopyNES command
        '''
        address_lsb = (address & 0x00ff)
        address_msb = (address & 0xff00) >> 8
        length_lsb = (length & 0x00ff)
        length_msb = (length & 0xff00) >> 8

        if length_lsb != 0x00:
            raise Exception('Memory may only be read/written in $0100 byte chunks, you are trying with a $%04x byte chunk' % length)

        self.write(prolog)
        self.write(address_lsb)
        self.write(address_msb)
        self.write(length_msb)
        self.write(epilog)

    def read_cpu_memory(self, address, length):
        self.__send_command(0x3a, address, length, 0xa3)
        return self.read(length)

    def write_cpu_memory(self, address, data):
        self.__send_command(0x4b, address, len(data), 0xb4)
        return self.write(data)

    def execute_code(self, address):
        self.__send_command(0x7e, address, 0x00, 0xe7)

    ###########################################################################
    ##
    ## Convenience methods
    ##
    ###########################################################################

    def run_plugin(self, plugin):
        self.write_cpu_memory(0x0400, plugin.data)
        self.execute_code(0x0400)

    def download_rom(self, plugin, ines_mapper):

        ##
        ## Packet types sent by dumping plugins
        ##
        PACKET_EOD = 0
        PACKET_PRG_ROM = 1
        PACKET_CHR_ROM = 2
        PACKET_WRAM = 3
        PACKET_RESET = 4

        self.run_plugin(plugin)
        prom = crom = wram = []
        mirroring = self.read_int() ^ 0x01
        (packet_type, data) = self.__read_packet()
        while packet_type != PACKET_EOD:
            if packet_type == PACKET_PRG_ROM:
                prom = data
            elif packet_type == PACKET_CHR_ROM:
                crom = data
            elif packet_type == PACKET_WRAM:
                wram = data
            elif packet_type == PACKET_RESET:
                self.reset()
            else:
                raise Exception('Unexpected packet type: %d' % packet_type)
            (packet_type, data) = self.__read_packet()
        logging.debug('Downloaded prg: %d bytes, chr: %d bytes, wram: %d bytes, mirroring: %d, mapper: %d', len(prom), len(crom), len(wram), mirroring, ines_mapper)
        return NESROM(prom, crom, ines_mapper, mirroring)

    def __read_packet(self):
        pages = self.read_int() | (self.read_int() << 8)
        length = pages << 8
        packet_type = self.read_int()
        if packet_type == 0:
            return (packet_type, 0)
        data = self.read(length)
        return (packet_type, data)

    
    @staticmethod
    def default_data_device():
        if platform.system() == 'Windows':
            return 'COM3'
        elif platform.system() == 'Darwin':
            serial_devices = glob.glob('/dev/tty.usbserial-*')
            return serial_devices[0] if len(serial_devices) >= 2 else '?'
        else:
            return '/dev/ttyUSB0'

    @staticmethod
    def default_control_device():
        if platform.system() == 'Windows':
            return 'COM4'
        elif platform.system() == 'Darwin':
            serial_devices = glob.glob('/dev/tty.usbserial-*')
            return serial_devices[1] if len(serial_devices) >= 2 else '?'
        else:
            return '/dev/ttyUSB1'
Example #56
0
class S128P(object):
    def __init__(self):
        self.debug = True

        print("Init lock.")
        self.lock = Lock()

        print("init s128p")
        self.port = Serial('/dev/ttyAudio', 19200, timeout=1.0) #0.2s timeout from protocol doc
        if self.is_connected():
            print("connected ok!")
        else:
            print("not connected.")

        print("init outputs")
        self.outputs = [Output(i) for i in range(1, self.get_output_count()+1)]
        print("Doing initial download of output data")
        self.refresh_output_data()
        print("outputs done")

        print("init inputs")
        self.inputs = [Input(i) for i in range(1, self.get_input_count()+1)]
        print("Doing initial download of input data")
        self.refresh_input_data()
        print("inputs done")

    def send(self, command):
        self.lock.acquire()
        if self.debug: print("got lock for", command)

        x = "&S12," + command
        result = ""
        ch = None

        while ch == '' or ch == None:
            #we have not received a character. We need to send the command.
            if self.debug: print("sending: " + x)
            self.port.write(x + '\r')
            self.port.flush()
            self.port.reset_input_buffer()
            if self.debug: print("waiting")
            ch = self.port.read()

        while ch != '\r':
            result += ch
            ch = self.port.read()
        #Now you would think we would lose the last character here, because
        #I just read it but didnt push it onto the string.
        #But I have some good news for you: the last character is always \r.

        if self.debug: print("    got: " + result)
        if self.debug: print("Releasing lock for", command)
        self.lock.release()

        try:
            result = result.split(',', 1)
            return result[1] 
        except:
            print("Bogus shit returned:", result)
            return ""


    def get_local_source_detect(self):
        resp = self.send("LSD,1?")
        resp = resp.split(',', 2)
        return resp[2]
    def get_output_count(self):
        return len(self.get_local_source_detect())

    def get_input_detect(self):
        resp = self.send("ASD,1?")
        resp = resp.split(',', 2)
        return resp[2]
    def get_input_count(self):
        return len(self.get_input_detect())


    def refresh_output_data(self):
        try:
            for output in self.outputs:
                output.input = self.get_selected_input(output.id)
                output.volume = self.get_volume(output.id)
        except IndexError:
            print("Output refresh failed!")
    
    def refresh_input_data(self):
        try:
            detect = list(self.get_input_detect())
            if self.debug: print(detect)
            for input in self.inputs:
                input.active = bool(int(detect[input.id-1]))
        except IndexError:
            print("Output refresh failed!")

    # this fetches the input of a particular OUTPUT.
    # this does NOT get, e.g. input 3 -- it gets the
    # input connected to output 3, if any.
    def get_selected_input(self, output_id):
        result = self.send("SRC," + str(output_id).zfill(2) + "?")
        result = result.split(',')
        temp = int(result[2])
        if temp == 0:
                temp = None
        return temp

    def set_input(self, output_id, input_id):
        result = self.send("SRC," + str(output_id).zfill(2) + ',' + str(input_id if input_id != None else 0).zfill(2))
        if result[0:3] == "ACK":
            self.outputs[output_id-1].input = input_id
        else:
            print("didn't get ack. :( got:", result[0:3])
        
        try:
            self.set_volume(output_id, self.outputs[output_id-1].default_volume)
        except:
            print("Failed to set volume on output", output_id)

    def get_volume(self, output_id):
        result = self.send("VOL," + str(output_id).zfill(2) + "?")
        result = result.split(',')
        return int(result[2])

    def set_volume(self, output_id, volume):
        print("Setting", output_id, "to volume", volume)
        result = self.send("VOL," + str(output_id).zfill(2) + ',' + str(volume))
        print(result)
        return result

    def is_connected(self):
        return "SYSOFF" in self.send("SYSOFF?")
Example #57
0
class BLE112:
	
	def __init__(self, devpath=''):
		self.devpath = devpath
		self.hw_addr = ''
		self.baud = 115200
		self.serialdev = None
		self.isopen = False
		self.devgood = False
		self.txpower = 0
		
	def setMode(self, disc, connect):
		print('Setting BLE112 Mode...')
		# payload is [GAP discoverable mode, GAP connectable mode]
		self.createAndSendCmdPacket(CID_GAP, CMD_SETMODE, [disc, connect])
		
	def setAdvData(self, data):
		print('Setting Adv data...')
		if len(data) > 31:
			print('    > data is longer than 31 bytes, aborting!')
			return
			
		payload = [ADV_ADVDATA]
		payload.extend(data)
		self.createAndSendCmdPacket(CID_GAP, CMD_ADVDATA, payload)
		
	def constructAdvPacket(self, advTypes, payload):
		# length of advertisement types
		len_types = len(advTypes)
		# length of payload
		len_payload = len(payload)
		# total packet length
		len_total = 2 + len_types + len_payload
		# check to make sure length doesn't exceed 31
		if len_total > 31:
			print('  Error: advertisement packet exceeds 31 bytes')
			return None
		# construct packet
		packet = bytearray([len_total, len_types])
		packet.extend(advTypes)
		packet.extend([len_payload])
		packet.extend(payload)
		#print('adv payload = ' + ''.join('{:02x} '.format(x) for x in packet))
		
		return packet
		
		
	def setAdvRate(self, desired_rate_hz):
		print('Setting BLE112 Adv. Rate...')
		# make sure rate is in good range (20ms to 10s)
		if desired_rate_hz > 20:
			print('    > requested rate too high, setting to 20 Hz')
			desired_rate_hz = 20
		if desired_rate_hz < 0.10:
			print('    > requested rate too low, setting to 0.10 Hz')
			desired_rate_hz = 0.10
	
		# convert desired rate to byte-value (0x20 (20ms) to 0x4000 (10+s) in steps of 625us)
		desired_interval_ms = round((1e3*1.0/desired_rate_hz))
		desired_interval_ticks = round(desired_interval_ms/0.625)
		
		# rate is specified by desired +/- 30ms
		int_ticks_min = desired_interval_ticks-48
		int_ticks_max = desired_interval_ticks+48
		
		# create payload (bytes are little endian!)
		min_bytes = struct.pack('<H', int_ticks_min)
		max_bytes = struct.pack('<H', int_ticks_max) 
		
		payload = bytearray()
		payload.extend(min_bytes)
		payload.extend(max_bytes)
		payload.extend([ADV_CHANNELS_ALL])
		
		# payload is: [adv_interval_min, adv_interval_max, adv_channels]
		self.createAndSendCmdPacket(CID_GAP, CMD_ADVPARA, payload)
		
	def setTxPower(self, power):
		self.createAndSendCmdPacket(CID_HW, CMD_TXPOWER, [power])	
		self.txpower = power
	
	def setBeaconParams(self, UUID, major, minor):
		# construct adv data array (adv. types, custom adv. payload)
		payload = IBCN_PREFIX
		payload.extend(UUID)
		# make major and minor into 2 byte arrays
		payload.extend(struct.pack('!H', major))
		payload.extend(struct.pack('!H', minor))
		# determine calibrated transmit power
		payload.extend([ TXPOW_1M_ARRAY[self.txpower] ])
		
		advpkt = self.constructAdvPacket(IBCN_TYPES, payload)
		self.setAdvData(advpkt)

	def enableAdv(self):
		self.setMode(GAP_USER_DATA, GAP_NON_CONNECTABLE)
		
	def disableAdv(self):
		self.setMode(GAP_NON_DISCOVERABLE, GAP_NON_CONNECTABLE)

	def autoSetup(self):
		# what OS are we using?
		local_os = platform.system()
		if local_os == OSTYPE_LINUX:
			print('Auto-detecting BLE112 (Linux)...')
			devlist = os.listdir('/dev')
			ble_regex = '.*ttyUSB.*'
		elif local_os == OSTYPE_OSX:
			print('Auto-detecting BLE112 (OSX)...')
			devlist = os.listdir('/dev')
			ble_regex = '.*tty.usbserial.*'
		else:
			print('Error: unrecognized host OS')
			return
		candidates = []
		for dev in devlist:
			check = re.match(ble_regex, dev)
			if check is not None:
				candidates.append(dev)

		if len(candidates) is 0:
			print('    > no devices found, aborting.')
			return NOSUCCESS

		print('    > found ' + str(len(candidates)) + ' device(s)')
		self.devpath = '/dev/' + candidates[0]
		print('    > opening device: ' + self.devpath)
		# open device
		try:
			self.serialdev = Serial(self.devpath, baudrate=self.baud, timeout=30e-3)
			self.isopen = True
		except Error:
			print('   > Error: unable to open device')
			return NOSUCCESS
		
		# fire up device listener thread
		self.listener = threading.Thread(target=self.listen)
		self.listener.start()
		
		# check to make sure the BLE device is functioning ok
		print('    > checking BLE health')
		self.probeDevHealth()
		if self.devgood is False:
			print('   > BLE Device has not issued "OK" signal, aborting.')
			return NOSUCCESS
		print('       BLE device is "OK"')
		
		print('    > determining device MAC')
		
		# probe device mac
		self.probeDevAddr()
		print('       Device MAC: ' + ''.join('{:02x} '.format(x) for x in self.hw_addr))
		
		# set starting TX Power
		self.setTxPower(TXPOW_HIGH)
		print('    > setting starting TX Power to HIGH...')
		
		# configure the LED pins
		self.configureLeds()

		# success!
		return SUCCESS

	def close(self):
		self.serialdev.close()
		
	def configureLeds(self):
		# set IO direction to output (port 1, pins 0 and 1)
		self.createAndSendCmdPacket(CID_HW, CMD_IODIR, [LED_PORT, (1<<LED_PIN_GREEN)+(1<<LED_PIN_RED)])

	def setGreenLed(self, val):
		self.createAndSendCmdPacket(CID_HW, CMD_IOWRITE, [LED_PORT, (1<<LED_PIN_GREEN), (val<<LED_PIN_GREEN)])

	def setRedLed(self, val):
		self.createAndSendCmdPacket(CID_HW, CMD_IOWRITE, [LED_PORT, (1<<LED_PIN_RED), (val<<LED_PIN_RED)])
		
	def probeDevHealth(self):
		pkt = self.createAndSendCmdPacket(CID_SYSTEM, CMD_HELLO, None)

	def probeDevAddr(self):
		self.createAndSendCmdPacket(CID_SYSTEM, CMD_GETADDR, None)

	def createCmdPacket(self, classID, cmdID, payload):
		# message type (0 = cmd/resp)
		MT = 0
		# technology Type (0 = BTSmart)
		TT = 0
		# Payload length
		if payload is None:
			PLL = 0
		else:
			PLL = len(payload)
		# PLL High (3 bits)
		LH = (PLL>>8)&0xFF
		# PLL Low (8 bits)
		LL = PLL&0xFF
		# Class ID
		CID = classID
		# Command ID
		CMD = cmdID
		# Payload
		PL = payload

		# -- create header array
		header = [(MT<<7)+(TT<<3)+(LH), LL, CID, CMD]
		# -- packet array
		if PL is not None:
			header.extend(PL)
		packet = bytes(header)
		
		return packet

	def unpackPacket(self, packet):
		# message type
		MT = (packet[0]>>7)&0x01
		# Command class ID
		CID = packet[2]
		# Command ID
		CMD = packet[3]
		# Payload
		if len(packet) > 4:
			PL = packet[4:]
		else:
			PL = None
		return [MT, CID, CMD, PL]

	def sendPacket(self, packet):
		if self.isopen is not True:
			return
		self.serialdev.write(packet)
		
	def createAndSendCmdPacket(self, classID, cmdID, payload):
		pkt = self.createCmdPacket(classID, cmdID, payload)
		self.sendPacket(pkt)
		print('          >> SENDING: ' + ''.join('{:02x} '.format(x) for x in pkt))
		time.sleep(CMD_WAIT_DEFAULT)
		
	def handleIncomingPacket(self, raw):
		[MT, CID, CMD, PL] = self.unpackPacket(raw)
		PL_str = 'None'
		if PL is not None:
			PL_str = ''.join('{:02x} '.format(x) for x in PL)
		print('          << RECEIVED: MT = %d, CID = %d, CMD = %d, PL = %s' % (MT, CID, CMD, PL_str))
			
		
		# handle address probe responses
		if CID is CID_SYSTEM and CMD is CMD_GETADDR:
			self.hw_addr = PL
			return
			
		# handle health probe responses
		if CID is CID_SYSTEM and CMD is CMD_HELLO:
			self.devgood = True
			return
			
		# handle parsing errors
		if MT is TYPE_EVENT and CID is CID_SYSTEM and CMD is EVT_PROTOERR:
			print('     ! BLE issued protocol error!')
			
		# unhandled packets get here
		#print(' (ignoring incoming packet from BLE)')
			

	# to be threaded
	def listen(self):
		while True:
			# is there any serial data waiting?
			if self.serialdev.inWaiting() > 0:
				rawbytes = self.serialdev.read(1024)
				# check length to ensure packet is not malformed
				if len(rawbytes) < 4:
					self.serialdev.flush()
					continue
				PL_len_high = rawbytes[0]&0x07
				PL_len_low = rawbytes[1]
				PL_len = int(PL_len_high<<7) + int(PL_len_low)
				if len(rawbytes) is not 4 + PL_len:
					self.serialdev.flush()
					continue
				# hand off the packet
				self.handleIncomingPacket(rawbytes)
class DfuTransportSerial():

    DEFAULT_BAUD_RATE = 57600
    DEFAULT_FLOW_CONTROL = False
    DEFAULT_SERIAL_PORT_TIMEOUT = 1.0  # Timeout time on serial port read
    ACK_PACKET_TIMEOUT = 1.0  # Timeout time for for ACK packet received before reporting timeout through event system
    SEND_INIT_PACKET_WAIT_TIME = 1.0  # Time to wait before communicating with bootloader after init packet is sent
    SEND_START_DFU_WAIT_TIME = 2.0  # Time to wait before communicating with bootloader after start DFU packet is sent			## was 10 sec
    DFU_PACKET_MAX_SIZE = 512  # The DFU packet max size

    def __init__(self, com_port, baud_rate=DEFAULT_BAUD_RATE, flow_control=DEFAULT_FLOW_CONTROL, timeout=DEFAULT_SERIAL_PORT_TIMEOUT):
        self.com_port = com_port
        self.baud_rate = baud_rate
        self.flow_control = 1 if flow_control else 0
        self.timeout = timeout
        self.serial_port = None
        """:type: serial.Serial """

    def open(self):
        
        self.serial_port = Serial(port=self.com_port, baudrate=self.baud_rate, rtscts=self.flow_control, timeout=self.timeout)
	self.serial_port.flushInput()
	self.serial_port.flushOutput()
	self.serial_port.flush()

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

    def is_open(self):
        
        if self.serial_port is None:
            return False

        return self.serial_port.isOpen()

    def send_validate_firmware(self):
        super(DfuTransportSerial, self).send_validate_firmware()
        return True

    def send_init_packet(self,firmware):
#        super(DfuTransportSerial, self).send_init_packet(init_packet)

	init_packet = 'ffffffffffffffff0100feff'
	init_packet += binascii.hexlify(struct.pack('<H', crc16.calc_crc16(firmware, crc=0xffff)))
	init_packet = binascii.unhexlify(init_packet)
	
        frame = int32_to_bytes(DFU_INIT_PACKET)
        frame += init_packet
        frame += int16_to_bytes(0x0000)  # Padding required

        packet = HciPacket(frame)
        self.send_packet(packet)
        time.sleep(DfuTransportSerial.SEND_INIT_PACKET_WAIT_TIME)

    def send_start_dfu(self, mode, softdevice_size=None, bootloader_size=None, app_size=None):
  #      super(DfuTransportSerial, self).send_start_dfu(mode, softdevice_size, bootloader_size, app_size)

        frame = int32_to_bytes(DFU_START_PACKET)
        frame += int32_to_bytes(mode)
        frame += self.create_image_size_packet(softdevice_size, bootloader_size, app_size)

        packet = HciPacket(frame)
        self.send_packet(packet)
        time.sleep(DfuTransportSerial.SEND_START_DFU_WAIT_TIME)

    def send_activate_firmware(self):
        super(DfuTransportSerial, self).send_activate_firmware()

    def send_firmware(self, firmware):
#        super(DfuTransportSerial, self).send_firmware(firmware)

        def progress_percentage(part, whole):
            return int(100 * float(part)/float(whole))

        frames = []
#        self._send_event(DfuEvent.PROGRESS_EVENT, progress=0, done=False, log_message="")

        for i in range(0, len(firmware), DfuTransportSerial.DFU_PACKET_MAX_SIZE):
            data_packet = HciPacket(int32_to_bytes(DFU_DATA_PACKET) + firmware[i:i + DfuTransportSerial.DFU_PACKET_MAX_SIZE])
            frames.append(data_packet)

        frames_count = len(frames)

        # Send firmware packets
        for count, pkt in enumerate(frames):
            self.send_packet(pkt)
#            self._send_event(DfuEvent.PROGRESS_EVENT,
#                             log_message="",
#                             progress=progress_percentage(count, frames_count),
#                             done=False)

        # Send data stop packet
        frame = int32_to_bytes(DFU_STOP_DATA_PACKET)
        packet = HciPacket(frame)
        self.send_packet(packet)

#        self._send_event(DfuEvent.PROGRESS_EVENT, progress=100, done=False, log_message="")

    def send_packet(self, pkt):
        attempts = 0
        last_ack = None
        packet_sent = False

        logger.debug("PC -> target: {0}".format(pkt))

	print format(binascii.hexlify(pkt.data))	

	print "Sequence number HCI: " + str(HciPacket.sequence_number)

        while not packet_sent:
            self.serial_port.write(pkt.data)
            attempts += 1
	    time.sleep(0.2)
            ack = self.get_ack_nr()
	    
	   # print "attempts: " + str(attempts)

            if last_ack is None:
		print str(ack)
                break

            if ack == (last_ack + 1) % 8:
                last_ack = ack
                packet_sent = True

                if attempts > 3:
                    raise Exception("Three failed tx attempts encountered on packet {0}".format(pkt.sequence_number))

    def get_ack_nr(self):
        def is_timeout(start_time, timeout_sec):
            return not (datetime.now() - start_time <= timedelta(0, timeout_sec))

        uart_buffer = ''
        start = datetime.now()

        while uart_buffer.count('\xC0') < 2:
            # Disregard first of the two C0
            temp = self.serial_port.read(6)

	    if temp:
                uart_buffer += temp
		print format(binascii.hexlify(uart_buffer))

            if is_timeout(start, DfuTransportSerial.ACK_PACKET_TIMEOUT):
                # reset HciPacket numbering back to 0
                HciPacket.sequence_number = 0
                print "Timed out waiting for acknowledgement from device."
		

                # quit loop
                break

                # read until you get a new C0
                # RESUME_WORK

        if len(uart_buffer) < 2:
            	print "No data received on serial port. Not able to proceed."
		return

        logger.debug("PC <- target: {0}".format(binascii.hexlify(uart_buffer)))
        data = self.decode_esc_chars(uart_buffer)

        # Remove 0xC0 at start and beginning
        data = data[1:-1]

        # Extract ACK number from header
        return (data[0] >> 3) & 0x07

    @staticmethod
    def decode_esc_chars(data):
        """Replace 0xDBDC with 0xCO and 0xDBDD with 0xDB"""
        result = []

        data = bytearray(data)

        while len(data):
            char = data.pop(0)

            if char == 0xDB:
                char2 = data.pop(0)

                if char2 == 0xDC:
                    result.append(0xC0)
                elif char2 == 0xDD:
                    result.append(0xDB)
                else:
                    raise Exception('Char 0xDB NOT followed by 0xDC or 0xDD')
            else:
                result.append(char)

        return result

    @staticmethod
    def create_image_size_packet(softdevice_size=0, bootloader_size=0, app_size=0):
        """
        Creates an image size packet necessary for sending start dfu.

        @param softdevice_size: Size of SoftDevice firmware
        @type softdevice_size: int
        @param bootloader_size: Size of bootloader firmware
        @type softdevice_size: int
        @param app_size: Size of application firmware
        :return: The image size packet
        :rtype: str
        """
        softdevice_size_packet = int32_to_bytes(softdevice_size)
        bootloader_size_packet = int32_to_bytes(bootloader_size)
        app_size_packet = int32_to_bytes(app_size)
        image_size_packet = softdevice_size_packet + bootloader_size_packet + app_size_packet
        return image_size_packet
Example #59
0
class SerialDaemon():
    """A wrapper class for Serial and DaemonContext with inet socket support.

    Creates a DaemonContext object and a Serial object using the passed
    arguments. Some arguments do not take effect after the daemon is started
    and hence can be altered anytime after initialization until it is started
    by calling <daemon>.start()

    Communication with the daemon is done on a port number specified during
    initialization (or anytime before start), defaulting to 57001. Data is
    decoded using the user specified encoding (default is UTF-8) and must be
    either exactly 'device', in which case the daemon will reply with the full
    path to the device file it is communicating with (serial_context.port),
    or it must be in the following format:
        <0-F><0-F0-F...0-F><data to be sent to device>
    where the first byte of data always signifies how many (base 16) bytes
    following it give the the number (base 16) of bytes that are to be read
    from device after the data is sent to it. 0 bytes are read if data[0] is
    0 or is not a valid hex number. <data[0] number of bytes> + 1 are always
    discarded from the beginning of data. For example:
        22F8921 sends 8921 to device and reads 2F (47) bytes of data
        X78192 sends 78192 to device and dos not read a reply
        3A2G9130 sends 9130 to device BUT does not read a reply since A2G is
            not a valid hex number. Note that these 3 bytes are still discarded

    This class does not inherit from either DaemonContext or Serial.
    The only export method is start() used to run the daemon.

    Accepted options for the constructor:

    name
        :Default: ``None``

        The name of the daemon, used for syslog and the default
        name of the pidfile and configuration files. Changes to this value
        after the daemon has started will only be reflected in syslog.

    config_file
        :Default: ``'/etc/<name>.conf'``

        Configuration file used to set some of the hereby listed parameters.
        All but name, daemon_context and serial_context are supported.
        Reloading of the configuration without restarting is done by sending
        SIGHUP to the daemon but please note that changes to pidfile_path,
        socket_path and log_file require restart to take effect.
        The format is as follows:
            <option_name> = <option value>
        Option names are case-INsensitive and ``_`` may be replaced by ``-``.
        Spaces around ``=`` are optional and have no effect.
        Option values may optionally be enclosed in either single or double
        quotes. # and any text following it on the line are ignored.

    log_file
        :Default: ``/tmp/<name>.log``

        Log file used to log exceptions during daemon run.

    pidfile_path
        :Default: ``'/var/run/<name>.pid'``

        Path to the pidfile. A pidfile lock is created and passed to
        DaemonContext. Alternatively, you may pass a pid lockfile directly by
        setting <daemon>.daemon_context.pidfile to the lockfile after
        initialization but before start. Changing either of them after the
        daemon is started requires a restart.

    socket_path
        :Default: ``'/var/run/<name>.socket'``

        Path for the unix daemon socket which the daemon will be listening on.
        Changing this after the daemon is started requires a restart. Also see
        documentation for serial.py.

    data_length
        :Default: ``1024``

        Number of bytes to be read from the socket. This MUST be at least the
        number of bytes that have been sent, otherwise the remainder is read
        afterwards and is confused for a new packet. See above for details on
        the data format.

    data_encoding
        :Default: ``'utf-8'``

        Valid encoding (accepted by the str.decode() and bytes() methods) for
        the data read from and sent to the socket.

    reply_length_strict
        :Default: ``False``

        If True daemon will not send data read from device unless the length
        matches the expected reply length given as part of the data sent over
        the socket. See above for details on the data format.

    daemon_context
        :Default: ``None``

        If this is not None, it must be a DaemonContext object and is used
        instead of creating a new one. All options relating to DaemoonContext
        are then ignored.

    serial_context
        :Default: ``None``

        If this is not None, it must be a Serial object and is used instead of
        creating a new one. All options relating to Serial are then ignored.

    In addition to the above arguments, SerialDaemon accepts all arguments
    valid for DaemonContext and Serial and uses them to create the
    corresponding objects (unless daemon_context or serial_context are given)
    """
    
    def __init__(
            self,
            name = 'seriald',
            config_file = 0,
            log_file = None,
            pidfile_path = 0,
            socket_path = 0,
            reply_length_strict = False,
            data_length = 1024,
            data_encoding = 'utf-8',
            daemon_context = None,
            serial_context = None,
            **kwargs
    ):

        self.name = name
        self.config_file = config_file
        if self.config_file == 0:
            self.config_file = '/etc/{name}.conf'.format(name = self.name)
            
        self.log_file = log_file
        # log file will be used even if user specified None
        if self.log_file is None:
            self.log_file = os.path.join(
                tempfile.gettempdir(), '{name}.log'.format(
                    name = self.name))
            
        self.pidfile_path = pidfile_path
        if self.pidfile_path == 0:
            self.pidfile_path = '/var/run/{name}.pid'.format(name = self.name)

        self.socket_path = socket_path
        if self.socket_path == 0:
            self.socket_path = '/var/run/{name}.socket'.format(name = self.name)
            
        self.reply_length_strict = reply_length_strict
        self.data_length = data_length
        self.data_encoding = data_encoding
        
        self.daemon_context = daemon_context
        if self.daemon_context is None:
            self.daemon_context = DaemonContext(
                signal_map = {
                    signal.SIGHUP: self.__accept_signal,
                    signal.SIGINT: self.__accept_signal,
                    signal.SIGQUIT: self.__accept_signal,
                    signal.SIGTERM: self.__accept_signal,
                }
            )
            for attr in filter(lambda s: not s.startswith('_'),
                               dir(self.daemon_context)):
                if kwargs.get(attr) is not None:
                    setattr(self.daemon_context, attr, kwargs.get(attr))
            
        self.serial_context = serial_context
        if self.serial_context is None:
            self.serial_context = Serial()
            for attr in filter(lambda s: not s.startswith('_'),
                               dir(self.serial_context)):
                if kwargs.get(attr) is not None:
                    setattr(self.serial_context, attr, kwargs.get(attr))
                    
    def __run(self):

        with open(self.log_file, 'a') as log_file:
            try:
                soc = None
                # flush doesn't work in daemon mode for ttyS?
                # close and reopen instead
                device = self.serial_context.port
                is_ttyS = True
                try:
                    # is it a number? Serial defaults to /dev/ttyS? if so
                    device += 0
                except TypeError:
                    # not a number, assume string
                    try:
                        if not device.startswith('/dev/ttyS'):
                            raise AttributeError
                    except AttributeError:
                        # not a string or not a ttyS? device
                        # assume flushing works
                        is_ttyS = False
                else:
                    device = '/dev/ttyS{num}'.format(num = device)
                                
                while True:
                    if not soc or soc.fileno() < 0:
                        logsyslog(LOG_INFO, 'Waiting for connection')
                        soc, soc_addr = self.socket.accept()
                        logsyslog(LOG_INFO, ('Connected to {addr}').format(
                            addr = soc_addr))

                    data = soc.recv(self.data_length).decode(
                        self.data_encoding)
                    if data == '':
                        logsyslog(LOG_INFO, 'Closing connection')
                        soc.close()
                        continue
                    elif data == 'device':
                        logsyslog(LOG_INFO, 'Device path requested')
                        try:
                            soc.sendall(device.encode(self.data_encoding))
                        except ConnectionResetError:
                            soc.close()
                        continue

                    logsyslog(LOG_INFO, 'Read from socket: {data}'.format(
                        data = data))

                    reply_length_byte_length = 0
                    try:
                        reply_length_byte_length = int(data[0], 16)
                        reply_length = int(
                            data[1 : reply_length_byte_length + 1], 16)
                    except ValueError:
                        reply_length = 0
                    data = data[reply_length_byte_length + 1:]

                    if not self.serial_context.isOpen():
                        # first time in the loop
                        logsyslog(LOG_INFO, 'Opening serial port')
                        self.serial_context.open()
                        
                    logsyslog(LOG_INFO, 'Sending {data}'.format(
                        data = data))
                    # discard any input or output
                    self.serial_context.flushOutput()
                    self.serial_context.flushInput()
                    self.serial_context.write(data.encode(self.data_encoding))
                    
                    if is_ttyS:
                        self.serial_context.close()
                        self.serial_context.open()
                    else:
                        self.serial_context.flush()
                            
                    logsyslog(LOG_INFO, ('Will read {length} bytes').format(
                        length = reply_length))
                    
                    if reply_length > 0:
                        reply = self.serial_context.read(reply_length)
                        reply_decoded = reply.decode(self.data_encoding)
                        logsyslog(LOG_INFO, 'Received {data}'.format(
                            data = reply_decoded))
                        if len(reply_decoded) == reply_length \
                           or not self.reply_length_strict:
                            try:
                                soc.sendall(reply)
                            except ConnectionResetError:
                                soc.close()
                                continue

            except:
                traceback.print_exc(file = log_file)
                
        self.__stop()
                
    def __load_config(self):
        def reset_invalid_value(opt):
            logsyslog(LOG_ERR,
                      ('{conf}: Invalid value for ' +
                       '{option}').format(
                           conf = self.config_file,
                           option = opt))
            return getattr(self, opt)

        conf = _openfile(self.config_file, 'r')
        if conf is not None:
            with conf:
            
                regex_pat = regex.compile(r"""\s* (?|
                    (?P<option>
                      reply_length_strict |
                      data[-_]length |
                      data[-_]encoding |
                      log[-_]file |
                      pidfile[-_]path |
		      socket[-_]path
		    ) \s* (?: =\s* )?
		    (?|
                      " (?P<value> [^"]+ ) " |
		      ' (?P<value> [^']+ ) ' |
		        (?P<value> [^#\r\n]+ )
		    ) )
                    """, regex.X|regex.I)
                
                line_num = 0
                for line in conf:
                    line_num += 1
                    
                    if line.startswith('#'):
                        continue
                    
                    match = regex_pat.match(line.strip())
                    if match:
                        # translate the option name to the object's attribute
                        opt = match.group('option').lower().replace('-', '_')
                        
                        if opt.endswith(('file',
                                         'dir',
                                         'path',
                                         'encoding')):
                            # value is a string
                            val = match.group('value')
                        elif opt == 'reply_length_strict':
                            # value must be a boolean
                            if val.lower() not in ['0', '1', 'false', 'true']:
                                val = reset_invalid_value(opt)
                            elif val.lower() in ['0', 'false']:
                                val = False
                            else:
                                val = True
                        else:
                            # value must be numeric and positive
                            val = int(match.group('value'))
                            if val <= 0:
                                val = reset_invalid_value(opt)
                                
                        setattr(self, opt, val)
                        
                    else:
                        logsyslog(LOG_ERR, ('{conf}: Invalid syntax at line ' +
                                            '{line}').format(
                                                conf = self.config_file,
                                                line = line_num))
                        
            logsyslog(LOG_INFO, 'Loaded configuration from {conf}'.format(
                conf = self.config_file))

    def start(self):
        """
        Load config, daemonize, connect to serial port, listen on socket
        """
        opensyslog(ident = self.name, facility = LOG_DAEMON)
        
        self.__load_config()
        if self.pidfile_path is not None:
            self.daemon_context.pidfile = lockfile.FileLock(self.pidfile_path)
            
        if _pidfile_isbusy(self.daemon_context.pidfile):
            logsyslog(LOG_ERR, 'Already running (pidfile is locked)')
            closesyslog()
            return
        
        if _socket_isbusy(self.socket_path):
            logsyslog(LOG_ERR, 'Already running (socket is in use)')
            closesyslog()
            return
        
        self.daemon_context.open()
        with _openfile(self.daemon_context.pidfile.path, 'w',
                      fail = self.__stop) as file:
            file.write('{pid}'.format(pid = os.getpid()))
        # opening the serial port here doesn't work
        # open it in __run instead
        # self.serial_context.open()
        logsyslog(LOG_INFO, 'Started')

        self.socket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
        self.socket.bind(self.socket_path)
        self.socket.listen(1)
        logsyslog(LOG_INFO, ('Listening on socket {socket}').format(
            socket = self.socket_path))
        self.__run()
        
    def __stop(self):
        pid = _get_pid(self.daemon_context.pidfile.path)
        if pid is None:
            return

        logsyslog(LOG_INFO, 'Stopping')
        
        os.remove(self.socket.getsockname())
        os.remove(self.daemon_context.pidfile.path)
        
        self.socket.close()
        
        if self.serial_context.isOpen():
            self.serial_context.close()
        self.daemon_context.close()
        
        try:
            os.kill(pid, signal.SIGKILL)
        except OSError:
            logsyslog(LOG_ERR, 'Could not stop process id {pid}'.format(
                pid = pid))
        closesyslog()
        
    def __accept_signal(self, sig, frame):
        if sig == signal.SIGHUP:
            self.__load_config()
        else:
            logsyslog(LOG_INFO, 'Caught signal {sig}'.format(sig = sig))
            self.__stop()
Example #60
-1
class TagReader:
    def __init__(self, port):
        self.serial_port = Serial(port, baudrate=9600, timeout=0.01)
        self.serial_port.close()
        self.serial_port.open()
        self.serial_port.flush()  # Flush any old data
        self.should_do_checksum = True

    def getBufferSize(self):
        return self.serial_port.inWaiting()

    """
    RFID Tag is 16 characters: STX(02h) DATA (10 ASCII) CHECK SUM (2 ASCII) CR LF ETX(03h)
    1 char of junk, 10 of hexadecimal data, 2 of hexadecimal check sum, 3 of junk
    XOR-ing 5 1-byte hex values will give the 1-byte check sum - if requested
    """
    def readTag(self):
        #  run the while loop since it may read a tag twice.
        #  May not be necessary
        while (self.getBufferSize() >= 16):
            junk = self.serial_port.read(1)  # Junk byte 1
            tag  = self.serial_port.read(10) # tag bytes 10
            check_sum = self.serial_port.read(2) # check sum 2 bytes
            junk = self.serial_port.read(3)  # Last 3 bytes are junk

            if (self.should_do_checksum):
                self.doCheckSum(tag, check_sum)

        return int(tag, base=16)  # Convert the tag to an integer.

    def doCheckSum(self, tag, check_sum):
        try:
            checked_val = 0
            for i in range(0,5):
                checked_val = checked_val ^ int(tag [(2 * i) : (2 * (i + 1))], 16)

            if checked_val != int(check_sum, 16):
                print ("Tag reader checksum error. Tag was not read fully...")
        except ValueError:
            print ("Error reading the tag properly.")
            print ("Tag: " + tag)

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