MEDINAKO 02

Instalar la IA de MediNako

Ahora procederemos a Instalar la IA de MediNako y para poder utilizar la IA de MediNako se requiere tener instalado Python 3.6 a 64bits ademas es necesario tener instalados TensorFlow y MySQL Connector. A continuación, se describen brevemente los pasos para instalar cada uno de estos componentes:

Instalar Python

Instalar Python: Python es un lenguaje de programación utilizado en el desarrollo de la IA de MediNako. Para instalar Python, se puede descargar el instalador correspondiente a la versión deseada desde el sitio web oficial de Python y seguir las instrucciones del instalador.

Además debemos actualizar las librerías de pip asi:

python -m pip install --upgrade pip

Instalar TensorFlow: TensorFlow es una plataforma de código abierto para el aprendizaje automático desarrollada por Google. Para instalar TensorFlow, se puede utilizar este comando.

pip install tensorflow

Instalar MySQL Connector: MySQL Connector es una biblioteca que permite la conexión de Python con la base de datos MySQL. Para instalar MySQL Connector, se puede utilizar este comando.

pip install mysql-connector

Instalar Flask: Flask es un popular framework web escrito en Python que permite a los desarrolladores construir aplicaciones web de manera rápida y sencilla que MediNako utiliza para mostrar la informacion de las mediciones tomadas. Su instalación es la siguiente:

pip install flask

Instalar librosa: Librosa es una biblioteca de Python utilizada para el análisis y procesamiento de señales de audio que MediNako usa para manipular las señales de audio recibidas y la instalamos de de la siguiente manera:

pip install librosa

Instalar Pandas: Pandas es una biblioteca de Python utilizada para el análisis y manipulación de datos que MediNako usa para manipular la informacion de la sondas de audio y permitir que la inteligencia artifical nos entregue las predicciones. Inhalaremos Pandas asi:

pip install pandas

Es importante tener en cuenta que la instalación de estos componentes puede variar según el sistema operativo que se esté utilizando. También es recomendable verificar que se están instalando las versiones más recientes y compatibles de cada componente para asegurar su correcto funcionamiento con la IA de MediNako.

Configuración de la base de datos

Creamos una base de datos en MariaDB llamada medinako asi:

CREATE DATABASE IF NOT EXISTS `medinako` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
USE `medinako`;

Creamos una tabla llamada mediciones así:

DROP TABLE IF EXISTS `mediciones`;
CREATE TABLE `mediciones` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `ip` varchar(100) NOT NULL,
  `idDispositivo` varchar(100) NOT NULL,
  `archivoAudio` varchar(200) NOT NULL,
  `estado` varchar(100) NOT NULL,
  `fechaCreacion` timestamp NOT NULL DEFAULT current_timestamp(),
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;

Ejecutar archivos de Python

Descargamos y descomprimimos los archivo desde github.com medinako asi:

python Entrenar.py
python LeeParaEntrenar.py
python Predecir.py

CargaModelo.py

from keras.models import load_model
import librosa
import numpy as np
import pandas as pd
#Extraemos los MFCC de cada archivo (osea convertimos el audio en una representacion grafica)
def extract_features(file_name):
    try:
        audio, sample_rate = librosa.load(file_name, res_type='kaiser_fast') 
        mfccs = librosa.feature.mfcc(y=audio, sr=sample_rate, n_mfcc=40)
        mfccsscaled = np.mean(mfccs.T,axis=0)
    except Exception as e:
        print("Error encountered while parsing file: ", file_name)
        return None 
    return mfccsscaled

def nivelDeLleno(rutaModelo,archivoAudio):
    model = load_model(rutaModelo)
    datosAudio = []
    #Extraemos el MFCC y los guardamos en rasgosArchivo
    rasgosArchivo = extract_features(archivoAudio)
    datosAudio.append([rasgosArchivo])
    datosAudioDataframe = pd.DataFrame(datosAudio, columns=['feature'])
    datosAudioNP = np.array(datosAudioDataframe.feature.tolist())

    prediccion = model.predict(datosAudioNP)
    listaEstados = np.array(['Vacio', 'Medio', 'Lleno'], dtype=np.object)
    numeroPrediccion = np.argmax(prediccion, axis = 1)
    exactitud=prediccion[0][numeroPrediccion[0]]
    return listaEstados[numeroPrediccion[0]],exactitud
    #print(listaEstados[numeroPrediccion[0]])
