X-Git-Url: https://git.llucax.com/z.facultad/75.59/weathemulator.git/blobdiff_plain/82a461b46a90cbbf783ff4b7bb0a13c6bb3f5f7d..a0d37fb61af6505ae6f3c89b2a3a7f6ec4179058:/src/sensor.py?ds=sidebyside diff --git a/src/sensor.py b/src/sensor.py index f073387..a3993ed 100644 --- a/src/sensor.py +++ b/src/sensor.py @@ -30,6 +30,19 @@ import random import threading from sync import * + +__all__ = ('SensorDireccionViento', 'SensorHumedad', 'SensorPresion', + 'SensorTemperatura', 'SensorVelocidadViento') + + +DEBUG = False + + +def dprint(msg): + if DEBUG: + print msg + + class Sensor(Synchronizable, threading.Thread): valorActual = SyncProp("Valor actualmente medido por el sensor") @@ -51,11 +64,12 @@ class Sensor(Synchronizable, threading.Thread): return self.mu def run(self): + #TODO Alguna forma de pausarlo while 1: - # Hacer algún signal al monitor de los sensores - self.valorActual = self.getValor() - print self.valorActual + #TODO Hacer algún signal al monitor de los sensores time.sleep(self.periodo) + self.valorActual = self.getValor() + dprint(self) def __str__(self): return self.valorActual @@ -89,6 +103,7 @@ class SensorDireccionViento(Sensor): self.mu = self.rndAngle(self.mu, self.sigma) return SensorDireccionViento.ROSA[int(round(self.mu))] + @staticmethod def direccionToString(direccion): if direccion == 0: return "Norte" @@ -107,7 +122,6 @@ class SensorDireccionViento(Sensor): if direccion == 7: return "Noroeste" raise NameError - direccionToString = staticmethod(direccionToString) def __str__(self): return SensorDireccionViento.direccionToString(self.valorActual) @@ -143,17 +157,139 @@ class SensorCalibrado(Sensor): self.valorAlto) +class SensorHistorico(SensorCalibrado): + + def __init__(self, valorBajo, valorAlto, sigma, periodo): + # Listado de los valores de las últimas 24hs (inicializado con None) + self.historial = [(None, None) for i in xrange(int(24 * 60 * 60 / periodo))] + SensorCalibrado.__init__(self, valorBajo, valorAlto, sigma, periodo) + + def getValor(self): + "Simula la medición del dispositivo físico." + nuevo = SensorCalibrado.getValor(self) + hora = time.strftime("%c") + self.actualizarHistorial(nuevo, hora) + return nuevo + + def actualizarHistorial(self, valor, hora): + self.historial.pop(0) + self.historial.append((valor, hora)) + actualizarHistorial = synchronized('historialLock')(actualizarHistorial) + + def getMin(self): + minimo = (None, None) + for (valor, hora) in self.historial: + if minimo[0] is None or valor <= minimo[0]: + minimo = (valor, hora) + return minimo + getMin = synchronized('historialLock')(getMin) + + def getMax(self): + maximo = (None, None) + for (valor, hora) in self.historial: + if valor >= maximo[0]: + maximo = (valor, hora) + return maximo + getMax = synchronized('historialLock')(getMax) + + valorMinimo = property(getMin, doc="Mínimo de las últimas 24hs como " \ + "tupla (minimo, hora).") + valorMaximo = property(getMax, doc="Máximo de las últimas 24hs como " \ + "tupla (maximo, hora).") + + +class SensorHumedad(SensorHistorico): + + def __init__(self): + SensorHistorico.__init__(self, (0.0, 0.0), (100.0, 100.0), 0.3, 300.0) + + def initMu(self): + return self.rnd.gauss(70.0, 5.0) + + +class SensorVelocidadViento(SensorHistorico): + + def __init__(self): + SensorHistorico.__init__(self, (0.0, 0.0), (100.0, 100.0), 0.1, 0.5) + + def initMu(self): + return self.rnd.gauss(30.0, 8.0) + + +class SensorTendencia(SensorHistorico): + + def __init__(self, cantidadTendencia, valorBajo, valorAlto, sigma, periodo): + """cantidadTendencia es la cantidad de valores del historial a tomar al + calcular la tendencia.""" + # Listado de los valores de las últimas 24hs (inicializado con None) + self.cantidadTendencia = cantidadTendencia + SensorHistorico.__init__(self, valorBajo, valorAlto, sigma, periodo) + + def getValoresTendencia(self): + return [ + (x, y[0]) + for (x, y) in enumerate(self.historial[-self.cantidadTendencia:]) + if y[0] is not None + ] + getValoresTendencia = synchronized('historialLock')(getValoresTendencia) + + def getTendencia(self): + def sumatoria(valores): + suma = 0 + for i in valores: + suma += i + return suma + valores = self.getValoresTendencia() + suma_xy = sumatoria([x*y for (x, y) in valores]) + suma_x = sumatoria([x for (x, y) in valores]) + suma_y = sumatoria([y for (x, y) in valores]) + suma_x2 = sumatoria([x**2 for (x, y) in valores]) + n = len(valores) + pendiente = (n * suma_xy - suma_x * suma_y) / (n * suma_x2 - suma_x**2) + return math.atan(pendiente) * 2 / math.pi + + tendencia = property(getTendencia, doc="Tendencia de las últimas 24hs " \ + "(como valor de punto flotante entre 1 y -1).") + + +class SensorTemperatura(SensorTendencia): + + def __init__(self): + SensorTendencia.__init__(self, 10, (0.0, -20.0), (100.0, 80.0), 0.2, 300) + + def initMu(self): + return self.rnd.gauss(35.0, 5.0) + + +class SensorPresion(SensorTendencia): + + def __init__(self): + SensorTendencia.__init__(self, 10, (0.0, 1000.0), (100.0, 1048.0), 1, 300) + + def initMu(self): + return self.rnd.gauss(50.0, 5.0) + + if __name__ == '__main__': DEBUG = True sensor = SensorDireccionViento() sensor.setDaemon(True) sensor.start() - SensorCalibrado.initMu = lambda self: 10 - sensor2 = SensorCalibrado((0.0,0.0), (100.0,100.0), 0.2, 0.5) + sensor2 = SensorHumedad() sensor2.setDaemon(True) sensor2.start() + sensor3 = SensorVelocidadViento() + sensor3.setDaemon(True) + sensor3.start() + sensor4 = SensorTemperatura() + sensor4.setDaemon(True) + sensor4.periodo = 0.1 + sensor4.start() time.sleep(2) + print sensor4.tendencia sensor2.valorBajo = (0.0, -10.0) sensor2.valorAlto = (100.0, 10.0) + print sensor3.valorMinimo, sensor3.valorMaximo time.sleep(3) + print sensor3.valorMinimo, sensor3.valorMaximo