#!/usr/bin/python
# -*- coding: utf-8 -*-

#########################################################################################################
 #    2017/10/19     Juan de Dios Yáñez Ávila www.onw4rds.com                                            
 #    interfaz_dispositivo.py     Python 3    Versión: 0.1.                                                           
 #                                                                                                       
 #    Este programa se ejecuta desde bash con el comando onwInventario. Posee el desarrollo de una 
 #    interfaz con Tkinter junto a todas sus funciones, incluido las alarmas con LED dentro de la 
 #    librería gpiozero                                                                                         
#########################################################################################################


import gpiozero as gp
led = gp.LED(23)


def checkfile(archivo):
	# FUNCION PARA DETERMINAR SI YA EXISTE UN ARCHIVO EMPRESAPASILLO.TXT.
	# Formato archivo carpeta/archivo.extension
	import os.path
	archivo = str(archivo)
    # os.path.exists(archivo) devuelve un True si existe el archivo en cuestión, y un False en otro caso.
	return os.path.exists(archivo)


def borrar(pasillo):
	import os
	pasillo = str(pasillo)
	name_doc = 'lecturas/'+pasillo+'.txt'
	fichero = open(name_doc, 'r')
	a = []
    # Todo el contenido del archivo a borrar se pasa a memoria volatil.
	for linea in fichero.readlines():
		a.append(linea)
	fichero.close()
	# Borramos el último registro
	a.pop(len(a)-1)
	# Borramos el archivo completo
	os.remove(name_doc)
    # Creamos un nuevo archivo con el nombre del que hemos borrado
	fichero2 = open(name_doc, 'w')
    # Volcamos todos los items registrados en el nuevo archivo (excepto el borrado)
	for i in range(len(a)):
		for j in range(len(a[i])):
			fichero2.write(a[i][j])
	fichero2.close()
    # Informamos de que el borrado se ha hecho correctamente.
	print("Borrado")


def leer(N):
    import serial
    if 'sensor' in locals():
        sensor.close()
    if 'sensor' in globals():
        sensor.close()
    sensor = serial.Serial('/dev/ttyACM0', timeout = 28)
    ## class Serial(port=None, baudrate=9600, bytesize=EIGHTBITS, parity=PARITY_NONE, stopbits=STOPBITS_ONE, timeout=None, xonxoff=False, rtscts=False, write_timeout=None, dsrdtr=False, inter_byte_timeout=None, exclusive=None, **kwargs)
	## /dev/ttyACM0 es el nombre del puerto en el sistema operativo del dispositivo, en Windows es COM3
    ## timeout es el tiempo en segundos de espera que tiene para leer el código
    # flushInput() no funciona bajo Python3, fue eliminado. Ahora es: reset_input_buffer()
    # Se usa para vaciar búfer de entrada, descartar todo su contenido de la lectuar anterior si la hubiese.
    # STJ: SisTema de Jeringuillas
    sensor.reset_input_buffer()
	# ¿? Esto parece que es un comando que se escribe en el puerto en caso de superar el timeout
    # ¿? O bien puede ser el puerto del propio sensor
    sensor.write('\x16T\r'.encode())
    # Guardamos en a la lectura del sensor que debe ser de una longitud N (longitud del codigo de barras)
    # ¿? Parece que la lectura es en tipo byte.
    a = sensor.read(N)
    # Mostramos por linea de comandos la lectura. Hay algo nuevo en Python3 y es que necesita encode() para llamar al puerto y devuelve además de la lectura entre '' el tipo.
    # En nuestro caso pone b'lectura' >N b de binario y lo devuelve. Esto genera problemas en el PHP de la web
    # Por lo que voy a crear antes de hacer el archivo un reprocesado de cada lectura para eliminar la información que no es capaz de procesar el PHP de la web.
    ## print(a)
    # En este momento la jeringa del puerto del sensor debe estar vacía, porque ya se ha transferido
    # el contenido a la variable a.
    # Si quedase algo de información, por poca que sea, estará a la espera de ser extraida, inWaiting()
    # Y por tanto se dará un error fatal
    # Esto se puede dar cuando el codigo leido es más largo del que esperamos ERROR FATAL
    # Si el código no llega a leerse es que es más corto de lo indicado y se declara una INCIDENCIA
    buf = sensor.inWaiting()
    if (buf != 0):
        a = 'error'
    sensor.close()

    # FILTRAR LECTURA
    if type(a) == bytes:
        a = str(a)
        proceso_a = a.split("'")
        a = proceso_a[1]
    else:
        a = "error lectura"
    print(a)

    return a