#estadoLleno=nivelDeLleno(rutaModelo='saved_models/weights.best.basic_mlp.hdf5',archivoAudio='audio/medio_05.wav')
#print(estadoLleno)

Conexion.py

host="localhost"
user="root"
passwd=""
database="medinako"

Entrenar.py

'''
ENTRENAR: CREA EL ARCHIVO hdf5 EXCLUSIVO DE ESTE RECIPIENTE
1.- LEEMOS LOS ARCHIVOS VACIO,MEDIO,LLENO (20 ARCHIVOS DE CADA UNO)
2.- EXTRAEMOS LOS MFCC DE CADA ARCHIVO
3.- GUARDAMOS LOS MFCC EN UNA MATRIZ
4.- GUARDAMOS LA MATRIZ EN UN ARCHIVO
5.- CARGAMOS EL MODELO
6.- ENTRENAMOS EL MODELO
7.- GUARDAMOS EL MODELO
'''
import os
from flask import Flask,request
from os import mkdir
import librosa
import numpy as np
import pandas as pd
import mysql.connector
import Conexion
mydb = mysql.connector.connect(
  host=Conexion.host,
  user=Conexion.user,
  passwd=Conexion.passwd,
  database=Conexion.database
)
cantidadAudios=20
#Extraemos los MFCC de cada archivo (osea convertimos el audio en una representacion grafica)
def extract_features(file_name):
    try:
        audio, sample_rate = librosa.load(file_name, res_type='kaiser_fast') 
        mfccs = librosa.feature.mfcc(y=audio, sr=sample_rate, n_mfcc=40)
        mfccsscaled = np.mean(mfccs.T,axis=0)
    except Exception as e:
        print("Error encountered while parsing file: ", file_name)
        return None 
    return mfccsscaled

app=Flask(__name__)
@app.route('/listo-entrenar')
def index():
    macAddress=request.args.get('mac')
    macAddressDir=macAddress.replace(':', '')
    #macAddressDir="8CAAB5D6F806"
    carpeta="audioRecibido/"+macAddressDir
    vacio=0
    medio=0
    lleno=0
    for estado in ["Vacio", "Medio", "Lleno"]:
        for i in range(0, cantidadAudios, 1):
            nombreArchivo=carpeta+"/"+estado+str(i)+".wav"
            if os.path.isfile(nombreArchivo):
                print("El archivo existe:",nombreArchivo)
                if estado=="Vacio":
                    vacio=vacio+1
                elif estado=="Medio":
                    medio=medio+1
                elif estado=="Lleno":
                    lleno=lleno+1
            else:
                print("El no archivo existe.",nombreArchivo)
    resultado="{\"data\":["
    resultado=resultado+"{\"Vacio\":\""+str(vacio)+"\",\"Medio\":\""+str(medio)+"\",\"Lleno\":\""+str(lleno)+"\"}"
    resultado=resultado+"]}"
    return resultado

