myAppSerial

Bene siamo arrivati alla nostra prima applicazione grafica.

Partiamo copiando la nostra prova myTry01 del modulo l01_startGtk

Modifichiamo la configurazione in conf=0x0010 perchè non ci servono i box:

  • application
  • global
  • main
  • menu
  • status

myTry01

Aggiungiamo l’ istanza del nostro device seriale con relativa configurazione.

Questa potete copiarla da myTry01 del modulo myProtocol.

#-----------------------------------------------------------------------------
# myTry
#-----------------------------------------------------------------------------
def myTry01(deb=1):
	""" + window (self)                                                   
	"conf                                       .------------------------.
	"0001 - aBox            (h application)     | application            |
	"0002   - gBox            (h global)        |   .--------------------.
	"0004   - mBox            (v main)          |   | g | m | menu       |
	"0008     - uBox            (h menu)        |   | l | a .------------.
	"0010     - bBox            (v body)        |   | o | i | body       |
	"0020     - sBox            (h status)      |   | b | n |            |
	"                                           |   | a |   .------------.
	"                                           |   | l |   | status     |
	"                                           .---.---.----------------.
	""" 
	# istanza l'applicazione base (no application, global, main, menu, status)
	self = MyApp(width=400, height=400, title="myApp", 
					center=True, color="#bbb", conf=0x0010, show=0)


	# inizializzazione in base al S.O.
	if sys.platform == 'win32':
		# Windows (numerazione parte da 1)
		por = "COM"
		par = ['1','115200','8','N','1']
	else:
		# Unix  (numerazione parte da 0)	
		#por = "/dev/ttyS"
		#por = "/dev/ttymxc"
		por = "/dev/ttyUSB"
		par = ['0','115200','8','N','1']

	#  istanza di un seriale
	dev = MySerial(por=por, par=par, ope=1, deb=deb)

	if dev.ser:
	# if 1:
		print "device Ok"
		self.dev = MyProtocol(ser=dev, sta='', sto=['\r','\n'], hex=0, cal=None)
		# contatore di errori
		self.dev.couErr = 0
		# istanza il Parser
		self.dev.prs = MyParser()
		# attivo il parser
		self.dev.cal = self.dev.prs.parser

		# re-imposta il titolo dell'applicazione
		self.set_title(self.title + " %s %s %s" %(self.dev.ser.por, self.dev.ser.par[1:], myRev) )

		return self
	else:
		print "device Ko"
		sys.exit()

myTry01 la useremo come base di partenza per avere la struttura base della nostra applicazioen Gtk.

Per finire notare che abbiamo cambiato il titolo della nostra applicazione aggiungendo la revisione e la configurazione come promemoria.

		# re-imposta il titolo dell'applicazione
		self.set_title(self.title + " %s %s %s" %(self.dev.ser.por, self.dev.ser.par[1:], myRev) )

myTry02

In myTry02 viene definita la nostra GUI personale.

def myTry02(self):
	"GUI (Graphics User Interface)"

	from my01Box import myFrame
	from my02TxtView import myTxtView
	from my02Entry import myEntFrame, myEntList
	from my02Label import myLabFrame
	from my03Button import myButton, myButFrame
	from my03ChkButton import myChkButton
#myTxtView
	#          0,   1,   2,   3,   4,    5,    6,       7 
	# fram,[labe,xBox,buff,text,cTag,clear,write,writeTag]
	fram,othe = myTxtView(name='logBuffer', colo="black",
							widt=400, heig=400, 
							font="courier 9", edit=False, 
							left=1, righ=1, bord=3,
							bFra=1, sFra=Gtk.SHADOW_ETCHED_OUT, tFra='v' )
	# insert object in apllication
	self.bBox.pack_start(fram, False, False, 1)
	
	# referenzio gli attributi
	self.cTag = othe[4]
	# referenzio i metodi
	self.clear = othe[5]
	self.write = othe[6] # *msg
	self.wriTg = othe[7] # str="", tag="blaWhi"

	# redefine self.wriTg in protol
	self.dev.wriTg = self.wriTg
	
	# redirect sul proprio buffer text
	sys.stdout = self