"""
	import serial
	
	sensor = serial.Serial('/dev/ttyACM0')
	
	sensor.flushInput()
	sensor.write("\x16T\r")
	a = sensor.read(N)
	a = str(a)
	
	sensor.close()
	return str(a)
	
	import random
	num = random.randrange(10000000,99999999)
	ultima = Label(ventana, text = num).place(x=160, y = 90)
	return str(num)
"""

# INCLUIDO EN go() FUNCIÓN crear_fichero()
#
 # def crear_fichero(nombre, opcion, texto):
 #	#funcion auxiliar creacion de fichero. El nombre tiene que escribirse con la extension.
 #	#en el nombre si la ubicacion es distinta le pongo la ubicacion
 #	opcion = str(opcion)
 #	nombre = str(nombre)
 #	if(opcion == 'inicio'):
 #		fichero = open(nombre, 'w')
 #		fichero.write(texto)
 #		fichero.close()
 #	else:
 #		if(checkfile(nombre)):
 #			fichero = open(nombre, 'a')
 #			fichero.write(texto)
 #			fichero.close()
 #		else:
 #			fichero = open(nombre, 'w')
 #			fichero.write(texto)
 #			fichero.close()
#

def envio(pasillo, empresa):
	import ftplib
	import os
	 
	# Datos FTP
	ftp_servidor = 'home662228864.1and1-data.host'
	ftp_usuario  = 'u87707226'
	ftp_clave    = 'airvant.1'
	ftp_raiz     = '/inventarios/lecturas' # Carpeta del servidor donde queremos subir el fichero
	 
	# Datos del fichero a subir
    # Ruta al fichero que vamos a subir con todos los items registrados
	fichero_origen = 'lecturas/'+str(empresa)+str(pasillo)+'.txt'
    # Nombre que tendra el fichero en el servidor
	fichero_destino = str(empresa)+str(pasillo)+'.txt' 
	 
	# Conectamos con el servidor
	try:
		s = ftplib.FTP(ftp_servidor, ftp_usuario, ftp_clave)
        ## class FTP(host='', user='', passwd='', acct='', timeout=_GLOBAL_DEFAULT_TIMEOUT, source_address=None)
		try:
            # ¿? Se abre el fichero de origen en binario, modo 'rb'
			f = open(fichero_origen, 'rb')
            # Especificamos el lugar donde se guardará el archivo que subimos desde el dispositivo
			s.cwd(ftp_raiz)
            # Guarda en el FTP el archivo leído en binario. Sin este comando no se guarda.
			s.storbinary('STOR ' + fichero_destino, f)
            ## def storbinary(cmd, fp, blocksize=8192, callback=None, rest=None)
			f.close()
			s.quit()
			print ("Enviado correctamente")
		except:
            		print("No se ha podido encontrar el fichero " + fichero_origen)
	except:
		print("No se ha podido conectar al servidor " + ftp_servidor)

# PARTE RELACIONADA CON EL DISEÑO Y FUNCIONES DE LA INTERFAZ
from tkinter import *