@app.route('/entrenar')
def index2():
    features=[]
    macAddress=request.args.get('mac')
    macAddressDir=macAddress.replace(':', '')
    #Creamos el nombre del modelo
    archivoModeo='modelos/'+macAddressDir+'.hdf5'
    #Si el archivo del modelo existe lo borramos
    if os.path.exists(archivoModeo):
        os.remove(archivoModeo)
    carpeta="audioRecibido/"+macAddressDir+"/"
    
    
    class_label=1
    for estado in ["Vacio", "Medio", "Lleno"]:
        for i in range(0, cantidadAudios, 1):
            #file_name=carpeta+"/"+estado+str(i)+".wav"
            file_name = os.path.join(os.path.abspath(carpeta),estado+str(i)+".wav")
            if os.path.isfile(file_name):
                #print("file_name=",file_name,"----class_label=",class_label)
                #Extraemos el MFCC y los guardamos en data
                data = extract_features(file_name)
                #Insertamos en el arreglo el valor del MFCC junto a su etiqueta
                features.append([data, str(class_label)])
        class_label=class_label+1
    # convertimos el arreglo en un DataFrame de pandas y lo dividimos en 2 columnas ('feature','class_label')
    

    featuresdf = pd.DataFrame(features, columns=['feature','class_label'])
    
    print('finalizo la extraccion de ', len(featuresdf), ' archivos') 
    features = featuresdf.loc[1]
    print(list(features))

    ############################
    #Convertir los datos y etiquetas
    ############################
    '''
    Para transformar los datos categóricos a numéricos usaremos «LabelEncoder» y así conseguiremos que el modelo sea capaz de entenderlos.
    '''
    from sklearn.preprocessing import LabelEncoder
    from tensorflow.keras.utils import to_categorical

    # Convertimos los rasgos MFCC a arreglo numpy
    X = np.array(featuresdf.feature.tolist())
    # Convertimos las etiquetas a arreglo numpy
    y = np.array(featuresdf.class_label.tolist())

    # Codificamos las etiquetas con sklearn.preprocessing para que coloque un 1 y lo demas lo rellene con 0 por ejemplo
    le = LabelEncoder()
    yy = to_categorical(le.fit_transform(y))
    print("Mostramos el valor de \"X\" que son los rasgos en MFCC")
    print(X)
    print("Mostramos el valor de \"y\" que son las etiquetas osea classID que extrajimos de UrbanSound8K_csv")
    print(y)
    print("Mostramos el valor de \"yy\" que son las etiquetas (classID) pero transformadas con sklearn.preprocessing. Por ejemplo:")
    print("El classID=3 no dara una arreglo asi [0.0.0.1.0.0.0.0.0.0]")
    print("El classID=2 no dara una arreglo asi [0.0.1.0.0.0.0.0.0.0]")
    print("El classID=1 no dara una arreglo asi [0.1.0.0.0.0.0.0.0.0]")
    print(yy)


    ###########################################
    #Dividir los datos en entrenamiento y test
    ###########################################
    #Dividimos el conjunto de datos en dos bloques (80% y 20%) y de ellos sacamos valores de X y de Y
    from sklearn.model_selection import train_test_split 
    x_train, x_test, y_train, y_test = train_test_split(X, yy, test_size=0.2, random_state = 42)

    #####################
    # Construir el modelo
    #####################
    '''
    Construimos una red neuronal mediante un perceptrón multicapa (MLP) usando Keras y un backend de Tensorflow.
    Se plantea un modelo secuencial para que podamos construir el modelo capa por capa.
    Se plantea una arquitectura de modelo simple, compuesta por:
    - Capa de entrada con 40 nodos, ya que la función MFCC de extracción de características nos devuelve un conjunto de datos de 1×40
    - Capas ocultas de 256 nodos, estas capas tendrán una capa densa con una función de activación de tipo ReLu, (se ha demostrado que esta función de activación funciona bien en redes neuronales). 
        También destacar que aplicaremos un valor de Dropout del 50% en nuestras dos primeras capas. Esto excluirá al azar los nodos de cada ciclo de actualización, lo que a su vez da como resultado 
        una red que es capaz de responder mejor a la generalización y es menos probable que se produzca sobreajuste en los datos de entrenamiento.
    - Capa de salida de 10 nodos, que coinciden con el número de clasificaciones posibles. La activación es para nuestra capa de salida una función softmax. 
        Softmax hace que la salida sume 1, por lo que la salida puede interpretarse como probabilidades. El modelo hará su predicción según la opción que tenga la mayor probabilidad
    '''
    from tensorflow.keras.models import Sequential
    from tensorflow.keras.layers import Dense, Dropout, Activation, Flatten
    from tensorflow.keras.layers import Convolution2D, MaxPooling2D
    from tensorflow.keras.optimizers import Adam
    from sklearn import metrics 

    num_labels = yy.shape[1]
    
    # Declaramos un modelo
    model = Sequential()
    #Creamos una capa que recibira 40 nodos de entrada y 256 capas ocultas
    model.add(Dense(256, input_shape=(40,)))
    model.add(Activation('relu'))
    model.add(Dropout(0.5))

    model.add(Dense(256))
    model.add(Activation('relu'))
    model.add(Dropout(0.5))

    model.add(Dense(num_labels))
    model.add(Activation('softmax'))

    #####################
    #Compilar el modelo
    #####################
    '''
    Para compilar nuestro modelo, utilizaremos los siguientes tres parámetros:
    - Función de pérdida: utilizaremos categorical_crossentropy. Esta es la opción más común para la clasificación. Una puntuación más baja indica que el modelo está funcionando mejor.
    - Métricas: utilizaremos la métrica de accuracy que nos permitirá ver la precisión en los datos de validación cuando entrenemos el modelo.
    - Optimizador: aquí usaremos adam, que generalmente es un buen optimizador para muchos casos de uso.
    '''
    # Compilamos el modelo
    model.compile(loss='categorical_crossentropy', metrics=['accuracy'], optimizer='adam')
    # Imprimimos el resultado de la compilacion
    model.summary()
    # Calcular la precisión previa al entrenamiento
    score = model.evaluate(x_test, y_test, verbose=0)
    accuracy = 100*score[1]
    print("Precisión previa al entrenamiento: %.4f%%" % accuracy)


    #####################
    #Entrenar el modelo
    #####################
    '''
    Se empieza probando con un número de épocas bajo y se prueba hasta ver donde alcanza un valor asintótico en el que por más que subamos las épocas no conseguimos que el modelo mejore significativamente.
    Por otro lado, el tamaño del lote debe ser suficientemente bajo, ya que tener un tamaño de lote grande puede reducir la capacidad de generalización del modelo.
    '''
    from tensorflow.keras.callbacks import ModelCheckpoint 
    from datetime import datetime 

    num_epochs = 100
    num_batch_size = 32
    #Creamos un el archivo del modelo
    checkpointer = ModelCheckpoint(filepath=archivoModeo, verbose=0, save_best_only=True)
    start = datetime.now()
    model.fit(x_train, y_train, batch_size=num_batch_size, epochs=num_epochs,validation_data=(x_test, y_test), callbacks=[checkpointer], verbose=0)
    duration = datetime.now() - start
    print("Entrenamiento completado en un tiempo de: ", duration)



    ########################
    #Evaluar el modelo
    ########################
    '''
    Finalmente, para determinar la precisión del modelo generado, llamamos a la función evaluate y le pasamos los datos de test que hemos definido previamente.
    '''
    # Evaluamos el modelo con el set de datos de testing
    score = model.evaluate(x_test, y_test, verbose=0)
    print("Testing Accuracy: ", score[1])

    return str(score[1])