##############################################################################
# Device

	# self.start = time()

	self.debLog = 1
	self.bufDev = 0
	self.couRcv = 0
	self.couSnd = 0
	self.couFil = 0
	self.namFil = ""
	def devRx(self):
		# if self.chkEna.get_active():
		if 1:
			# ricevo dati
			try:
				# lettura dati
				data = self.dev.read()
				# if data:
				# 	# aggiorno bytes ricevuti
				# 	self.couRcv += len(data)
				# 	self.labRcv.set_text(" %d" %self.couRcv)

				# 	# print data,
				# 	self.write(data)
				# 	# clear data rx
				# 	self.dev.prs.data = None

			except Exception,err:
				if "DEV read error" in err:
					pass
				else:
					pass
					self.dev.couErr += 1
					print "err:", self.dev.couErr, err
		sleep(0.001)
		# rimane attivo
		return True

	# referenzio il metodo che inserisco nel loop di Idle
	self.rxDev = GObject.idle_add(devRx, self)

	def devTx(self):
		# invio dati
		try:
			# send parameters
			if self.bufDev:

				# print data_str
				self.dev.sendListCommands(self.bufDev, sto="", log=1)
				self.bufDev = []

				self.couSnd +=1
				self.labSnd.set_text(" %d" %self.couSnd)
			else:
				pass

		except:
			if self.debLog:
				print("MyDevice write Frame error")

		# visualizzo tempo trascorso
		# print "tim:%s" %(time() - self.start)

		sleep(0.001)
		# rimane attivo
		return True

	# referenzio il metodo che inserisco nel loop di Idle
	self.txDev = GObject.idle_add(devTx, self)

##############################################################################
#myFrame (Tx Commands)
	# fram,[labe,xBox]
	obje, othe = myFrame(name='Tx commands', obje=None, colo='black',
						bord=2, shad=Gtk.SHADOW_ETCHED_OUT,
						tBox='h', aBox=[False, False, 10])
	# referenzio l'oggetto
	self.boxCmd = othe[1]
	# change background color to Class
	chaBackColor(obj=obje, css="boxCmd", col="#a0a0a0")
	
	# insert object in application
	self.bBox.pack_start(obje, False, False, 1)

#myLabFrame (counter Tx data)
	#fram, [labe, lFrm, xBox]
	obje, othe = myLabFrame(name='0', 
							leng=len('0')+1, prea=' ', post='', 
							font='Arial 10', 
							colo='blue',
							nFra='Tx.data', cFra='black', bFra=1, sFra=Gtk.SHADOW_ETCHED_OUT, 
							tFra='h', aFra=[False, False, 1])
	# referenzio l'oggetto
	self.labSnd = othe[0]
	# insert object in application
	self.boxCmd.pack_start(obje, False, False, 1)

#myEntFrame (cmd Serial)
	# ridefinisco la callback        
	def on_activate(widg, *data):
		data_str = widg.get_text()
		# CR	
		if self.chkCR.get_active():
			data_str += '\r'
		# LF
		if self.chkLF.get_active():
			data_str += '\n'
		# convert to list
		data_str = [data_str,]

		# send data
		if data_str:
			# print data_str
			# self.dev.prot.sendListCommands(data_str, sto="", log=0)
			self.bufDev = data_str
			# printHex(data_str[0])

	#fram, [labe, xBoxcmdB, entr, call]        
	obje, othe = myEntFrame(name='', 
							numb=29,
							call=on_activate, data=[],
							nFra='cmd.Serial', bFra=1, sFra=Gtk.SHADOW_ETCHED_OUT, 
							tFra='h', aFra=[False, False, 1])
	# referenzio l'oggetto
	self.entCmdSerial = othe[2]
	# insert object in application
	self.boxCmd.pack_start(obje, False, False, 1)

#myChkButton (enable CR)
	# ridefinisco la callback        
	def on_clicked(widg, name, *data):
		pass
	# butt, call
	obje, othe = myChkButton(name='Ena', 
							valu=1, colo='black', 
							call= on_clicked, data=['-',])
	# referenzio l'oggetto
	self.chkCR = obje
	# fram,[labe,xBox]
	obj1, oth1 = myFrame(name='CR', obje=obje, colo='black',
						 bord=2, shad=Gtk.SHADOW_ETCHED_OUT,
						 tBox='h' )
	# insert object in application
	self.boxCmd.pack_start(obj1, False, False, 1)

#myChkButton (enable LF)
	# ridefinisco la callback        
	def on_clicked(widg, name, *data):
		pass
	# butt, call
	obje, othe = myChkButton(name='Ena', 
							valu=1, colo='black', 
							call= on_clicked, data=['-',])
	# referenzio l'oggetto
	self.chkLF = obje
	# fram,[labe,xBox]
	obj1, oth1 = myFrame(name='LF', obje=obje, colo='black',
						 bord=2, shad=Gtk.SHADOW_ETCHED_OUT,
						 tBox='h' )
	# insert object in application
	self.boxCmd.pack_start(obj1, False, False, 1)