# SCRIPT PARA COMENZAR EL PASILLO
def go():
	import time as t
	# Tomamos los datos de la interfaz usuario
	empresa_ = empresa.get()
	pasillo = entrada_pasillo.get()

	num = int(numerodelecturas.get()) # es un numero entero siempre
	
	longitud = long_codigo.get()
	# Creamos la dirección donde se guardará en el dispositivo esta lectura.
    	# Podemos ver como se forma también el nombre del archivo que se subirá al ftp
	nombre = 'lecturas/'+str(empresa_)+str(pasillo)+'.txt'
	# Se muestra en linea de comandos la operación en curso
	
	print(empresa, pasillo, num, longitud)
	
	# Creamos un while que parte de 0 hasta el total de items a leer, esto marcará el fin del proceso
	aux = 0
	ultima_lectura = ''
	#num = int(num)

	while(aux<num):
		# Escribe en pantalla el número de la lectura
		print(aux)
		led.on()
        # Llamamos a la función leer para una longitud dada.
        # Nos devuelve el código leído con el sensor barcode-scanner
		lectura = leer(int(longitud))
		# La función leer envía un conjunto de bytes
		lectura = str(lectura)
		# Ya tenemos la lectura, puede ser un número o error fatal
		texto = lectura+'\n'
        # Procesamos la lectura:
        # Si la lectura no coincide con la anterior, no hay error y existe lectura
        # El caso de lectura != '' se refiere a que el sensor indica que hay lectura, pero no envia nada, ni hay nada en su jeringa.
		if (lectura != ultima_lectura and lectura != 'error' and lectura != ''):
            		aux = aux + 1
            		led.off()
            		ultima_lectura = lectura
            		opcion = 'final'
            		titular = 'Correcto' + lectura
            		opcion = str(opcion)
            		nombre = str(nombre)
            		# Cuando cargamos go() la opcion esta en 'final', luego lo primero que hace es un checkfile(nombre), que incluye al pasillo
            		# ¿? De momento la opcion == inicio no tiene utilidad, salvo para sobreescribir el archivo
            		if(opcion == 'inicio'):
                		fichero = open(nombre, 'w')
                		fichero.write(texto)
                		fichero.close()
            		else:
                		# Chequeamos si existe el archivo
                		if(checkfile(nombre)):
                    			# Si existe el archivo lo abrimos bajo add 'a' y se añadira algo al final del archivo
                    			fichero = open(nombre, 'a')
                    			# Añadimos el codigo de barras leído
                    			fichero.write(texto)
                    			fichero.close()
                		else:
                    			# En caso de no existir se crea automáticamente.
                    			fichero = open(nombre, 'w')
                    			# y se adiciona en la primera linea el primer registro
                    			fichero.write(texto)
                    			fichero.close()
            		t.sleep(1.2)
        	# En caso de que exista algún error, se indica con las luces un patrón de 3 encendidos
		if(lectura == 'error' or lectura == ''):
            		led.off()
            		t.sleep(0.4)
            		led.on()
            		t.sleep(0.4)
            		led.off()
            		t.sleep(0.4)
            		led.on()
            		t.sleep(0.4)
            		led.off()
            		t.sleep(0.4)
            		led.on()
            		t.sleep(0.4)
            		led.off()
            		# ¿? esto de momento no se que función tiene
            		titular = 'Repetida' + lectura
    	# Fin del while. Ya tenemos el archivo empresapasillo.txt con las lecturas en el dispositivo.
	
# SCRIPT PARA TERMINAR EL PASILLO		
def fin():
	pasillo = entrada_pasillo.get()
	empresa_ = empresa.get()
	envio(str(pasillo), str(empresa_))

# SCRIPT PARA BORRAR EL PASILLO
def borrar_():
        empresa_b = empresa.get()
        pasillo_b = entrada_pasillo.get()
        pasar = empresa_b+pasillo_b
        pasar = str(pasar)
        borrar(pasar)

# DISEÑO DE LA GPU DE LA INTERFAZ
ventana = Tk()
ventana.geometry("400x500")
ventana.title("Plataforma inventariado version Onw4rds 0.1.")

entrada_pasillo = StringVar()
long_codigo = StringVar()
numerodelecturas = StringVar()
empresa = StringVar()

titulo1 = Label(ventana, text = "APP para control del sensor", relief= 'groove').place(x = 10, y = 10)
# Pedimos la identificación del pasillo
form_pasillo = Label(ventana, text = "Pasillo").place(x=10, y = 50)
pasillo = Entry(ventana, textvariable=entrada_pasillo, width = 8).place(x=10, y = 90)
# Pedimos la identificacion del número de lecturas.
# Esto marcará cuando se tiene que detener el sensor de guardar datos.
form_numero = Label(ventana, text = "Numero de lecturas").place(x = 10, y = 130)
numero = Entry(ventana, textvariable=numerodelecturas, width = 8).place(x = 10, y = 170)
# Pedimos la longitud de los codigos a leer.
# Esto servirá para informar de cuando existe un error y cuando no.
form_longitud = Label(ventana , text = "Longitud del codigo").place(x = 10, y = 210)
longitud = Entry(ventana, textvariable=long_codigo, width = 8).place(x = 10, y = 250)
# Pedimos el nombre de la empresa.
# Junto a la información del pasillo nos servirá para dar nombre al archivo.
form_empresa = Label(ventana, text = "Empresa", width = 8).place(x = 10, y = 290)
empresa2 = Entry(ventana, textvariable=empresa, width = 8).place(x = 10, y = 330)
# Botones con los que interactua el operario.
boton = Button(ventana, text = "Empezar", command = go).place(x = 10, y = 390)
boton_fin = Button(ventana, text = "Fin pasillo", command = fin).place(x = 90, y = 390)
# ¿? Creo que solo se puede borrar ultima lectura si esta da un error.
boton_borrar = Button(ventana, text = "Borrar ultima lectura", command = borrar_).place(x = 50, y = 450)
#mainloop

ventana.mainloop()