]> git.llucax.com Git - z.facultad/75.59/weathemulator.git/blobdiff - src/sensor.py
Reemplaza staticmethod viejo con decorator.
[z.facultad/75.59/weathemulator.git] / src / sensor.py
index e677b6b3f905f76f54540e65659d7c091db59f69..a3993ede3a2577c91ec3cb064b97acbd5a787802 100644 (file)
@@ -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)
@@ -117,10 +131,165 @@ class SensorDireccionViento(Sensor):
             self, self.valorActual)
 
 
+class SensorCalibrado(Sensor):
+
+    valorBruto = SyncProp("Valor en bruto leido del dispositivo.")
+    valorBajo = SyncProp("Valor bajo de calibrado como tupla (valorBruto, " \
+        "valorCalibrado).")
+    valorAlto = SyncProp("Valor alto de calibrado como tupla (valorBruto, " \
+        "valorCalibrado).")
+
+    def __init__(self, valorBajo, valorAlto, sigma, periodo):
+        self.valorBajo = valorBajo
+        self.valorAlto = valorAlto
+        Sensor.__init__(self, sigma, periodo)
+
+    def getValor(self):
+        "Simula la medición del dispositivo físico."
+        self.valorBruto = self.mu = Sensor.getValor(self)
+        (x1, y1) = self.valorBajo
+        (x2, y2) = self.valorAlto
+        return (y2 - y1) / (x2 - x1) * (self.mu - x1) + y1
+
+    def __repr__(self):
+        return "<%s valorActual=%s valorBruto=%f valorBajo=%s valorAlto=%s>" \
+            % (self.__class__.__name__, self, self.valorBruto, self.valorBajo,
+                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()
+    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