@app.route('/existe-modelo')
def existeModelo():
    macAddress=request.args.get('mac')
    macAddressDir=macAddress.replace(':', '')
    archivoModelo="modelos/"+macAddressDir+".hdf5"
    #Validar que el archivo existe
    if os.path.isfile(archivoModelo):
        return "1"
    else:
        return "0"

@app.route('/lista-mediciones')
def listaMediciones():
    import json
    from datetime import date, datetime
    if 'mac' in request.args:
        macAddress=request.args.get('mac')
        fecha=request.args.get('fecha')
        #macAddressDir=macAddress.replace(':', '')
        sql = "SELECT ip,idDispositivo,archivoAudio,estado,fechaCreacion FROM mediciones WHERE idDispositivo='"+macAddress+"' and fechaCreacion>='"+fecha+" 00:00:00'  AND fechaCreacion<='"+fecha+" 23:59:59' order by fechaCreacion desc; ";
        print(sql)
        mycursor = mydb.cursor()
        mycursor.execute(sql)
        row_headers=[x[0] for x in mycursor.description] #this will extract row headers
        rv = mycursor.fetchall()
        mydb.commit()
        json_data=[]
        for result in rv:
            print(result)
            json_data.append(dict(zip(row_headers,result)))
        jsonString="{\"data\":"
        jsonString=jsonString + json.dumps(json_data, default=str)
        jsonString=jsonString + "}"
        mycursor.close()
        return jsonString
    else:
        jsonString="{\"data\":"
        jsonString=jsonString + "[]"
        jsonString=jsonString + "}"
        return jsonString
#INICIAMSO FLASK
if __name__ == "__main__":
  app.run(host="0.0.0.0")

LeeParaEntrenar.py

'''
LEE PARA ENTRENAR:
ESTE PROGRAMA RECIBE LOS AUDIOS DE LOS DISPOSITIVOS
QUE DESPUES SERAN LEIDOS PARA CREAR UN MODELO
'''
from datetime import datetime
import socket
import wave
from itertools import groupby
import os

