Related
I have about a half million records that look somewhat like this:
=001 000016937
=005 20160611133900.0
=007 ta
=008 930824s1990\\\\cl\\\\\\\\\\\\000\0\spa\u
=041 1 $aspaspaeng
=084 \ $aTV/UdeC/G589s
=100 1 $aGonzález Ugas, Jorge$e, autor$e, autor
=245 10$aSincronización de estro y fertilidad en bovinos de carne sincronizados con un análogo de PGF-2 alfa vía intravulvosubmucosa
=260 \ $aChillán:$bUniversidad de Concepción,$c1990
=300 \ $a48 páginas$bcuadros
=336 \ $atext$btxt$2rdacontent
=337 \ $aunmediated$bn$2rdamedia
=338 \ $avolume$bnc$2rdacarrier
=502 \ $aMemoria de título (Méd. Veterinario)
=504 \ $aIncluye Bibliografía
=520 \ $aCon el fin de establecer la eficacia de la administración de 0,45 mgr de Tiaprost vía intravulvosubmucosa en la inducción de estro y determinar la fertilidad de los sistemas de inseminación artificial a tiempo fijo, con detección de estro y monta dirigida, se trataron 134 vacas y vaquillas de carne divididas en 3 grupos: grupo 1=56 vaquillas; grupo 2=39 [24 vaquillas y 15 vacas] y grupo 3=39 vaquillas. Cada grupo recibió un manejo nutricional diferente. El Tiaprost se administró luego de detectar la presencia de un cuerpo luteo. A las vaquillas del grupo 1 se les detectó calor 3 veces al día durante 45 minutos y se inseminaron con semen congelado a un tiempo prefijado de 80 hrs. Los animales que no entraron en calor en un tiempo de 5 días post-tratamiento volvieron a ser tratados con PGF-2 alfa 10-12 días después; se detectó calor y realizó monta dirigida. Las hembras del grupo 2 se inseminaron a las 80 hrs. después del tratamiento sin detectar calor; y a las vaquillas del grupo 3 se les realizó monta dirigida con toro 12 hrs. después de iniciado el calor. Todas las hembras tratadas se palparon 60-90 días post-tratamiento para diagnosticar preñez. En el grupo 1 se obtuvo un lapso tratamiento-estro promedio de 42,5 hrs.[8-96 hrs.], un 100 por ciento de respuesta al tratamiento dentro de las primeras 96 hrs. post-tratamiento y una duración del celo de 19,22 hrs.[8-36 hrs] con moda de 18 hrs. Se obtuvo un 69,9 por ciento de preñez para el grupo 1; 33,1 por ciento en el grupo 2 [29.1 por ciento en vaquillas y 40 por ciento en vacas] y un 79.9 por ciento en el grupo 3. Se concluyó que la administración de 0,45 mgr de Tiaprost vía intravulvosubmucosa es efectiva en inducir estro en hembras bovinas de carne y la fertilidad es comparable a la obtenida con monta natural. La fertilidad es superior al emplear la detección de estros e inseminar a tiempo prefijado [80 hrs.] o cubrir con monta natural [12 hrs. después de iniciado el calor]
=520 \ $aque al inseminar a las 80 hrs. sin previa detección de calor. Se obtuvieron resultados aceptables al comparar la inseminación artificial a tiempo prefijado [80 hrs.] detectando calor con monta natural en vaquillas sincronizadas con Tiaprost vía intravulvosubmucosa.
=650 \4$aVaquillas
=650 \4$aGanado Vacuno de Carne
However, the value in the 001 field is incorrect for many thousands of items. I have a mapping file of what needs to be there that looks like this:
000016937 000138905
000022242 000142318
000022736 000125671
000023118 000141783
000031516 000165088
000068203 000165324
000071245 000132319
000081724 000163695
000093665 000237196
Desired output would be something like:
=001 000138905
=005 20160611133900.0
=007 ta
=008 930824s1990\\\\cl\\\\\\\\\\\\000\0\spa\u
=041 1 $aspaspaeng
=084 \ $aTV/UdeC/G589s
=100 1 $aGonzález Ugas, Jorge$e, autor$e, autor
=245 10$aSincronización de estro y fertilidad en bovinos de carne sincronizados con un análogo de PGF-2 alfa vía intravulvosubmucosa
=260 \ $aChillán:$bUniversidad de Concepción,$c1990
=300 \ $a48 páginas$bcuadros
=336 \ $atext$btxt$2rdacontent
=337 \ $aunmediated$bn$2rdamedia
=338 \ $avolume$bnc$2rdacarrier
=502 \ $aMemoria de título (Méd. Veterinario)
=504 \ $aIncluye Bibliografía
=520 \ $aCon el fin de establecer la eficacia de la administración de 0,45 mgr de Tiaprost vía intravulvosubmucosa en la inducción de estro y determinar la fertilidad de los sistemas de inseminación artificial a tiempo fijo, con detección de estro y monta dirigida, se trataron 134 vacas y vaquillas de carne divididas en 3 grupos: grupo 1=56 vaquillas; grupo 2=39 [24 vaquillas y 15 vacas] y grupo 3=39 vaquillas. Cada grupo recibió un manejo nutricional diferente. El Tiaprost se administró luego de detectar la presencia de un cuerpo luteo. A las vaquillas del grupo 1 se les detectó calor 3 veces al día durante 45 minutos y se inseminaron con semen congelado a un tiempo prefijado de 80 hrs. Los animales que no entraron en calor en un tiempo de 5 días post-tratamiento volvieron a ser tratados con PGF-2 alfa 10-12 días después; se detectó calor y realizó monta dirigida. Las hembras del grupo 2 se inseminaron a las 80 hrs. después del tratamiento sin detectar calor; y a las vaquillas del grupo 3 se les realizó monta dirigida con toro 12 hrs. después de iniciado el calor. Todas las hembras tratadas se palparon 60-90 días post-tratamiento para diagnosticar preñez. En el grupo 1 se obtuvo un lapso tratamiento-estro promedio de 42,5 hrs.[8-96 hrs.], un 100 por ciento de respuesta al tratamiento dentro de las primeras 96 hrs. post-tratamiento y una duración del celo de 19,22 hrs.[8-36 hrs] con moda de 18 hrs. Se obtuvo un 69,9 por ciento de preñez para el grupo 1; 33,1 por ciento en el grupo 2 [29.1 por ciento en vaquillas y 40 por ciento en vacas] y un 79.9 por ciento en el grupo 3. Se concluyó que la administración de 0,45 mgr de Tiaprost vía intravulvosubmucosa es efectiva en inducir estro en hembras bovinas de carne y la fertilidad es comparable a la obtenida con monta natural. La fertilidad es superior al emplear la detección de estros e inseminar a tiempo prefijado [80 hrs.] o cubrir con monta natural [12 hrs. después de iniciado el calor]
=520 \ $aque al inseminar a las 80 hrs. sin previa detección de calor. Se obtuvieron resultados aceptables al comparar la inseminación artificial a tiempo prefijado [80 hrs.] detectando calor con monta natural en vaquillas sincronizadas con Tiaprost vía intravulvosubmucosa.
=650 \4$aVaquillas
=650 \4$aGanado Vacuno de Carne
There are many ways this problem could be solved, but I'm hoping for a quick and dirty way (ie a few lines of script as opposed to a program) as I expect to encounter similar situations again. My gut reaction was to just hand it to sed, but I got an "Argument list too long" which puzzled me because
sh-4.2$ getconf ARG_MAX
2097152
and I don't have that many values to map. That the correct numbers overlap with the incorrect ones is not a problem -- I'll just prefix the former so only the wrong ones can get fixed.
Total file size of the records is just over a half gig so there should be some options.
For me, this is a natural fit for awk:
tmp=$(mktemp)
awk '
NR == FNR {map[$1] = $2; next}
$1 == "=001" && $2 in map {$2 = map[$2]}
{print}
' mappingFile bigFile > "$tmp" && mv "$tmp" bigFile
Maybe ed if available/acceptable, with the bash shell using Process Substitution.
#!/usr/bin/env bash
ed -s giant_file.txt < <(
printf '%s\n' 'g|.|s|^\([^[:blank:]]*\)*[[:blank:]]*\(.*\)$|g/^=001 /s/\1/\2/|' '$a' w . ,p Q |
ed -s mapping_file.txt
)
Note: It will edit the file in-place
This version will just output to stdout.
#!/usr/bin/env bash
ed -s giant_file.txt < <(
printf '%s\n' 'g|.|s|^\([^[:blank:]]*\)*[[:blank:]]*\(.*\)$|g/^=001 /s/\1/\2/|' '$a' ,p Q . ,p Q |
ed -s mapping_file.txt
)
I am trying to load and delete images when loading an image I create a status bar to tell me the name of the file and if I delete it, the bar is cleaned, I get this error and I do not know what it may be, luckily they load me the images but in the console, it throws me that error and it does not show me the status bar (I leave part of the code), thanks...
Error
Traceback (most recent call last): File "lol.py", line 220, in
self.animacionMostar.finished.connect(lambda: (self.statusBar.showMessage(nombre))) AttributeError:
'VentanaVISUALIZAR' object has no attribute 'statusBar'
Code:
class VentanaVISUALIZAR(QDialog):
def __init__(self, parent=None):
super(VentanaVISUALIZAR, self).__init__()
self.setWindowIcon(QIcon("icono.png"))
self.setWindowTitle("Visualizador ")
self.setWindowFlags(Qt.MSWindowsFixedSizeDialogHint)
self.setFixedSize(1020, 680)
self.widget()
def widget(self):
# ===================== LLAMAR WIDGETS =======================
framePrincipal = QFrame(self)
framePrincipal.setFrameShape(QFrame.Box)
framePrincipal.setFrameShadow(QFrame.Sunken)
framePrincipal.setAutoFillBackground(True)
framePrincipal.setBackgroundRole(QPalette.Light)
framePrincipal.setFixedSize(1000, 560)
framePrincipal.move(10, 10)
frame = QFrame(framePrincipal)
frame.setFixedSize(980, 540)
frame.move(10, 10)
self.labelImagen = QLabel(frame)
self.labelImagen.setAlignment(Qt.AlignCenter)
self.labelImagen.setGeometry(0, 0, 980, 540)
self.labelImagenUno = QLabel(frame)
self.labelImagenUno.setAlignment(Qt.AlignCenter)
self.labelImagenUno.setGeometry(-970, 0, 980, 540)
# =================== BOTONES VISUALIZADOR ==================
botonVCargar = QPushButton("Cargar Imagen", self)
botonVCargar.setGeometry(QRect(10,590,325,30))
botonVCargar.setIcon(QtGui.QIcon("cargar.png"))
botonVCargar.setIconSize(QtCore.QSize(20,20))
botonVEliminar = QPushButton("Eliminar Imagen", self)
botonVEliminar.setGeometry(QRect(350,590,325,30))
botonVEliminar.setIcon(QtGui.QIcon("borrar.png"))
botonVEliminar.setIconSize(QtCore.QSize(20,20))
#================== ACCIONES BOTONES VISUALIZADOR ===================
botonVCargar.clicked.connect(self.Cargar)
botonVEliminar.clicked.connect(self.Eliminar)
posicion = int
carpetaActual = QDir()
imagenesCarpeta = []
def bloquearBotones(self, bool):
self.botonVCargar.setEnabled(bool)
self.botonVEliminar.setEnabled(bool)
def Mostrar (self, label, imagen, nombre, posicionX=970):
imagen = QPixmap.fromImage(imagen)
# Escalar imagen a 640x480 si el ancho es mayor a 640 o el alto mayor a 480
if imagen.width() > 980 or imagen.height() > 540:
imagen = imagen.scaled(980, 540, Qt.KeepAspectRatio, Qt.SmoothTransformation)
# Mostrar imagen
label.setPixmap(imagen)
# Animación (al finalizar la animación se muestra en la barra de estado el nombre y la extensión de la imagen
# y se desbloquean los botones).
self.animacionMostar = QPropertyAnimation(label, b"geometry")
self.animacionMostar.finished.connect(lambda: (self.statusBar.showMessage(nombre)))
self.animacionMostar.setDuration(200)
self.animacionMostar.setStartValue(QRect(posicionX, 0, 960, 540))
self.animacionMostar.setEndValue(QRect(0, 0, 960, 540))
self.animacionMostar.start(QAbstractAnimation.DeleteWhenStopped)
def Limpiar(self, labelConImagen, labelMostrarImagen, imagen, nombre,
posicionInternaX, posicionX=None):
def Continuar(estado):
if estado:
if posicionX:
self.Mostrar(labelMostrarImagen, imagen, nombre, posicionX)
else:
self.Mostrar(labelMostrarImagen, imagen, nombre)
self.animacionLimpiar = QPropertyAnimation(labelConImagen, b"geometry")
self.animacionLimpiar.finished.connect(lambda: labelConImagen.clear())
self.animacionLimpiar.setDuration(200)
# self.animacionLimpiar.valueChanged.connect(lambda x: print(x))
self.animacionLimpiar.stateChanged.connect(Continuar)
self.animacionLimpiar.setStartValue(QRect(0, 0, 980, 540))
self.animacionLimpiar.setEndValue(QRect(posicionInternaX, 0, 980, 540))
self.animacionLimpiar.start(QAbstractAnimation.DeleteWhenStopped)
def Cargar(self):
nombreImagen, _ = QFileDialog.getOpenFileName(self, "Seleccionar imagen",
QDir.currentPath(),
"Archivos de imagen (*.jpg *.png *.ico *.bmp)")
if nombreImagen:
# Verificar que QLabel tiene imagen
labelConImagen = ""
if self.labelImagen.pixmap():
labelConImagen = self.labelImagen
elif self.labelImagenUno.pixmap():
labelConImagen = self.labelImagenUno
imagen = QImage(nombreImagen)
if imagen.isNull():
if labelConImagen:
self.Eliminar()
QMessageBox.information(self, "Visor de imágenes",
"No se puede cargar %s." % nombreImagen)
return
# Obtener ruta de la carpeta que contiene la imagen seleccionada
self.carpetaActual = QDir(QFileInfo(nombreImagen).absoluteDir().path())
# Obtener la ruta y el nombre de las imagenes que se encuentren en la carpeta de
# la imagen seleccionada
imagenes = self.carpetaActual.entryInfoList(["*.jpg", "*.png", "*.ico", "*.bmp"],
QDir.Files, QDir.Name)
self.imagenesCarpeta = [imagen.absoluteFilePath() for imagen in imagenes]
self.posicion = self.imagenesCarpeta.index(nombreImagen)
# Función encargada de bloquear o desbloquear los botones
#self.bloquearBotones(False)
# Nombre y extensión de la imagen
nombre = QFileInfo(nombreImagen).fileName()
if labelConImagen:
posicionInternaX = -970
labelMostrarImagen = self.labelImagen if self.labelImagenUno.pixmap() else self.labelImagenUno
self.Limpiar(labelConImagen, labelMostrarImagen, imagen, nombre, posicionInternaX)
else:
self.Mostrar(self.labelImagen, imagen, nombre)
def Eliminar(self):
def establecerValores():
labelConImagen.clear()
labelConImagen.move(0, 0)
# Limpiar la barra de estado
self.statusBar.clearMessage()
# Establecer los valores predeterminados
self.posicion = int
self.estadoAnterior, self.estadoSiguiente = False, False
self.carpetaActual = QDir()
self.imagenesCarpeta.clear()
#self.bloquearBotones(True)
# Verificar que QLabel tiene imagen
labelConImagen = ""
if self.labelImagen.pixmap():
labelConImagen = self.labelImagen
elif self.labelImagenUno.pixmap():
labelConImagen = self.labelImagenUno
if labelConImagen:
#self.bloquearBotones(False)
self.animacionEliminar = QPropertyAnimation(labelConImagen, b"geometry")
self.animacionEliminar.finished.connect(establecerValores)
self.animacionEliminar.setDuration(200)
self.animacionEliminar.setStartValue(QRect(0, 0, 640, 480))
self.animacionEliminar.setEndValue(QRect(-650, 0, 640, 480))
self.animacionEliminar.start(QAbstractAnimation.DeleteWhenStopped)
VentanaVISUALIZAR is a subclass of QDialog which does not have a status bar by default. You can add one by adding something like this to VentanaVISUALIZAR.__init__:
self.statusBar = QStatusBar(self)
self.statusBar.setSizeGripEnabled(False)
self.statusBar.move(0,650)
self.statusBar.setFixedSize(1020,30)
Helloooo guys !
I've started a project to write an algorithm that can recognize constellations in the northern hemisphere. But it can only recognize constellations on very easy pictures.
My objective being this:
private fun rotate(
templateData: Array<Array<Array<String>>>,
brightest_index: Int,
second_brightest: Int
): Array<Array<DoubleArray>> {
val userStarData: Array<DoubleArray> = CameraActivity.starArray
val rotatedTemplates =
Array(
5
) {
Array(
89
) { arrayOfNulls<String>(31) }
}
val x0: Double
val y0: Double
val x1: Double
val y1: Double
val dx: Double
val dy: Double
var angle = 0.0
x0 = userStarData[brightest_index][0]
y0 = userStarData[brightest_index][1]
x1 = userStarData[second_brightest][0]
y1 = userStarData[second_brightest][1]
dx = x1 - x0
dy = y1 - y0
// Angle en Radians
angle = Math.atan(dx / dy)
Log.i(TAG, "Rotation angle: $angle")
return rotateTemplates(templateData, angle)
}
/**
* Cette fonction est appelée une fois que l'angle de rotation a été calculé, fait tourner les données du modèle.
* #param templateData template de constellation
* #param angle angle de rotation déterminé par rotateTemplate
* #return
*/
private fun rotateTemplates(
templateData: Array<Array<Array<String>>>,
angle: Double
): Array<Array<DoubleArray>> {
val rotatedTemplates =
Array(
5
) { Array(89) { DoubleArray(31) } }
var x: Double
var y: Double
var xprime: Double
var yprime: Double
// Pour chaque constellation :
for (i in 0..85) {
val numStars = templateData[0][i][1].toInt()
for (j in 0 until numStars) {
x = templateData[1][i][j].toDouble()
y = templateData[2][i][j].toDouble()
// Pour chaque x et y, analyser les valeurs, puis calculer les valeurs pivotées. Formules :
// x' = (x * cos(theta)) - (y * sin(theta))
// y' = (x * sin(theta)) + (y * cos(theta))
xprime = x * Math.cos(angle) - y * Math.sin(angle)
yprime = x * Math.sin(angle) + y * Math.cos(angle)
// Échange des coordonnées x et y pour inverser les modèles afin qu'ils correspondent à la façon dont la caméra représente les blobs
rotatedTemplates[1][i][j] = yprime
rotatedTemplates[2][i][j] = xprime
}
}
return rotatedTemplates
}
//cette fonction recherche dans les ensembles de données d'images et de modèles de l'utilisateur pour trouver une correspondance entre les données
//cette fonction recherche les correspondances en analysant chaque ensemble de triplets d'étoiles dans l'ensemble des données de l'image utilisateur
//regarder d'abord les deux premières étoiles du triplet pour déterminer l'échelle de leurs coordonnées et appliquer cette échelle au modèle considéré
//puis itérez sur l'ensemble de données de l'utilisateur pour chaque ensemble de triplets possibles, en vérifiant s'il y a une correspondance de distance
//dans une fenêtre de 10 % de la distance entre les étoiles correspondantes du modèle
//continuer d'itérer jusqu'à ce qu'un triplet soit trouvé
//puis itérez les données de l'utilisateur à partir de la troisième étoile du triplet pour trouver les autres étoiles de la constellation
private fun findConstellationMatch(templateData: Array<Array<Array<String>>>): Array<Array<String>> {
val userStarData: Array<DoubleArray> =
CameraActivity.starArray //saisir un ensemble de données à partir d'une image de l'utilisateur provenant de l'activité de la caméra
val match =
Array(
3
) { Array(31, {i -> ""}) }
// ) { arrayOfNulls<String>(31) } //ce tableau contiendra les coordonnées de toutes les étoiles de la constellation identifiée
var templateNumStars: Int
for (i in 0..85) //itérer à travers chacune des 89 constellations
{
templateNumStars = templateData[0][i][1].toInt()
//itérer sur le jeu de données de l'image utilisateur pour l'index de la première étoile du triplet
for (starOne in 0 until userStarData.size - 2) {
val starOne_x = userStarData[starOne][0]
//itérer sur le jeu de données de l'image utilisateur pour l'index de la seconde étoile du triplet
for (starTwo in starOne + 1 until userStarData.size - 1) {
val rotatedTemplates =
rotate(templateData, starOne, starTwo)
val starTwo_x = userStarData[starTwo][0]
//itérer sur le jeu de données de l'image utilisateur pour l'index de la troisieme étoile du triplet
for (starThree in starTwo + 1 until userStarData.size) { // Échelle utilisant la distance entre les deux étoiles les plus brillantes, calculer les rapports.
val templateXDelta =
(rotatedTemplates[1][i][2] - rotatedTemplates[1][i][1]) / (rotatedTemplates[1][i][1] - rotatedTemplates[1][i][0])
val templateYDelta =
(rotatedTemplates[2][i][2] - rotatedTemplates[2][i][1]) / (rotatedTemplates[2][i][1] - rotatedTemplates[2][i][0])
val xDelta =
(userStarData[starThree][0] - userStarData[starTwo][0]) / (userStarData[starTwo][0] - userStarData[starOne][0])
val yDelta =
(userStarData[starThree][1] - userStarData[starTwo][1]) / (userStarData[starTwo][1] - userStarData[starOne][1])
//vérifier si une correspondance a été trouvée avec le jeu de triplés
if (templateNumStars <= userStarData.size && xDelta > templateXDelta * 0.9 && xDelta < templateXDelta * 1.1 && yDelta > templateYDelta * 0.9 && yDelta < templateYDelta * 1.1) {
Log.i(
TAG,
"Match le premier triplet de " + templateData[0][i][0]
)
//si une correspondance a été trouvée, enregistrer leurs coordonnées dans le tableau de correspondance [][] ainsi que le nom de la constellation identifiée
match[0][0] = templateData[0][i][0]
match[1][0] =
java.lang.Double.toString(userStarData[starOne][0])
match[2][0] =
java.lang.Double.toString(userStarData[starOne][1])
match[1][1] =
java.lang.Double.toString(userStarData[starTwo][0])
match[2][1] =
java.lang.Double.toString(userStarData[starTwo][1])
match[1][2] =
java.lang.Double.toString(userStarData[starThree][0])
match[2][2] =
java.lang.Double.toString(userStarData[starThree][1])
return match
}
}
}
}
}
// Si aucune correspondance n'a été trouvée, retournez un tableau vide..
val res = Array(3) { Array(31, {i -> ""}) }
return res
// return Array(3) { arrayOfNulls<String>(31) }
}
}
The database look like that :
link to image of db
I don't know if the error comes from the image processing or from the algorithm itself.
My script:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import multiprocessing
import pickle
import socket
import ssl
import sys
import time
from Logs.cryptography import symmetric_crypto
from Logs import sign_up_log_in as log
class Servidor():
"""
Se creara un servidor en local (127.0.0.1), en el puerto 7000.
"""
def __init__(self,host = "192.168.0.16", port = 7000):
"""
En self.clientes se almacenaran todos los usuarios que se conecten al servidor
setblocking(False or True) -> si este es True (por defecto), sera un socket bloqueante,
lo que quiere decir que el servidor solo atendera a una sola peticion y las demas deberan
esperar, en cambio si es False, este atendera todas las peticiones que lleguen de manera simultanea con ayuda de los hilos.
threading.Thread(target = metodo())
* La clase Thread cuenta con un parametro llamado target, el cual ejecutara un metodo o funcionalidad de forma simultanea a
otros procesos, tareas (metodos - funcionalidades) que tambien deseen ejecutarse al tiempo, a esto se le conoce como hilos.
El parametro daemon sirve para darle fin a los hilos, una vez que el programa haya terminado, esto es util cuando no queremos que estos procesos
queden andando sin motivo alguno.
El metodo start(), da inicio al hilo hijo, el hilo principal es el de la ejecucion del propio programa en si.
Este metodo se coloca despues del parametro daemon, siempre y cuando hagamos uso de el.
El metodo join(), sirve para indicarle al programa que no debe ejecutar mas procesos (hilos), hasta que no termine con el actual(proceso-hilo),
este metodo se coloca despues del start() metodo.
"""
self.load_clients()
self.clientes_registrados = []
self.clientes_conectados = []
self.staging_area = []
self.nickname = None
self.transmitted_message = None
self.server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
self.server.bind((str(host),int(port)))
self.server.listen(10)
self.server.setblocking(False)
# se ejecutan de inmediato al iniciar el programa
recv_logging = multiprocessing.Process(target = self.recv_logging)
aceptar_conn = multiprocessing.Process(target = self.aceptar_conn)
recv_messages = multiprocessing.Process(target = self.recv_messages)
lista_send_conn = multiprocessing.Process(target = self.lista_send_conn)
# se anclan al hilo principal, los hilos hijos, para que estos no queden como procesos andantes aun despues de haberse cerrado el programa,
# seguido de esto se inicia la ejecucion de los metodos.
recv_logging.daemon = True
recv_logging.start()
aceptar_conn.daemon = True
aceptar_conn.start()
lista_send_conn.daemon = True
lista_send_conn.start()
recv_messages.daemon = True
recv_messages.start()
def lista_send_conn(self):
if bool( self.clientes_conectados ):
package = (self.clientes_conectados,"lista_conn")
self.conn_cliente.send( pickle.dumps(package) )
def save_clients(self):
"""
Metodo que guarda los cambios producidos en el archivo clientes.pckl
"""
with open("clientes.pckl","wb") as clients:
pickle.dump(self.clientes_registrados,clients)
def load_clients(self):
"""
Metodo que carga el archivo clientes.pckl en una variable para su posterior uso.
"""
with open("clientes.pckl","ab+") as clients:
clients.seek(0)
try:
self.clientes_registrados = pickle.load(clients)
except:
pass
def recv_logging(self):
# El error esta en este metodo, que no hace el recv de lo que le manda el cliente (obj_usuario -> (user/password) )
"""
Este metodo recibira una variable por parte del metodo login(), del modulo cliente.py, el cual tendra un dict que tiene en la clave la ip del usuario,
y en su valor, el objeto de la clase Usuario del cliente.
Se recorre la lista (con los diccionarios "self.clientes del modulo sign_up_log_in.py" dentro), para asi poder verificar la existencia de un usuario
que dice registrarse o logearse dentro del servidor.
A cada cliente de la lista de registrados, se le saca su valor a la variable obj_usuario, recordemos que la clave era la ip, y su valor el objeto de la clase Usuario del respectivo
usuario.
"""
while True:
# Desencripta el archivo .pckl para su posterior uso.
if self.transmitted_message != None:
self.decrypt_data_logging(self.transmitted_message)
# cliente[ip] devuelve un objeto Usuario (nickname, password del usuario), objeto que se almcanera en obj_usuario,
# para posteriormente comparar los nicknames de los clientes en base de datos, con los que se acaban de pronunciar (sign or log),
# y sus contraseñas.
# Este for lo uso para saber si esa ip entrante ya esta registrada, de modo que si se levanta un error, no esta registrada,
# en cambio si no se levanta un error, quiere decir que el usuario si esta, pero que si no ingreso es por un error de autenticacion
manager = log.Controller()
# recibir una tupla (obj_user, id, ip), el id puedes ser "log-in" o "sign-up"
if bool(self.staging_area):
for conexion in self.staging_area:
try:
received_data = conexion.recv(2048) # ERROR (pero aca se caga todoooo)
except Exception as e:
print(e)
else:
received_data = pickle.loads(received_data)
# desempaquetamos el paquete
#received_id = received_data[0][1]
received_id = received_data[1]
# el id sirve especificamente para redireccionar en este condicional, a sus respectivos metodos
if received_id == "sign_up":
#received_sign_up = received_data[0][0]
received_sign_up = received_data[0]
status_ok = manager.add_user(received_sign_up, self.clientes_registrados)
else:
#received_log_in = received_data[0][0]
received_log_in = received_data[0]
status_ok = manager.verify_user(received_log_in, self.clientes_registrados)
# de acuerdo a lo que se retorna en los metodos verify_user() y add_user(), se ejecutan ciertas tareas.
# Errores al momento de realizar el proceso de logueo
if status_ok == "user_exist_signup":
if bool(self.staging_area):
for conexion in self.staging_area:
conexion.send("user_exist_sign-up".encode("utf-8"))
elif status_ok == "invalid_nickname":
if bool(self.staging_area):
for conexion in self.staging_area:
conexion.send("invalid_nickname".encode("utf-8"))
elif status_ok == "user_exist_log-in":
if bool(self.staging_area):
for conexion in self.staging_area:
conexion.send("user_exist_log-in".encode("utf-8"))
elif status_ok == "not_found":
if bool(self.staging_area):
for conexion in self.staging_area:
conexion.send("not_found".encode("utf-8"))
else:
# si retorna una tupla (obj_usuario, id), entonces este se pasa por el else
data_decode = pickle.loads(status_ok)
# si el id es igual a sign-up, se redireccionara para que inicie sesion
if data_decode[1] == "sign_up":
# solo se agrega el obj_usuario
self.clientes_registrados.append((data_decode[0]))
if bool(self.staging_area):
for conexion in self.staging_area:
conexion.send("log-in_go".encode("utf-8"))
else:
# si el id es igual a log-in, se redireccionara para que inicie el chat
if bool(self.staging_area):
for conexion in self.staging_area:
conexion.send("chat".encode("utf-8"))
# devolver un objeto usuario, con la ip que manda el mismo
for client in self.clientes_registrados:
obj_usuario = client[received_data[2]]
self.nickname = obj_usuario.usuario
self.clientes_conectados.append( {self.nickname:[conexion for conexion in self.staging_area if bool(self.staging_area)]} )
return self.nickname
# Se encriptan los datos de los usuarios y se guarda (confirma) dicho cambio, posteriormente se le envia una señal al cliente,
# para avisarle de que dicho usuario ya esta registrado y que solo debera iniciar seison, no registrarse, de no ser por este aviso,
# el usuario podria volver accidentalmente a registrarse, y eso no es lo que queremos, verdad?
self.encrypt_data_logging()
self.save_clients()
def encrypt_data_logging(self):
"""
Este metodo cifrara el archivo.pckl
"""
manager = symmetric_crypto.Transmitter()
key = manager.random_key()
msg = manager.extract_message("clientes.pckl")
# self.transmitted_message, es un atributo que se usara para el decrypt_data_logging(self,transmitted_message) metodo.
# cipher_text, solo guarda la copia del mensaje cifrado, sin adjuntos. Util para encriptar el fichero .pckl
self.transmitted_message,cipher_text = manager.encrypt(key,msg.encode("utf-8"))
with open("clientes.pckl",'wb') as file:
file.write(cipher_text)
def decrypt_data_logging(self,transmitted_message):
"""
Este metodo descifrara el archivo.pckl
"""
manager = symmetric_crypto.Receiver()
cipher_text, tag_mac, salt, nonce = manager.unpacking(transmitted_message)
plain_text = manager.decrypt(cipher_text, tag_mac, salt, nonce)
with open("clientes.pckl",'wb') as file:
file.write(plain_text)
def main(self):
"""
Este metodo solo reaccionara ante el input "salir", lo cual causara el cierre del servidor, y de la terminal.
"""
self.aceptar_conn()
while True:
opcion = input("\n-> ").strip().lower()
if opcion == "salir":
self.server.close()
sys.exit()
else:
pass
def aceptar_conn(self):
"""
Aceptaremos todas las conexiones entrantes, (maximo 10 coneixones) y a cada usuario que se conecte, le aplicaremos el metodo
setblocking = False, para que estos puedan ejecutar multiples tareas.
"""
while True:
try:
conn_cliente, data_cliente = self.server.accept()
conn_cliente.setblocking(False)
except Exception as e:
print(e)
else:
self.staging_area.append(conn_cliente)
def recv_messages(self):
"""
Si self.clientes_conectados es mayor que 0, es decir, si aun hay usuarios conectados, y ademas, si han enviado algun mensaje,
se recibiran los mensajes de cada uno de ellos, y se enviaran al metodo msg_to_whoami().
"""
while True:
# mientras hayan clientes en linea
if bool(self.clientes_conectados):
# A cada cliente conectado se le recibiran sus dichas peticiones (mensajes)
for cliente in self.clientes_conectados:
# se captura el nombre del usuario (whoami), al cual se le quiere hacer llegar el mensaje, y el mensaje_anidado,
# digo anidado porque ademas del mensaje, este tiene otros adjuntos que ayudan al cifrado del mismo.
whoami, msg = cliente.recv(4096)
whoami,msg = pickle.loads(whoami), pickle.loads(msg)
# verificar que haya un msg y un usuario existente
if cliente[whoami]:
# # ip_user = obj_usuario[whoami]
if msg:
self.msg_to_whoami(cliente, msg)
def msg_to_whoami(self,cliente,msg):
"""
El mensaje se envia a todos los usuarios conectados, menos al que envio el mensaje propiamente.
En caso de que halla un error, ese usuario sera sacado de la red, ya que este estaba inactivo y le
esta quitando el espacio a un usuario activo que desee entrar en el chat.
"""
for client in self.clientes_conectados:
# generamos una lista con las claves de todos los usuarios (nicknames), y su valor es (conn_objeto_socket)
keys = client.keys()
for key in keys:
# para cada clave en la lista, si alguna es igual al nickname parametro, se obtiene su objeto para poder enviarle el
# mensaje solo a dicha persona.
if key == cliente:
conn_obj = client[key]
conn_obj.send(pickle.dumps(msg))
# Si hay algun tipo de error, se removera el usuario del servidor para darle lugar a otros, ya que dicho usuario esta inactivo.
self.clientes_conectados.remove(client)
if __name__ == '__main__':
init = Servidor()
init.main()
My code was fine, until suddenly I get this error.
Error code:
Traceback (most recent call last):
File ".\servidor.py", line 355, in <module>
init.main()
File ".\servidor.py", line 274, in main
self.aceptar_conn()
File ".\servidor.py", line 295, in aceptar_conn
conn_cliente, data_cliente = self.server.accept()
File "C:\Users\EQUIPO\AppData\Local\Programs\Python\Python37-32\lib\socket.py", line 212, in accept
fd, addr = self._accept()
BlockingIOError: [WinError 10035] A non-blocking socket operation could not be completed immediately
Anyone know why this happens, and how can I fix it?
I searched the internet, but I really can't understand much about this error. Basically what I do is put the connections in a list and going through the list (bone in order of arrival), I am performing certain tasks with each connection, because the connection is lost once it is established (because the method is always waiting for connection and configure 10 in the queue, in the self.server.listen (10))
PDTA: If this information is of any use, I am doing a small private chat room, so I need that conn_cliente.setblocking (False)
BlockingIOError: [WinError 10035] A non-blocking socket operation could not be completed immediately
accept usually waits until a client is connected and only then returns successful. But you've explicitly set the socket to non-blocking which means it will not wait. Instead it will return the error you see if no client connected during (the short time) accept was called.
... so I need that conn_cliente.setblocking (False)
None of your code deals specifically with non-blocking sockets so I doubt that you actually need it.
On raspberry pi 3, with Raspberry camera v2 and using python 3.4.2,
sometimes, totally random, i get this error:
Exception in thread Thread-1:
Traceback (most recent call last):
File "/usr/lib/python3/dist-packages/picamera/camera.py", line 1189, in stop_recording
encoder = self._encoders[splitter_port]
KeyError: 1
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/usr/lib/python3.4/threading.py", line 920, in _bootstrap_inner
self.run()
File "/usr/lib/python3.4/threading.py", line 868, in run
self._target(*self._args, **self._kwargs)
File "/usr/lib/python3/dist-packages/gpiozero/mixins.py", line 496, in fill
self.parent._fire_events()
File "/usr/lib/python3/dist-packages/gpiozero/mixins.py", line 315, in _fire_events
self._fire_deactivated()
File "/usr/lib/python3/dist-packages/gpiozero/mixins.py", line 294, in _fire_deactivated
self.when_deactivated()
File "/home/pi/Programmi/Camera+sensoreX/cam_sens2.py", line 48, in stop_video
camera.stop_recording() #stoppiamo la registrazione
File "/usr/lib/python3/dist-packages/picamera/camera.py", line 1193, in stop_recording
'port %d' % splitter_port)
picamera.exc.PiCameraNotRecording: There is no recording in progress on port 1
But most of the time the program works.
How to solve this?
The Program:
import os #Importo modulo os per gestione dei percorsi dei file e cartelle
import cayenne.client #importo modulo cayenne.client per poter mandare dati a cayenne e quindi attivare le trigger e notifiche.
import datetime as date #Importo modulo datetime per la gestione del tempo abbreviandolo come "date"
import RPi.GPIO as gpio #Importo modulo GPIO per la gestione dei pin del gpio del raspberry abbreviandolo come "gpio"
#Se non si desidera utilizzare il nome della libreria tutte le volte che si richiama una funzione, è possibile importare anche i nomi delle funzioni direttamente: from [modulo] import [nome_funzione]
from picamera import PiCamera #Importo la funzione PiCamera dal modulo picamera
from time import sleep #Importo la funzione "sleep" dal modulo time
from gpiozero import MotionSensor #Importo la funzione MotionSensor dal modulo gpiozero
gpio.setwarnings(False) #Disabilito i messaggi di avvertimento del modulo GPIO
gpio.setmode(gpio.BCM) #Numerazione dei pin della GPIO di tipo BCM = numerazione pin secondo ai numeri dei pin SoC Broadcom, quindi usando i numeri dei pin "GPIO"
sensore = 4 #il sensore di movimento sarà collegato al pin 7 della GPIO (4 BCM)
gpio.setup(sensore, gpio.IN) #pin 7 impostato come input
camera = PiCamera() #help?
sensor = MotionSensor(4) #help?
#camera.hflip = True #camera ad effetto specchio (flip orizzontale)
camera.resolution = (1280, 720) #impostiamo la risoluzione della registrazione, in HD 1280x720p (larghezza, altezza)
destinazione = '/home/pi/Registrazioni' #path (percorso) dove andremo a salvare i file di registrazione
cont_iniz = 3 #valore inizale del contatore (3 secondi), necessario per l'inizializzazione del sensore
durata_registrazione = 15 #secondi di registrazione
durata_tot = 0 #variabile usata tenere conto della durata della registrazione eseguita
#variabili globali, per utilizzare i valori letti all'interno di una funzione (conf_routine) nel main
tempo_uscita_letto = 0
tempo_entrata_letto = 0 #tempo per entrare in casa e chiudere il programma
#Credenziali di autenticazione di Cayenne, possono essere ottenuti dalla dashboard di Cayenne.
MQTT_USERNAME = "private_info"
MQTT_PASSWORD = "private_info"
MQTT_CLIENT_ID = "private_info"
#inizializzazione della connessione con Cayenne MyDevices
client = cayenne.client.CayenneMQTTClient()
client.begin(MQTT_USERNAME, MQTT_PASSWORD, MQTT_CLIENT_ID)
#definiamo la funzione countdown che utilizziamo per impostare un tempo di registrazione in secondi e decrementarlo fino a 0, ma se nel frattempo il sensore rileva un altro movimento, il tempo viene reimpostato al valore inziale
def countdown(contatore):
global durata_tot #importiamo la variabile globale durata_tot
notifica_cayenne() #notifichiamo via sms e/o e-mail che è stato rilevato un movimento
while (contatore >= 0): #finché il valore del contatore (passato attraverso la variabile durata_registrazione) è maggiore o uguale a zero
print (contatore) #output a video del valore del contatore
durata_tot += 1 #incrementiamo il valore della durata totale, dato che ogni ciclo del while corrisponde a 1 secondo
contatore -= 1 #decrementiamo il contatore
if gpio.input(sensore): #se riceviamo un input dal sensore sulla GPIO (quindi il sensore rileva un movimento)...
contatore = durata_registrazione #il contatore viene resettato al valore iniziale (quindi al valore della variabile durata_registrazione)
sleep(1) #interrompiamo l'esecuzione del programma per un secondo
#definiamo la funzione registra_video che utilizziamo, a grandi linee, per iniziare la registrazione del video, darci un nome , definire la durata e cartella di destinazione
def registra_video():
#generariamo il nome univoco del video basato sull'ora e data attuale e creiamo un "percorso completo" aggiungendo il percorso (variabile destinazione) della cartella in cui vogliamo salvare il video
nome_file = os.path.join(destinazione, date.datetime.now().strftime("%d-%m-%Y_%H.%M.%S.h264"))
#iniziamo l'anteprima della registrazione in corso, impostiamo che non la vogliamo a schermo intero e quindi impostiamo le coordinate della finestra (x, y, larghezza, altezza)
camera.start_preview(fullscreen=False, window =(100, 200, 640, 480))
#iniziamo la registrazione specificando il nome del file (variabile nome_file) generato precedentemente
camera.start_recording(nome_file)
print ("Registrazione Iniziata") #output a video per notificarci che la registrazione è iniziata
countdown(durata_registrazione) #chiamiamo la funzione countdown, specificando la durata della registrazione
#definiamo la funzione stop_video, che stopperà il video una volta che il conto alla rovescia sarà finito
def stop_video():
global durata_tot, tempo_uscita_letto, tempo_entrata_letto #importiamo variabili globali necessarie
camera.stop_recording() #stoppiamo la registrazione
camera.stop_preview() #chiudiamo l'anteprima
durata_tot2 = float(durata_tot) + float(tempo_entrata_letto) #calcolo della durata della registrazione effettiva
print ("Registrazione Stoppata. Filmato di {} secondi".format(durata_tot2)) #output a video per notificarci che la registrazione è finita, mostrandoci la durata in secondi
#azzeriamo il valori che tengono conto della durata totale delle singole registrazioni, per conteggiare per la prossima registrazione
durata_tot = 0
durata_tot2 = 0
print("Aspettando movimenti...") #output a video per notificarci che il sistema è in attesa di movimenti
#definiamo la funzione conf_routine, che ci permette di impostare i tempi di uscita ed entrata in casa e salvarli in un file
def conf_routine():
global tempo_uscita_letto, tempo_entrata_letto #importiamo la variabili globali dichiarate tempo_uscita_letto e tempo_entrata_letto
nomefile = "conf.txt" #nome predefinito del file di configurazione
if os.path.isfile(nomefile) == False: #se il file contenente la configurazione non esiste...
print ("ATTENZIONE! Non è stato trovato alcun file di configurazione, verrà creato...\n") #notifica all'utente che non è presente il file di configurazione
file = open (nomefile,"w") #creiamo il file (in scrittura)
file.close() #chiudiamo il file
if os.stat(nomefile).st_size == False: #se il file esiste ma è vuoto (quindi non è stata effettuata la configurazione)...
file = open (nomefile,"a") #apriamo il file in append mode
tempo_uscita = input("Inserisci il tempo (in secondi) che impieghi solitamente ad uscire dall'abitazione una volta avviato il programma: ") #inseriamo il tempo che impieghiamo solitamente per uscire di casa
file.write(tempo_uscita + "\n") #scriviamo nella prima riga del file il tempo che impieghiamo ad uscire di casa
tempo_entrata = input("\nInserisci il tempo (in secondi) che impieghi solitamente ad entrare nell'abitazione una volta avviato il programma: ")
file.write(tempo_entrata) #scriviamo nella seconda riga del file il tempo che impieghiamo ad entrare in casa
print("\nATTENZIONE! Se vorrai cambiare i tempi impostati, dovrai aprire il file cambiare manualmente i secondi oppure, cancellare il file e riavviare il programma\n") #messaggio di avviso
file.close() #chiudiamo il file
file = open (nomefile, "r") #apriamo il file in sola lettura
riga = file.readlines() #leggiamo ogni riga del file e le mettiamo nella variabile riga
tempo_uscita_letto = riga[0] #mettiamo nella variabile globale tempo_uscita_letto il valore letto dalla prima riga del file
tempo_entrata_letto = riga[1] #mettiamo nella variabile globale tempo_entrata_letto il valore letto dalla seconda riga del file
file.close() #chiudiamo il file
print ("\nTempo per uscire: {} secondi\n".format(float(tempo_uscita_letto))) #output a video del valore letto
print ("Tempo per entrare: {} secondi\n".format(float(tempo_entrata_letto))) #output a video del valore letto
#definiamo la funzione che permette a cayenne di mandarci una notifica via mail e/o messaggio
#impostiamo un "trigger" dal sito di cayenne, che scatta quando il valore sul canale 2 diventa 1. Il trigger, una volta scattato, manda la notifica.
#mandiamo 0 e poi 1 perché il trigger perché scatta nel passaggio del dato da 0 a 1; quindi, se mandassimo solo 1, il trigger non scatterebbe mai.
def notifica_cayenne():
sleep (float(tempo_entrata_letto)) #ritardo necessario per disattivare il sistema dopo l'entrata in casa
client.virtualWrite(2, 0) #mandiamo un dato digitale (0) a cayenne, sul canale 2 [canale, valore]
client.virtualWrite(2, 1) #mandiamo un dato digitale (1) a cayenne, sul canale 2 [canale, valore]
############################################# main #############################################
def main():
global cont_iniz #importiamo la variabile globale dichiarata cont_iniz
print("Inizializzo il sensore, attendere {} secondi".format(cont_iniz)) #output a video per notificarci che inizialmente dobbiamo attendere 3 secondi per permettere al sensore di inizializzarsi
#semplice conto alla rovesca in base al valore di cont_iniz || aspettiamo 3 secondi, necessari per inizializzare il sensore.
while (cont_iniz >= 0):
print (cont_iniz)
cont_iniz -= 1
sleep(1)
conf_routine() #esecuzione delle routine di configurazione, dove eventualmente viene creato il file e ci vengono salvati (e poi letti) il tempo di entrata ed uscita
sleep (float(tempo_uscita_letto)) #aspettiamo il tempo impostato prima di continuare ad eseguire il programma, dandoci tempo per uscire di casa, evitando di essere riconosciuti come intrusi
print("Aspettando movimenti...") #output a video per notificarci che il sistema è in attesa di movimenti
while True: #ciclo infinito, il sistema aspetta input dal sensore, in base ad essi fa partire le funzioni di inizio o interruzione della registrazione
client.loop() #connessione continua con Cayenne.
sensor.when_motion = registra_video #se viene rilevato dal sensore un movimento, parte? la funzione che inizia la registrazione del video (registra_video)
sensor.when_no_motion = stop_video #se non viene rilevato dal sensore nessun movimento, parte? la funzione che stoppa la registrazione del video (stop_video)
if __name__ == "__main__": #main
main()
Thanks in advance.
P.s: if you want to help me comment the instruction, obviously in English, I would appreciate it. I mean the instruction followed by: #help?