2 # -*- coding: iso-8859-1 -*-
3 # vim: set expandtab tabstop=4 shiftwidth=4 :
4 #----------------------------------------------------------------------------
6 #----------------------------------------------------------------------------
7 # This file is part of weathemulator.
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)
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
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 #----------------------------------------------------------------------------
33 class Sensor(Synchronizable, threading.Thread):
35 valorActual = SyncProp("Valor actualmente medido por el sensor")
37 def __init__(self, sigma, periodo):
38 threading.Thread.__init__(self)
39 self.rnd = random.Random()
41 self.periodo = periodo
42 self.mu = self.initMu()
43 self.valorActual = self.getValor()
46 raise NotImplementedError # Abstracto
49 "Simula la medición del dispositivo físico."
50 self.mu = self.rnd.gauss(self.mu, self.sigma)
54 #TODO Alguna forma de pausarlo
56 # Hacer algún signal al monitor de los sensores
57 self.valorActual = self.getValor()
58 print self.valorActual
59 time.sleep(self.periodo)
62 return self.valorActual
65 return "<%s valorActual=%s>" % (self.__class__.__name__, self)
68 class SensorDireccionViento(Sensor):
78 ROSA = (N, NE, E, SE, S, SO, O, NO)
81 Sensor.__init__(self, sigma=0.01, periodo=0.1)
83 def rndAngle(self, base, arco):
84 return (base + arco * (self.rnd.random() - 0.5)) % math.pi
87 return self.rndAngle(0, 2 * math.pi)
90 self.mu = self.rndAngle(self.mu, self.sigma)
91 return SensorDireccionViento.ROSA[int(round(self.mu))]
93 def direccionToString(direccion):
111 direccionToString = staticmethod(direccionToString)
114 return SensorDireccionViento.direccionToString(self.valorActual)
117 return "<%s dirección=%s valorActual=%d>" % (self.__class__.__name__,
118 self, self.valorActual)
121 class SensorCalibrado(Sensor):
123 valorBruto = SyncProp("Valor en bruto leido del dispositivo.")
124 valorBajo = SyncProp("Valor bajo de calibrado como tupla (valorBruto, " \
126 valorAlto = SyncProp("Valor alto de calibrado como tupla (valorBruto, " \
129 def __init__(self, valorBajo, valorAlto, sigma, periodo):
130 self.valorBajo = valorBajo
131 self.valorAlto = valorAlto
132 Sensor.__init__(self, sigma, periodo)
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
142 return "<%s valorActual=%s valorBruto=%f valorBajo=%s valorAlto=%s>" \
143 % (self.__class__.__name__, self, self.valorBruto, self.valorBajo,
147 class SensorHistorico(SensorCalibrado):
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)
155 "Simula la medición del dispositivo físico."
156 nuevo = SensorCalibrado.getValor(self)
157 hora = time.strftime("%c")
158 self.actualizarHistorial(nuevo, hora)
161 def actualizarHistorial(self, valor, hora):
162 self.historial.pop(0)
163 self.historial.append((valor, hora))
164 actualizarHistorial = synchronized('historialLock')(actualizarHistorial)
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)
172 getMin = synchronized('historialLock')(getMin)
175 maximo = (None, None)
176 for (valor, hora) in self.historial:
177 if valor >= maximo[0]:
178 maximo = (valor, hora)
180 getMax = synchronized('historialLock')(getMax)
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).")
188 class SensorHumedad(SensorHistorico):
191 SensorHistorico.__init__(self, (0.0, 0.0), (100.0, 100.0), 0.3, 300.0)
194 return self.rnd.gauss(70.0, 5.0)
197 class SensorVelocidadViento(SensorHistorico):
200 SensorHistorico.__init__(self, (0.0, 0.0), (100.0, 100.0), 0.1, 0.5)
203 return self.rnd.gauss(30.0, 8.0)
206 if __name__ == '__main__':
208 sensor = SensorDireccionViento()
209 sensor.setDaemon(True)
211 sensor2 = SensorHumedad()
212 sensor2.setDaemon(True)
214 sensor3 = SensorVelocidadViento()
215 sensor3.setDaemon(True)
218 sensor2.valorBajo = (0.0, -10.0)
219 sensor2.valorAlto = (100.0, 10.0)
220 print sensor3.valorMinimo, sensor3.valorMaximo
222 print sensor3.valorMinimo, sensor3.valorMaximo