#myChkButton (enable Debug)
	# ridefinisco la callback        
	def on_clicked(widg, name, *data):
		self.dev.ser.deb = widg.get_active()
	# butt, call
	obje, othe = myChkButton(name='Ena', 
							valu=0, colo='black', 
							call= on_clicked, data=['-',])
	# referenzio l'oggetto
	self.chkDeb = obje
	# fram,[labe,xBox]
	obj1, oth1 = myFrame(name='Deb', obje=obje, colo='black',
						 bord=2, shad=Gtk.SHADOW_ETCHED_OUT,
						 tBox='h' )
	# insert object in application
	self.boxCmd.pack_start(obj1, False, False, 1)

#myChkButton (enable RTS)
	# ridefinisco la callback        
	def on_clicked(widg, name, *data):
		if widg.get_active():
			self.dev.ser.ser.setRTS(1)
		else:
			self.dev.ser.ser.setRTS(0)
	# butt, call
	obje, othe = myChkButton(name='On', 
							valu=1, colo='black', 
							call= on_clicked, data=['-',])
	# referenzio l'oggetto
	self.chkRts = obje
	# fram,[labe,xBox]
	obj1, oth1 = myFrame(name='Rts', obje=obje, colo='black',
						 bord=2, shad=Gtk.SHADOW_ETCHED_OUT,
						 tBox='h' )
	# insert object in application
	self.boxCmd.pack_start(obj1, False, False, 1)

#myChkButton (enable DTR)
	# ridefinisco la callback        
	def on_clicked(widg, name, *data):
		if widg.get_active():
			self.dev.ser.ser.setDTR(1)
		else:
			self.dev.ser.ser.setDTR(0)
	# butt, call
	obje, othe = myChkButton(name='On', 
							valu=1, colo='black', 
							call= on_clicked, data=['-',])
	# referenzio l'oggetto
	self.chkDtr = obje
	# fram,[labe,xBox]
	obj1, oth1 = myFrame(name='Dtr', obje=obje, colo='black',
						 bord=2, shad=Gtk.SHADOW_ETCHED_OUT,
						 tBox='h' )
	# insert object in application
	self.boxCmd.pack_start(obj1, False, False, 1)

Logger

Il primo widget inserito è un myTxtView che lo useremo come logger della nostra applicazione. Qui vedremo i nostri Tx e Rx.

#myTxtView
	#          0,   1,   2,   3,   4,    5,    6,       7 
	# fram,[labe,xBox,buff,text,cTag,clear,write,writeTag]
	fram,othe = myTxtView(name='logBuffer', colo="black",
							widt=400, heig=400, 
							font="courier 9", edit=False, 
							left=1, righ=1, bord=3,
							bFra=1, sFra=Gtk.SHADOW_ETCHED_OUT, tFra='v' )
	# insert object in apllication
	self.bBox.pack_start(fram, False, False, 1)
	
	# referenzio gli attributi
	self.cTag = othe[4]
	# referenzio i metodi
	self.clear = othe[5]
	self.write = othe[6] # *msg
	self.wriTg = othe[7] # str="", tag="blaWhi"

	# redefine self.wriTg in protol
	self.dev.wriTg = self.wriTg
	
	# redirect sul proprio buffer text
	sys.stdout = self

Notate che abbiamo fatto un redirect per indirizzare lo stdout nel nostro logger. Questo avviene perchè abbiamo mantenuto la compatibilità delle chiamate.

Device

La seconda sezione viene enfatizzata da un commento per aumentare la leggibilità.

##############################################################################
# Device

	# self.start = time()

	self.debLog = 1
	self.bufDev = 0
	self.couRcv = 0
	self.couSnd = 0
	self.couFil = 0
	self.namFil = ""
	def devRx(self):
		# if self.chkEna.get_active():
		if 1:
			# ricevo dati
			try:
				# lettura dati
				data = self.dev.read()
				# if data:
				# 	# aggiorno bytes ricevuti
				# 	self.couRcv += len(data)
				# 	self.labRcv.set_text(" %d" %self.couRcv)

				# 	# print data,
				# 	self.write(data)
				# 	# clear data rx
				# 	self.dev.prs.data = None

			except Exception,err:
				if "DEV read error" in err:
					pass
				else:
					pass
					self.dev.couErr += 1
					print "err:", self.dev.couErr, err
		sleep(0.001)
		# rimane attivo
		return True

	# referenzio il metodo che inserisco nel loop di Idle
	self.rxDev = GObject.idle_add(devRx, self)

	def devTx(self):
		# invio dati
		try:
			# send parameters
			if self.bufDev:

				# print data_str
				self.dev.sendListCommands(self.bufDev, sto="", log=1)
				self.bufDev = []

				self.couSnd +=1
				self.labSnd.set_text(" %d" %self.couSnd)
			else:
				pass

		except:
			if self.debLog:
				print("MyDevice write Frame error")

		# visualizzo tempo trascorso
		# print "tim:%s" %(time() - self.start)

		sleep(0.001)
		# rimane attivo
		return True

	# referenzio il metodo che inserisco nel loop di Idle
	self.txDev = GObject.idle_add(devTx, self)

