#!/usr/bin/env python #-*- coding: iso8859-15 -*- ########################################################## # FILE_PESYR v1.0 # ########################################################## # Autor: Juan Miguel Taboada Godoy # # Fecha: Szczecin, 28 de Julio de 2006 # # Descripción: Cargador de datos de fichero de PESYR # # Versión: 2006071900 # # # # Codigo fuente bajo licencia GNU/GPL # # Centrologic (Computational Logistic Center) # # http://www.centrologic.com - info@centrologic.com # ########################################################## # Librerías necesarias {{{1 import gzip import fcntl from FILTER import coma2point from DATE import timenormal from HERENCIA import BASE from INTERFACES import READABLE,LockError from MATH_BIN import hextobin # }}}1 # Funciones generales {{{1 # Funcion para obtener el listado de palabras de una cadena {{{2 def palabras (cadena): cad='' trozos=[] for caracter in cadena: if caracter=='!': trozos.append(cad) cad='' elif (caracter=='\n') or (caracter=='\r'): cad=cad else: cad=cad+caracter trozos.append(cad) cad='' return trozos #}}}2 # }}}1 # ### FILE_PESYR ### ################################## ## \internal ## FILE_PESYR: Lector de ficheros con formato PESYR ## \version 19/07/2006 1600 Malaga class FILE_PESYR(BASE,READABLE): # Constructor {{{1 def __init__(self): # Cargo las acciones del padre BASE.__init__(self,None,"FILE_PESYR") # Inicializo el contador de elementos self.__elemento_actual=0 # Inicializo la frecuencia interna self.__frecuencia=None # Inicializo la compresion self.__compress=False # Inicializa a None el mantener bloqueo self.__keeplock=None # Creo la lista vacía self.__lista=[] # }}}1 # Destructor {{{1 ## Destructor ## \param - self def __del__(self): # Close the file if is locked with keeplock self.close() # }}}1 # Devuelve si el fichero esta comprimido o no {{{1 ## Devuelve si el fichero esta comprimido o no ## \param self - def compress(self): return self.__compress # }}}1 # Frecuencia de compresion interna {{{1 ## Frecuencia de compresion interna ## \param self - ## \param value Valor de la frecuencia de compresion interna (opcional) def frecuencia(self,value=None): if (value==None): return self.__frecuencia else: self.__frecuencia=value # }}}1 # Añade un elemento a la lista {{{1 ## \internal ## Inserta un elemento en la lista de datos ## \param self - ## \param id ID de la senal ## \param date Fecha y hora ## \param value Valor contenido ## \return True si lo ha insertado, False si no lo ha insertado def __add(self,id,date,value): # Comprueba la condicción de carga if (value!=""): # Añade el elemento a la lista self.__lista.append((id,date,value)) # Devuelve que si lo añadió return True else: # Devuelve que no lo añadió return False # }}}1 # Carga el fichero de datos ordenadamente {{{1 ## \internal ## Carga el fichero de datos ordenadamente en la memoria ## \param self - ## \param fichero Fichero a leer ## \param flock nolock:No bloquear, wait:esperar a que se libere el fichero, lock:bloquear o fallar (Por defecto: nolock) ## \param keeplock Indica si mantener el bloqueo despues del load (Por defecto: False) def load(self,fichero,flock="nolock",keeplock=False): self.debug("Cargando el fichero %s" % (fichero)) # Revisa si la extension del fichero es gz if (fichero.split(".")[-1]=="gz"): # En tal caso abro el fichero con el modulo gzip file=gzip.open(fichero,"r") # Bloqueo el acceso al fichero si necesario if (flock=="wait"): fcntl.flock(file.fileno(), fcntl.LOCK_EX) elif (flock=="lock"): try: fcntl.flock(file.fileno(), fcntl.LOCK_EX|fcntl.LOCK_NB) except IOError,error: raise LockError,error # Recuerdo que está comprimido self.__compress=True else: # Si es un fichero normal lo abro normalmente file=open(fichero,"r") # Bloqueo el acceso al fichero si necesario if (flock=="wait"): fcntl.flock(file.fileno(), fcntl.LOCK_EX) elif (flock=="lock"): try: fcntl.flock(file.fileno(), fcntl.LOCK_EX|fcntl.LOCK_NB) except IOError,error: raise LockError,error # Recuerdo que no está comprimido self.__compress=False # Etiqueta 1 self.debug("Leyendo etiqueta 1") file.readline() # Cabeceras self.debug("Cabeceras") # medio= file.readline() # telefono= file.readline() # producto= producto=file.readline().split("=")[1][0:2] # montaje= file.readline() # serie= seriebig=file.readline()[0:-1].split("=")[1] serie=seriebig[0] if (producto=="IA" and serie=="4"): modelotelemando="l3" elif (producto=="IB" and serie=="5"): modelotelemando="l6" else: raise IOError,"Fichero corrupto, el producto (%s) y el indice (%s) del numero de serie (%s) no coinciden." % (producto,serie,seriebig) # version= file.readline() # servicio= file.readline() # Etiqueta 2 self.debug("Leyendo etiqueta 2") file.readline() # Proceso el fichero {{{2 self.debug("Procesando el fichero") contenido=file.readlines() for linea in contenido: # Inicializo los valores ea_med=[] ea_min=[] ea_max=[] ec=[] # Separo cada línea s=palabras(linea) # Compruebo que tiene el número de palabras esperadas (Añadir tamaños aquí implica reconocerlos en la recogida de registros mas abajo) if ((len(s)==40) or (len(s)==41) or (len(s)==5) or (len(s)==73) or (len(s)==74)): # Debug # Recojo los datos genéricos {{{3 #tipo=s[0] # Codigo de estado fechaSalvaje=s[2] # Fecha salvaje # Adapto la fecha al formato requerido por la Base de Datos {{{4 # Traduzco la Feche Salvaje a TIMENORMAL fecha=timenormal(fechaSalvaje) # Recorto la fecha para separar fecha y hora # longitud=len(fecha) lista=[] cad='' for caracter in fecha: if (caracter==' '): lista.append(cad) cad='' elif (caracter=='\n') or (caracter=='\r'): cad=cad else: cad=cad+caracter lista.append(cad) cad='' # Separo las variables fecha=lista[0] hora=lista[1] # }}}4 # }}}3 # Recojo el resto de registros {{{3 if ((len(s)==40) or (len(s)==41) or (len(s)==73) or (len(s)==74)): # Recojo los datos de los registros tipo largo {{{4 # Estado de las entradas digitales if (s[3]!=""): binario_ed=hextobin(s[3]) if (modelotelemando=="l6"): indexini=8 else: indexini=0 for i in range(indexini,16): self.__add("ed:%s" % (i),(fecha,hora),binario_ed[-i-1]) # Estado de las entradas analógicas if (s[4]!=""): binario_ea=hextobin(s[4]) for i in range(0,8): self.__add("ea:%s" % (i),(fecha,hora),binario_ea[-i-1]) # Estado de las salidas de los relés if (s[5]!=""): binario_sd=hextobin(s[5]) for i in range(0,8): self.__add("sd:%s" % (i),(fecha,hora),binario_sd[-i-1]) # Estado de bits especiales if (s[6]!=""): binario_be=hextobin(s[6]) for i in range(0,8): self.__add("be:%s" % (i),(fecha,hora),binario_be[-i-1]) ea_med.append(s[7]) # Entrada analógica 0 [Media del periodo] ea_min.append(s[8]) # Entrada analógica 0 [Mínimo del periodo] ea_max.append(s[9]) # Entrada analógica 0 [Máximo del periodo] ea_med.append(s[10]) # Entrada analógica 1 [Media del periodo] ea_min.append(s[11]) # Entrada analógica 1 [Mínimo del periodo] ea_max.append(s[12]) # Entrada analógica 1 [Máximo del periodo] ea_med.append(s[13]) # Entrada analógica 2 [Media del periodo] ea_min.append(s[14]) # Entrada analógica 2 [Mínimo del periodo] ea_max.append(s[15]) # Entrada analógica 2 [Máximo del periodo] ea_med.append(s[16]) # Entrada analógica 3 [Media del periodo] ea_min.append(s[17]) # Entrada analógica 3 [Mínimo del periodo] ea_max.append(s[18]) # Entrada analógica 3 [Máximo del periodo] ea_med.append(s[19]) # Entrada analógica 4 [Media del periodo] ea_min.append(s[20]) # Entrada analógica 4 [Mínimo del periodo] ea_max.append(s[21]) # Entrada analógica 4 [Máximo del periodo] ea_med.append(s[22]) # Entrada analógica 5 [Media del periodo] ea_min.append(s[23]) # Entrada analógica 5 [Mínimo del periodo] ea_max.append(s[24]) # Entrada analógica 5 [Máximo del periodo] ea_med.append(s[25]) # Entrada analógica 6 [Media del periodo] ea_min.append(s[26]) # Entrada analógica 6 [Mínimo del periodo] ea_max.append(s[27]) # Entrada analógica 6 [Máximo del periodo] ea_med.append(s[28]) # Entrada analógica 7 [Media del periodo] ea_min.append(s[29]) # Entrada analógica 7 [Mínimo del periodo] ea_max.append(s[30]) # Entrada analógica 7 [Máximo del periodo] ec.append(s[31]) # Valor de conteo 0 ec.append(s[32]) # Valor de conteo 1 ec.append(s[33]) # Valor de conteo 2 ec.append(s[34]) # Valor de conteo 3 ec.append(s[35]) # Valor de conteo 4 ec.append(s[36]) # Valor de conteo 5 ec.append(s[37]) # Valor de conteo 6 ec.append(s[38]) # Valor de conteo 7 self.__add("cobertura",(fecha,hora),s[39]) # Cobertura GSM if (len(s)==41): self.__add("extra",(fecha,hora),s[40]) # Bits EXTRAs # }}}4 # Reajusto los valores {{{4 # MEDIA {{{5 for i in range(len(ea_med)): if (ea_med[i]==""): ea_med[i]="NULL" # MEDIA else: ea_med[i]=coma2point(ea_med[i]) # Intercambia , por . en Media # }}}5 # MAXIMO {{{5 for i in range(len(ea_max)): if (ea_max[i]==""): ea_max[i]="NULL" # MAXIMO else: ea_max[i]=coma2point(ea_max[i]) # Intercambia , por . en Maximo # }}}5 # MINIMO {{{5 for i in range(len(ea_min)): if (ea_min[i]==""): ea_min[i]="NULL" # MINIMO else: ea_min[i]=coma2point(ea_min[i]) # Intercambia , por . en Mínimo # }}}5 # CONTEO {{{5 for i in range(len(ec)): if ec[i]=="": ec[i]="NULL" # CONTEO # }}}5 # }}}4 # Añado los registros {{{4 for i in range(len(ea_med)): self.__add("eamed:%d" % (i),(fecha,hora),ea_med[i]) for i in range(len(ea_min)): self.__add("eamin:%d" % (i),(fecha,hora),ea_min[i]) for i in range(len(ea_max)): self.__add("eamax:%d" % (i),(fecha,hora),ea_max[i]) for i in range(len(ec)): self.__add("ec:%d" % (i),(fecha,hora),ec[i]) # }}}4 elif (len(s)==5): # Recojo los registros cortos (eventos) {{{4 self.__add("cobertura",(fecha,hora),s[4]) # Cobertura GSM # }}}4 # }}}3 else: # El número de palabras es incorrecto, la línea no se usaraá self.debug("Cadena incorrecta en el fichero '%s', se rechaza por tener longitud no reconocida (%s elementos): %s" % (fichero,len(s),linea)) # }}}2 # Ordeno los resultados por fecha (La clase principal lo hace por si sola) #self.__lista.sort(lambda x,y:x[1]