sockEntrenar = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# Recibimos datos desde cualquier ip al puerto 8080
sockEntrenar.bind(("", 8080))
# Si el socket se tarda mas de 1 segundo en recibir datos, se cierra
sockEntrenar.settimeout(2)
#Iniciamos los frames para guardar el archivo
frames = []
#Almacenamos la direccion ip de del paquete recibido
direccionIP=""
#Almacenamos el puerto de del paquete recibido
data=""
# Se sale si precionamos ctrl + c
try:
    # Creamos un ciclo infinito
    while True:
        # Se sale si no se reciben datos por mas de 1 segundo
        try:
            #Creamos un bucle infinito para que siempre este escuchando
            while True:
                data, addr = sockEntrenar.recvfrom(1024)
                direccionIP=str(addr[0])
                print (len(data))
                frames.append({'data':data,'direccion':direccionIP})
        #Si se dejo de recibir datos por mas de 1 segundo, se sale del ciclo
        except socket.timeout:
            # Si se recibio algo, se guarda en un archivo
            if(len(data)>0):
                #Agrupamos los frames por direccion ip
                frames.sort(key=lambda content: content['direccion'])
                groups = groupby(frames, lambda content: content['direccion'])
                #Hacemos un ciclo por cada direccion ip (grupo)
                for direccionIP, group in groups:
                    #Esta variable almacenara los frames (sonido/segundo) que despues se guardaran en un archivo
                    framesData=[]
                    macAddress=""
                    estado=""
                    contadorPaq=0
                    contadorArch=0
                    print ('direccion', direccionIP)
                    #Ciclo que leera cada frame (sonido/segundo) y lo guardara en la variable framesData que despues se guardara en un archivo
                    for content in group:
                        print ('\ttam=', len(content["data"])," contadorPaq=",contadorPaq)
                        #Si el tamaño es menor a 50 entonces es macadress del esp8266
                        if(len(content["data"])<100):
                            contenido=content["data"].decode("utf-8")
                            #Si el contenido recibido es igual a algun estado entonces  guardamos ese estado
                            if(contenido=="Vacio" or contenido=="Medio" or contenido=="Lleno"):
                                estado=contenido
                            #Si el contenido recibido es para inicializar el servidor y escuchar todo
                            elif(contenido=="1"):
                                pass
                            #Si el contenido no es ningun estado ni 1 entonces es una macadress
                            else:
                                macAddress=contenido
                                macAddress=content["data"].decode("utf-8")
                        else:
                            framesData.append(content["data"])
                            if( (contadorPaq%8)==0 and contadorPaq>0 ):
                                #Creamos el nombre del archivo con la direccion ip y la fecha de hoy
                                nombreArchivo = estado+str(contadorArch)+".wav"
                                print(nombreArchivo)
                                macAddressDir=macAddress.replace(':', '')
                                try:
                                    os.mkdir("audioRecibido/"+macAddressDir)
                                except FileExistsError:
                                    pass
                                nombreArchivo="audioRecibido/"+macAddressDir+"/"+nombreArchivo
                                #Si el archivo del modelo existe lo borramos
                                if os.path.exists(nombreArchivo):
                                    os.remove(nombreArchivo)

                                # Creamos un archivo con la fecha y hora y la direccion ip
                                file = wave.open(nombreArchivo, 'wb')
                                file.setnchannels(1)
                                file.setframerate(11111)
                                # en bytes. 1->8 bits, 2->16 bits
                                file.setsampwidth(1)
                                file.writeframes(b''.join(framesData))
                                file.close()
                                contadorArch=contadorArch+1
                                framesData=[]
                            contadorPaq=contadorPaq+1
                frames=[]
                framesData=[]
                data=""
except KeyboardInterrupt:
    print("Cerrando...")
    sockEntrenar.close()

Predecir.py