Qui abbiamo creato 2 metodi devRx e devTx per automatizzare l’aggiornamento. Li abbiamo aggiunti al loop di idle così verranno richiamati quando non vi sono altre priorità.

	# referenzio il metodo che inserisco nel loop di Idle
	self.rxDev = GObject.idle_add(devRx, self)
	# referenzio il metodo che inserisco nel loop di Idle
	self.txDev = GObject.idle_add(devTx, self)

Tx

Per finire abbiamo aggiunto una sezione per la gestione delle nostre trasmissioni.

##############################################################################
#myFrame (Tx Commands)
	# fram,[labe,xBox]
	obje, othe = myFrame(name='Tx commands', obje=None, colo='black',
						bord=2, shad=Gtk.SHADOW_ETCHED_OUT,
						tBox='h', aBox=[False, False, 10])
	# referenzio l'oggetto
	self.boxCmd = othe[1]
	# change background color to Class
	chaBackColor(obj=obje, css="boxCmd", col="#a0a0a0")
	
	# insert object in application
	self.bBox.pack_start(obje, False, False, 1)

#myLabFrame (counter Tx data)
	#fram, [labe, lFrm, xBox]
	obje, othe = myLabFrame(name='0', 
							leng=len('0')+1, prea=' ', post='', 
							font='Arial 10', 
							colo='blue',
							nFra='Tx.data', cFra='black', bFra=1, sFra=Gtk.SHADOW_ETCHED_OUT, 
							tFra='h', aFra=[False, False, 1])
	# referenzio l'oggetto
	self.labSnd = othe[0]
	# insert object in application
	self.boxCmd.pack_start(obje, False, False, 1)

#myEntFrame (cmd Serial)
	# ridefinisco la callback        
	def on_activate(widg, *data):
		data_str = widg.get_text()
		# CR	
		if self.chkCR.get_active():
			data_str += '\r'
		# LF
		if self.chkLF.get_active():
			data_str += '\n'
		# convert to list
		data_str = [data_str,]

		# send data
		if data_str:
			# print data_str
			# self.dev.prot.sendListCommands(data_str, sto="", log=0)
			self.bufDev = data_str
			# printHex(data_str[0])

	#fram, [labe, xBoxcmdB, entr, call]        
	obje, othe = myEntFrame(name='', 
							numb=29,
							call=on_activate, data=[],
							nFra='cmd.Serial', bFra=1, sFra=Gtk.SHADOW_ETCHED_OUT, 
							tFra='h', aFra=[False, False, 1])
	# referenzio l'oggetto
	self.entCmdSerial = othe[2]
	# insert object in application
	self.boxCmd.pack_start(obje, False, False, 1)

#myChkButton (enable CR)
	# ridefinisco la callback        
	def on_clicked(widg, name, *data):
		pass
	# butt, call
	obje, othe = myChkButton(name='Ena', 
							valu=1, colo='black', 
							call= on_clicked, data=['-',])
	# referenzio l'oggetto
	self.chkCR = obje
	# fram,[labe,xBox]
	obj1, oth1 = myFrame(name='CR', obje=obje, colo='black',
						 bord=2, shad=Gtk.SHADOW_ETCHED_OUT,
						 tBox='h' )
	# insert object in application
	self.boxCmd.pack_start(obj1, False, False, 1)

#myChkButton (enable LF)
	# ridefinisco la callback        
	def on_clicked(widg, name, *data):
		pass
	# butt, call
	obje, othe = myChkButton(name='Ena', 
							valu=1, colo='black', 
							call= on_clicked, data=['-',])
	# referenzio l'oggetto
	self.chkLF = obje
	# fram,[labe,xBox]
	obj1, oth1 = myFrame(name='LF', obje=obje, colo='black',
						 bord=2, shad=Gtk.SHADOW_ETCHED_OUT,
						 tBox='h' )
	# insert object in application
	self.boxCmd.pack_start(obj1, False, False, 1)

