Пример #1
0
	def detect_all(cls): # {{{
		resumeinfo = [(yield), None]
		for p in ports:
			if ports[p] is not None:
				continue
			c = websockets.call(resumeinfo, cls.detect, p)
			while c(): c.args = (yield websockets.WAIT)
Пример #2
0
	def upload(self, port, board): # {{{
		assert self.socket.data['role'] in ('benjamin', 'admin')
		assert ports[port] is None
		resumeinfo = [(yield), None]
		sudo, brd, protocol, baudrate, mcu = self._get_info(board)
		self.disable(port)
		data = ['']
		filename = fhs.read_data(os.path.join('firmware', brd + '.hex'), opened = False)
		command = sudo + (config['avrdude'], '-q', '-q', '-c', protocol) + baudrate + ('-p', mcu, '-P', port, '-U', 'flash:w:' + filename + ':i')
		log('Flashing firmware: ' + ' '.join(command))
		process = subprocess.Popen(command, stdin = subprocess.PIPE, stdout = subprocess.PIPE, stderr = subprocess.STDOUT, close_fds = True)
		def output(fd, cond):
			d = ''
			try:
				d = process.stdout.read()
			except:
				data[0] += '\nError writing %s firmware: ' % board + traceback.format_exc()
				log(repr(data[0]))
				resumeinfo[0](data[0])
				return False
			if d != '':
				self._broadcast(None, 'message', port, '\n'.join(data[0].split('\n')[-4:]))
				data[0] += d
				return True
			resumeinfo[0](data[0])
			return False
		fl = fcntl.fcntl(process.stdout.fileno(), fcntl.F_GETFL)
		fcntl.fcntl(process.stdout.fileno(), fcntl.F_SETFL, fl | os.O_NONBLOCK)
		GLib.io_add_watch(process.stdout, GLib.IO_IN | GLib.IO_PRI | GLib.IO_HUP, output)
		self._broadcast(None, 'blocked', port, 'uploading firmware for %s' % board)
		self._broadcast(None, 'message', port, '')
		d = (yield websockets.WAIT)
		try:
			process.kill()	# In case it wasn't dead yet.
		except OSError:
			pass
		process.communicate()	# Clean up.
		self._broadcast(None, 'blocked', port, None)
		self._broadcast(None, 'message', port, '')
		if autodetect:
			websockets.call(None, self.detect, port)()
		if d:
			yield ('firmware upload for %s: ' % board + d)
		else:
			yield ('firmware for %s successfully uploaded' % board)
Пример #3
0
	def detect(cls, port): # {{{
		resumeinfo = [(yield), None]
		log('detecting printer on %s' % port)
		if port not in ports or ports[port] != None:
			log('port is not in detectable state')
			return
		ports[port] = False
		c = websockets.call(resumeinfo, detect, port)
		while c(): c.args = (yield websockets.WAIT)
Пример #4
0
	def printer_input(self, fd, cond): # {{{
		line = self.process.stdout.readline()
		if line == '':
			log('%s died.' % self.name)
			self.process.communicate()	# Clean up the zombie.
			for t in range(3):
				for w in self.waiters[t]:
					self.waiters[t][w](False, 'Printer died')
			Connection._disable('admin', self.port)
			return False
		data = json.loads(line)
		#log('printer input:' + repr(data))
		if data[1] == 'broadcast':
			Connection._broadcast(data[2], data[3], self.port, *(data[4:]))
		elif data[1] == 'disconnect':
			# Don't remember a printer that hasn't sent its name yet.
			port = self.port
			ports[self.port] = None
			# If there already is an orphan with the same uuid, kill the old orphan.
			for o in [x for x in orphans if x[0] == self.uuid]:
				# This for loop always runs 0 or 1 times, never more.
				log('killing duplicate orphan')
				del orphans[x]
			orphans[self.run_id] = self
			Connection._broadcast(None, 'del_printer', port)
			if autodetect:
				websockets.call(None, Connection.detect, self.port)()
		elif data[1] == 'error':
			if data[0] is None:
				# Error on command without id.
				log('error on command without id: %s' % repr(data))
			else:
				self.waiters[0].pop(data[0])(False, data[2])
		elif data[1] == 'return':
			self.waiters[0].pop(data[0])(True, data[2])
		elif data[1] == 'movecb':
			self.waiters[1].pop(data[0])(True, data[2])
		elif data[1] == 'tempcb':
			self.waiters[2].pop(data[0])(True, data[2])
		else:
			raise AssertionError('invalid reply from printer process: %s' % repr(data))
		return True
Пример #5
0
	def add_port(cls, port): # {{{
		resumeinfo = [(yield), None]
		if port in ports:
			log('already existing port %s cannot be added' % port)
			return
		if re.match(config['blacklist'], port) or re.match(config['add-blacklist'], port):
			#log('skipping blacklisted port %s' % port)
			return
		ports[port] = None
		cls._broadcast(None, 'new_port', port);
		if autodetect:
			c = websockets.call(resumeinfo, cls.detect, port)
			while c(): c.args = (yield websockets.WAIT)
Пример #6
0
	if config['done']:
		cmd = config['done']
		cmd = cmd.replace('[[STATE]]', 'completed' if completed else 'aborted').replace('[[REASON]]', reason)
		log('running %s' % cmd)
		p = subprocess.Popen(cmd, stdout = subprocess.PIPE, shell = True, close_fds = True)
		def process_done(fd, cond):
			data = p.stdout.read()
			if data:
				return True
			log('Flashing done; return: %s' % repr(p.wait()))
			return False
		GLib.io_add_watch(p.stdout.fileno(), GLib.IO_IN, process_done)
# }}}

if config['local'] != '':
	websockets.call(None, Connection.add_port, '-')()

# Assume a GNU/Linux system; if you have something else, you need to come up with a way to iterate over all your serial ports and implement it here.  Patches welcome, especially if they are platform-independent.
try:
	# Try Linux sysfs.
	for tty in os.listdir('/sys/class/tty'):
		websockets.call(None, Connection.add_port, '/dev/' + tty)()
except:
	# Try more generic approach.  Don't use this by default, because it doesn't detect all ports on GNU/Linux.
	try:
		import serial.tools.list_ports
		for tty in serial.tools.list_ports.comports():
			websockets.call(None, Connection.add_port, tty[0])()
	except:
		traceback.print_exc()
		log('Not probing serial ports, because an error occurred: %s' % sys.exc_info()[1])