]> git.llucax.com Git - z.facultad/75.59/weathemulator.git/blob - src/sensor.py
Utiliza decorators.
[z.facultad/75.59/weathemulator.git] / src / sensor.py
1 #!/usr/bin/env python
2 # -*- coding: iso-8859-1 -*-
3 # vim: set expandtab tabstop=4 shiftwidth=4 :
4 #----------------------------------------------------------------------------
5 #                               Weathemulator
6 #----------------------------------------------------------------------------
7 # This file is part of weathemulator.
8 #
9 # weathemulator is free software; you can redistribute it and/or modify it
10 # under the terms of the GNU General Public License as published by the Free
11 # Software Foundation; either version 2 of the License, or (at your option)
12 # any later version.
13 #
14 # weathemulator is distributed in the hope that it will be useful, but
15 # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16 # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17 # more details.
18 #
19 # You should have received a copy of the GNU General Public License along
20 # with weathemulator; if not, write to the Free Software Foundation, Inc., 59
21 # Temple Place, Suite 330, Boston, MA  02111-1307  USA
22 #----------------------------------------------------------------------------
23 # Creado:  sáb oct  1 18:26:32 ART 2005
24 # Autores: Leandro Lucarella <llucare@fi.uba.ar>
25 #----------------------------------------------------------------------------
26
27 import time
28 import math
29 import random
30 import threading
31 from sync import *
32
33 class Sensor(Synchronizable, threading.Thread):
34
35     valorActual = SyncProp("Valor actualmente medido por el sensor")
36
37     def __init__(self, sigma, periodo):
38         threading.Thread.__init__(self)
39         self.rnd = random.Random()
40         self.sigma = sigma
41         self.periodo = periodo
42         self.mu = self.initMu()
43         self.valorActual = self.getValor()
44
45     def initMu(self):
46         raise NotImplementedError # Abstracto
47
48     def getValor(self):
49         "Simula la medición del dispositivo físico."
50         self.mu = self.rnd.gauss(self.mu, self.sigma)
51         return self.mu
52
53     def run(self):
54         #TODO Alguna forma de pausarlo
55         while 1:
56             # Hacer algún signal al monitor de los sensores
57             self.valorActual = self.getValor()
58             print self.valorActual
59             time.sleep(self.periodo)
60
61     def __str__(self):
62         return self.valorActual
63
64     def __repr__(self):
65         return "<%s valorActual=%s>" % (self.__class__.__name__, self)
66
67
68 class SensorDireccionViento(Sensor):
69
70     N  = 0
71     NE = 1
72     E  = 2
73     SE = 3
74     S  = 4
75     SO = 5
76     O  = 6
77     NO = 7
78     ROSA = (N, NE, E, SE, S, SO, O, NO)
79
80     def __init__(self):
81         Sensor.__init__(self, sigma=0.01, periodo=0.1)
82
83     def rndAngle(self, base, arco):
84         return (base + arco * (self.rnd.random() - 0.5)) % math.pi
85
86     def initMu(self):
87         return self.rndAngle(0, 2 * math.pi)
88
89     def getValor(self):
90         self.mu = self.rndAngle(self.mu, self.sigma)
91         return SensorDireccionViento.ROSA[int(round(self.mu))]
92
93     def direccionToString(direccion):
94         if direccion == 0:
95             return "Norte"
96         if direccion == 1:
97             return "Noreste"
98         if direccion == 2:
99             return "Este"
100         if direccion == 3:
101             return "Sudeste"
102         if direccion == 4:
103             return "Sur"
104         if direccion == 5:
105             return "Sudoeste"
106         if direccion == 6:
107             return "Oeste"
108         if direccion == 7:
109             return "Noroeste"
110         raise NameError
111     direccionToString = staticmethod(direccionToString)
112
113     def __str__(self):
114         return SensorDireccionViento.direccionToString(self.valorActual)
115
116     def __repr__(self):
117         return "<%s dirección=%s valorActual=%d>" % (self.__class__.__name__,
118             self, self.valorActual)
119
120
121 class SensorCalibrado(Sensor):
122
123     valorBruto = SyncProp("Valor en bruto leido del dispositivo.")
124     valorBajo = SyncProp("Valor bajo de calibrado como tupla (valorBruto, " \
125         "valorCalibrado).")
126     valorAlto = SyncProp("Valor alto de calibrado como tupla (valorBruto, " \
127         "valorCalibrado).")
128
129     def __init__(self, valorBajo, valorAlto, sigma, periodo):
130         self.valorBajo = valorBajo
131         self.valorAlto = valorAlto
132         Sensor.__init__(self, sigma, periodo)
133
134     def getValor(self):
135         "Simula la medición del dispositivo físico."
136         self.valorBruto = self.mu = Sensor.getValor(self)
137         (x1, y1) = self.valorBajo
138         (x2, y2) = self.valorAlto
139         return (y2 - y1) / (x2 - x1) * (self.mu - x1) + y1
140
141     def __repr__(self):
142         return "<%s valorActual=%s valorBruto=%f valorBajo=%s valorAlto=%s>" \
143             % (self.__class__.__name__, self, self.valorBruto, self.valorBajo,
144                 self.valorAlto)
145
146
147 class SensorHistorico(SensorCalibrado):
148
149     def __init__(self, valorBajo, valorAlto, sigma, periodo):
150         # Listado de los valores de las últimas 24hs (inicializado con None)
151         self.historial = [(None, None) for i in xrange(int(24 * 60 * 60 / periodo))]
152         SensorCalibrado.__init__(self, valorBajo, valorAlto, sigma, periodo)
153
154     def getValor(self):
155         "Simula la medición del dispositivo físico."
156         nuevo = SensorCalibrado.getValor(self)
157         hora = time.strftime("%c")
158         self.actualizarHistorial(nuevo, hora)
159         return nuevo
160
161     def actualizarHistorial(self, valor, hora):
162         self.historial.pop(0)
163         self.historial.append((valor, hora))
164     actualizarHistorial = synchronized('historialLock')(actualizarHistorial)
165
166     def getMin(self):
167         minimo = (None, None)
168         for (valor, hora) in self.historial:
169             if minimo[0] is None or valor <= minimo[0]:
170                 minimo = (valor, hora)
171         return minimo
172     getMin = synchronized('historialLock')(getMin)
173
174     def getMax(self):
175         maximo = (None, None)
176         for (valor, hora) in self.historial:
177             if valor >= maximo[0]:
178                 maximo = (valor, hora)
179         return maximo
180     getMax = synchronized('historialLock')(getMax)
181
182     valorMinimo = property(getMin, doc="Mínimo de las últimas 24hs como " \
183         "tupla (minimo, hora).")
184     valorMaximo = property(getMax, doc="Máximo de las últimas 24hs como " \
185         "tupla (maximo, hora).")
186
187
188 class SensorHumedad(SensorHistorico):
189
190     def __init__(self):
191         SensorHistorico.__init__(self, (0.0, 0.0), (100.0, 100.0), 0.3, 300.0)
192
193     def initMu(self):
194         return self.rnd.gauss(70.0, 5.0)
195
196
197 class SensorVelocidadViento(SensorHistorico):
198
199     def __init__(self):
200         SensorHistorico.__init__(self, (0.0, 0.0), (100.0, 100.0), 0.1, 0.5)
201
202     def initMu(self):
203         return self.rnd.gauss(30.0, 8.0)
204
205
206 if __name__ == '__main__':
207     DEBUG = True
208     sensor = SensorDireccionViento()
209     sensor.setDaemon(True)
210     sensor.start()
211     sensor2 = SensorHumedad()
212     sensor2.setDaemon(True)
213     sensor2.start()
214     sensor3 = SensorVelocidadViento()
215     sensor3.setDaemon(True)
216     sensor3.start()
217     time.sleep(2)
218     sensor2.valorBajo = (0.0, -10.0)
219     sensor2.valorAlto = (100.0, 10.0)
220     print sensor3.valorMinimo, sensor3.valorMaximo
221     time.sleep(3)
222     print sensor3.valorMinimo, sensor3.valorMaximo
223