#myChkButton (enable Debug)
	# ridefinisco la callback        
	def on_clicked(widg, name, *data):
		self.dev.ser.deb = widg.get_active()
	# butt, call
	obje, othe = myChkButton(name='Ena', 
							valu=0, colo='black', 
							call= on_clicked, data=['-',])
	# referenzio l'oggetto
	self.chkDeb = obje
	# fram,[labe,xBox]
	obj1, oth1 = myFrame(name='Deb', obje=obje, colo='black',
						 bord=2, shad=Gtk.SHADOW_ETCHED_OUT,
						 tBox='h' )
	# insert object in application
	self.boxCmd.pack_start(obj1, False, False, 1)

#myChkButton (enable RTS)
	# ridefinisco la callback        
	def on_clicked(widg, name, *data):
		if widg.get_active():
			self.dev.ser.ser.setRTS(1)
		else:
			self.dev.ser.ser.setRTS(0)
	# butt, call
	obje, othe = myChkButton(name='On', 
							valu=1, colo='black', 
							call= on_clicked, data=['-',])
	# referenzio l'oggetto
	self.chkRts = obje
	# fram,[labe,xBox]
	obj1, oth1 = myFrame(name='Rts', obje=obje, colo='black',
						 bord=2, shad=Gtk.SHADOW_ETCHED_OUT,
						 tBox='h' )
	# insert object in application
	self.boxCmd.pack_start(obj1, False, False, 1)

#myChkButton (enable DTR)
	# ridefinisco la callback        
	def on_clicked(widg, name, *data):
		if widg.get_active():
			self.dev.ser.ser.setDTR(1)
		else:
			self.dev.ser.ser.setDTR(0)
	# butt, call
	obje, othe = myChkButton(name='On', 
							valu=1, colo='black', 
							call= on_clicked, data=['-',])
	# referenzio l'oggetto
	self.chkDtr = obje
	# fram,[labe,xBox]
	obj1, oth1 = myFrame(name='Dtr', obje=obje, colo='black',
						 bord=2, shad=Gtk.SHADOW_ETCHED_OUT,
						 tBox='h' )
	# insert object in application
	self.boxCmd.pack_start(obj1, False, False, 1)

Come potete vedere abbiamo inserito la possibilità di abilitare il fine linea LF e il ritorno carrello CR nelle nostre TX.

Per test ho inserito anche la possibilità di modificare lo stato dei segnali RTS e DTR

Per finire ho aggiunto un contatore delle nostre trasmissioni Tx.Data

main

Il nostro main richiama le 2 definizioni myTryXX e per dimostrazione aggiunge 2 trasmissioni.

		# istanza l'Applicazione (MyApp)
		# inizializza il device seriale
		self = myTry01(0)
		myTry02(self)

		# test: invio un comando in apertura
		self.dev.sendListCommands(["cmd_1",], sto="\r")

		# delay richiesta ritardata
		GLib.timeout_add(600, self.dev.sendListCommands, ["cmd_2",], sto="\r")

Se proviamo ad avviare il nostro script vedremo:

alternate text

myAppSerial in esecuzione.

Come potete notare appaiono le 3 trasmissione Tx/Rx.

Tx viene enfatizzata dal colore verde.

Rx viene enfatizzata dal prepost rx:

Le prime 2 trasmissioni sono automatiche da codice.

		# test: invio un comando in apertura
		self.dev.sendListCommands(["cmd_1",], sto="\r")

		# delay richiesta ritardata
		GLib.timeout_add(600, self.dev.sendListCommands, ["cmd_2",], sto="\r")

La terza l’ abbiamo fatta noi tramite il widget cmd.Serial.

Package

La struttura aggiornata del nostro package è la seguente:

myAppSerial/
  l00_start.py
  l01_startGtk.py
  my00init.py
  myAppSerial.py
  myLib/
    __init__.py
    myProtocol/
      __init__.py
      my00init.py
      myProtocol.py
      mySerial.py

Per scaricare la nuova versione 20150909.zip

Nota

Ricordatevi di fare il loop TX<->Rx sulla seriale e di impostare la porta giusta del vostro device su myTry01!

Saluti

Per oggi mi fermo qui.

Nel prossimo post aggiungeremo alla nostra GUI altre caratteristiche.

Ciao alla prossima. (stay tune!)