'''
PREDECIR
ESTE PROGRAMA SE ENCARGA DE RECIBIR LOS AUDIOS DE LOS DISPOSITIVOS 
PREDECIR SU ESTADO (VACIO,MEDIO,LLENO) Y AGREGARLAS A LA BASE DE DATOS
'''
from datetime import datetime
import socket
import wave
from itertools import groupby
import CargaModelo as model
#pip install mysql-connector
import mysql.connector
import Conexion
import os
mydb = mysql.connector.connect(
  host=Conexion.host,
  user=Conexion.user,
  passwd=Conexion.passwd,
  database=Conexion.database
)
mycursor = mydb.cursor()
sockPredecir = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# Recibimos datos desde cualquier ip al puerto 80
sockPredecir.bind(("", 80))
# Si el socket se tarda mas de 1 segundo en recibir datos, se cierra
sockPredecir.settimeout(2)
#Iniciamos los frames para guardar el archivo
frames = []
#Almacenamos la direccion ip de del paquete recibido
direccionIP=""
#Almacenamos el puerto de del paquete recibido
data=""
# Se sale si precionamos ctrl + c
try:
    # Creamos un ciclo infinito
    while True:
        # Se sale si no se reciben datos por mas de 1 segundo
        try:
            #Creamos un bucle infinito para que siempre este escuchando
            while True:
                data, addr = sockPredecir.recvfrom(1024)
                direccionIP=str(addr[0])
                print (len(data))
                frames.append({'data':data,'direccion':direccionIP})
        #Si se dejo de recibir datos por mas de 1 segundo, se sale del ciclo
        except socket.timeout:
            # Si se recibio algo, se guarda en un archivo
            if(len(data)>0):
                #Agrupamos los frames por direccion ip
                frames.sort(key=lambda content: content['direccion'])
                groups = groupby(frames, lambda content: content['direccion'])
                #Hacemos un ciclo por cada direccion ip (grupo)
                for direccionIP, group in groups:
                    #Esta variable almacenara los frames (sonido/segundo) que despues se guardaran en un archivo
                    framesData=[]
                    macAddress=""
                    print ('direccion', direccionIP)
                    #Ciclo que leera cada frame (sonido/segundo) y lo guardara en la variable framesData que despues se guardara en un archivo
                    for content in group:
                        print ('\t', len(content["data"]))
                        # Si el tamano es menor a 50 entonces es macadress del esp8266
                        if(len(content["data"])<100):
                            contenido=content["data"].decode("utf-8")
                            #Si el contenido recibido es para inicializar el servidor y escuchar todo
                            if(contenido=="1"):
                                pass
                            else:
                                macAddress=content["data"].decode("utf-8")
                        else:
                            framesData.append(content["data"])
                    macAddressDir=macAddress.replace(':', '')
                    #Creamos el nombre del archivo con la direccion ip y la fecha de hoy
                    nombreArchivoAudio = direccionIP+"-"+datetime.now().strftime('%Y-%m-%d-%H-%M-%S')+".wav"
                    print("nombreArchivoAudio=",nombreArchivoAudio)
                    #Si estamos en windows, se crea un archivo en la carpeta de windows, si no, en la carpeta de linux
                    nombreArchivoAudio="audioRecibido/"+nombreArchivoAudio
                    # Creamos un archivo con la fecha y hora y la direccion ip
                    file = wave.open(nombreArchivoAudio, 'wb')
                    file.setnchannels(1)
                    file.setframerate(11111)
                    # en bytes. 1->8 bits, 2->16 bits
                    file.setsampwidth(1)
                    file.writeframes(b''.join(framesData))
                    file.close()
                    file_size = os.path.getsize(nombreArchivoAudio)
                    #Si el tamano del archivo es mayor a 5KB hacemos la prediccion del sonido
                    if( file_size>5000 ):
                        #Si el modelo de esta mac existe la usamos de lo contrario usamos el archivo estandar
                        archivoModelo="modelos/"+macAddressDir+".hdf5"
                        if os.path.isfile(archivoModelo)==False:
                            archivoModelo="modelos/estandar.hdf5"
                        print("archivoModelo=",archivoModelo)
                        try:
                            estadoLleno,exactitud=model.nivelDeLleno(rutaModelo=archivoModelo,archivoAudio=nombreArchivoAudio)
                            print("---ESTADO:",estadoLleno," | Exactitud de prediccion:",exactitud)
                        except:
                            estadoLleno="Intente de nuevo"
                            print("---ESTADO:",estadoLleno)
                        #Insertamos en la tabla mediociones las mediciones de este dispositivo
                        sql = "INSERT INTO mediciones(ip,idDispositivo,archivoAudio,estado) VALUES (%s,%s,%s,%s)"
                        val = (direccionIP,macAddress,nombreArchivoAudio,estadoLleno)
                        #validar si se inserto correctamente
                        try:
                            mycursor.execute(sql, val)
                            mydb.commit()
                        except mysql.connector.Error as error:
                            print("Error: No se pudo insertar la medicion ",error)
                        finally:
                            if os.path.exists(nombreArchivoAudio):
                                #os.remove(nombreArchivoAudio)
                                #print(nombreArchivoAudio," borrado")
                                pass
                            #mycursor.close()
                            pass
                frames=[]
                framesData=[]
                data=""
except KeyboardInterrupt:
    print("Cerrando...")
    sockPredecir.close()

Ejecutamos estos 3 archivos para iniciar la IA de MediNako
Finalmente de debe ver asi

Los comentarios están cerrados.

Salir de la versión móvil