##// END OF EJS Templates
Update others.py
Armando123x -
r248:b0ab8791da6b
parent child
Show More
@@ -1,2019 +1,2019
1 import gc
1 import gc
2 import os
2 import os
3 import io
3 import io
4 import cv2
4 import cv2
5 import json
5 import json
6 import pytz
6 import pytz
7 import busio
7 import busio
8 import board
8 import board
9 import gzip
9 import gzip
10 import random
10 import random
11 import numpy
11 import numpy
12 import base64
12 import base64
13 import requests
13 import requests
14 import traceback
14 import traceback
15 import subprocess
15 import subprocess
16 import adafruit_ina219
16 import adafruit_ina219
17 import RPi.GPIO as GPIO
17 import RPi.GPIO as GPIO
18 import adafruit_lidarlite
18 import adafruit_lidarlite
19 import paho.mqtt.client as mqtt
19 import paho.mqtt.client as mqtt
20 import urllib.request
20 import urllib.request
21
21
22 from functools import wraps
22 from functools import wraps
23 from time import sleep
23 from time import sleep
24 from copy import deepcopy
24 from copy import deepcopy
25 from PIL import Image, ImageOps
25 from PIL import Image, ImageOps
26 from datetime import datetime,time
26 from datetime import datetime,time
27 from contextlib import contextmanager
27 from contextlib import contextmanager
28 from requests.auth import HTTPDigestAuth
28 from requests.auth import HTTPDigestAuth
29 from adafruit_ina219 import ADCResolution, BusVoltageRange
29 from adafruit_ina219 import ADCResolution, BusVoltageRange
30
30
31
31
32
32
33
33
34 #---------------------------------------#
34 #---------------------------------------#
35 def load_version():
35 def load_version():
36 try:
36 try:
37 model = None
37 model = None
38 with open('/proc/cpuinfo', 'r') as cpuinfo:
38 with open('/proc/cpuinfo', 'r') as cpuinfo:
39 for line in cpuinfo:
39 for line in cpuinfo:
40 if line.startswith('Hardware'):
40 if line.startswith('Hardware'):
41 hardware = line.split(':')[1].strip()
41 hardware = line.split(':')[1].strip()
42 elif line.startswith('Revision'):
42 elif line.startswith('Revision'):
43 revision = line.split(':')[1].strip()
43 revision = line.split(':')[1].strip()
44 elif line.startswith('Model'):
44 elif line.startswith('Model'):
45 model = line.split(':')[1].strip()
45 model = line.split(':')[1].strip()
46
46
47 return model
47 return model
48 except:
48 except:
49 return False
49 return False
50
50
51
51
52 model = load_version()
52 model = load_version()
53
53
54
54
55
55
56 if 'Raspberry Pi Zero' in model :
56 if 'Raspberry Pi Zero' in model :
57
57
58 '''
58 '''
59 Importamos la versión simple
59 Importamos la versión simple
60 '''
60 '''
61
61
62 TOTAL_BUFFER_VIDEO = 10
62 TOTAL_BUFFER_VIDEO = 10
63 import tflite_runtime.interpreter as lite
63 import tflite_runtime.interpreter as lite
64
64
65
65
66 elif 'Raspberry Pi 4' in model :
66 elif 'Raspberry Pi 4' in model :
67 '''
67 '''
68
68
69 Agregar más dispositivos si es necesario
69 Agregar más dispositivos si es necesario
70
70
71 '''
71 '''
72 TOTAL_BUFFER_VIDEO = 150
72 TOTAL_BUFFER_VIDEO = 150
73 ######################################################################
73 ######################################################################
74 ######################################################################
74 ######################################################################
75 ######################################################################
75 ######################################################################
76
76
77 # import tqdm
77 # import tqdm
78 # import keras
78 # import keras
79 # import random
79 # import random
80 # import einops
80 # import einops
81 # import pathlib
81 # import pathlib
82 # import itertools
82 # import itertools
83 # import collections
83 # import collections
84 # import tensorflow as tf
84 # import tensorflow as tf
85
85
86 TOTAL_BUFFER_VIDEO = 10
86 TOTAL_BUFFER_VIDEO = 10
87 import tflite_runtime.interpreter as lite
87 import tflite_runtime.interpreter as lite
88
88
89
89
90 ##################################################################################################################################################################################################################
90 ##################################################################################################################################################################################################################
91 ##################################################################################################################################################################################################################
91 ##################################################################################################################################################################################################################
92 ##################################################################################################################################################################################################################
92 ##################################################################################################################################################################################################################
93 ##################################################################################################################################################################################################################
93 ##################################################################################################################################################################################################################
94 ##################################################################################################################################################################################################################
94 ##################################################################################################################################################################################################################
95 ##################################################################################################################################################################################################################
95 ##################################################################################################################################################################################################################
96 #---------------------------------------#
96 #---------------------------------------#
97
97
98
98
99 #------------------------------------#
99 #------------------------------------#
100 i2c = busio.I2C(board.SCL, board.SDA)
100 i2c = busio.I2C(board.SCL, board.SDA)
101 #------------------------------------#
101 #------------------------------------#
102
102
103
103
104 @contextmanager
104 @contextmanager
105 def locked(lock):
105 def locked(lock):
106 lock.acquire()
106 lock.acquire()
107 try:
107 try:
108 yield
108 yield
109 finally:
109 finally:
110 lock.release()
110 lock.release()
111
111
112
112
113
113
114 def format_frames(frame, output_size):
114 def format_frames(frame, output_size):
115 """
115 """
116 Pad and resize an image from a video.
116 Pad and resize an image from a video.
117
117
118 Args:
118 Args:
119 frame: Image that needs to resized and padded.
119 frame: Image that needs to resized and padded.
120 output_size: Pixel size of the output frame image.
120 output_size: Pixel size of the output frame image.
121
121
122 Return:
122 Return:
123 Formatted frame with padding of specified output size.
123 Formatted frame with padding of specified output size.
124 """
124 """
125 ########frame = tf.image.convert_image_dtype(frame, tf.float32)
125 ########frame = tf.image.convert_image_dtype(frame, tf.float32)
126 ########frame = tf.image.resize_with_pad(frame, *output_size)
126 ########frame = tf.image.resize_with_pad(frame, *output_size)
127
127
128
128
129 frame = Image.fromarray(frame)
129 frame = Image.fromarray(frame)
130 frame = ImageOps.pad(frame,output_size,method=Image.Resampling.BILINEAR)
130 frame = ImageOps.pad(frame,output_size,method=Image.Resampling.BILINEAR)
131
131
132 frame = numpy.array(frame)/255.0
132 frame = numpy.array(frame)/255.0
133
133
134 return frame
134 return frame
135
135
136
136
137 def frames_from_video_file(video, n_frames, output_size = (224,224), frame_step = 15):
137 def frames_from_video_file(video, n_frames, output_size = (224,224), frame_step = 15):
138 """
138 """
139 Creates frames from each video file present for each category.
139 Creates frames from each video file present for each category.
140
140
141 Args:
141 Args:
142 video_path: File path to the video.
142 video_path: File path to the video.
143 n_frames: Number of frames to be created per video file.
143 n_frames: Number of frames to be created per video file.
144 output_size: Pixel size of the output frame image.
144 output_size: Pixel size of the output frame image.
145
145
146 Return:
146 Return:
147 An NumPy array of frames in the shape of (n_frames, height, width, channels).
147 An NumPy array of frames in the shape of (n_frames, height, width, channels).
148 """
148 """
149 # Read each video frame by frame
149 # Read each video frame by frame
150 result = []
150 result = []
151 #src = cv2.VideoCapture(str(video_path))
151 #src = cv2.VideoCapture(str(video_path))
152
152
153 src = video
153 src = video
154
154
155 video_length = len(src)
155 video_length = len(src)
156
156
157 need_length = 1 + (n_frames - 1) * frame_step
157 need_length = 1 + (n_frames - 1) * frame_step
158
158
159 if need_length > video_length:
159 if need_length > video_length:
160 start = 0
160 start = 0
161 else:
161 else:
162 max_start = video_length - need_length
162 max_start = video_length - need_length
163 start = random.randint(0, max_start + 1)
163 start = random.randint(0, max_start + 1)
164
164
165 # ret is a boolean indicating whether read was successful, frame is the image itself
165 # ret is a boolean indicating whether read was successful, frame is the image itself
166
166
167
167
168 for _ in range(n_frames):
168 for _ in range(n_frames):
169 frame = video[start]
169 frame = video[start]
170 frame = format_frames(frame, output_size)
170 frame = format_frames(frame, output_size)
171 result.append(frame)
171 result.append(frame)
172 start += frame_step
172 start += frame_step
173 if start >= video_length:
173 if start >= video_length:
174 break
174 break
175
175
176 result = numpy.array(result)[..., [2, 1, 0]]
176 result = numpy.array(result)[..., [2, 1, 0]]
177
177
178 result = result.reshape((1,result.shape[0],result.shape[1],result.shape[2],result.shape[3]))
178 result = result.reshape((1,result.shape[0],result.shape[1],result.shape[2],result.shape[3]))
179
179
180 return result
180 return result
181
181
182 def throttle(seconds):
182 def throttle(seconds):
183 def decorator(func):
183 def decorator(func):
184 last_called = {}
184 last_called = {}
185
185
186 @wraps(func)
186 @wraps(func)
187 def wrapper(self, *args, **kwargs):
187 def wrapper(self, *args, **kwargs):
188 current_time = datetime.now().timestamp()
188 current_time = datetime.now().timestamp()
189 if self not in last_called:
189 if self not in last_called:
190 last_called[self] = 0
190 last_called[self] = 0
191
191
192 if current_time - last_called[self] >= seconds:
192 if current_time - last_called[self] >= seconds:
193 last_called[self] = current_time
193 last_called[self] = current_time
194 return func(self, *args, **kwargs)
194 return func(self, *args, **kwargs)
195 else:
195 else:
196 return
196 return
197 return wrapper
197 return wrapper
198 return decorator
198 return decorator
199
199
200
200
201 class MyErrorForManage(Exception):
201 class MyErrorForManage(Exception):
202 def __init__(self, mensaje):
202 def __init__(self, mensaje):
203 super().__init__(mensaje)
203 super().__init__(mensaje)
204 self.mensaje = mensaje
204 self.mensaje = mensaje
205
205
206
206
207 class BytesEncoder(json.JSONEncoder):
207 class BytesEncoder(json.JSONEncoder):
208 def default(self, obj):
208 def default(self, obj):
209 if isinstance(obj, bytes):
209 if isinstance(obj, bytes):
210 return obj.decode('utf-8')
210 return obj.decode('utf-8')
211 return json.JSONEncoder.default(self, obj)
211 return json.JSONEncoder.default(self, obj)
212
212
213
213
214
214
215 def on_connect(client, userdata, flags, rc):
215 def on_connect(client, userdata, flags, rc):
216 print("Connected with result code " + str(rc))
216 print("Connected with result code " + str(rc))
217 print("UserData= " + str(userdata))
217 print("UserData= " + str(userdata))
218 print("flags= " + str(flags))
218 print("flags= " + str(flags))
219 print("")
219 print("")
220
220
221
221
222 class VarsJons(object):
222 class VarsJons(object):
223
223
224 id = None
224 id = None
225 location = None
225 location = None
226 data = None
226 data = None
227 debug = False
227 debug = False
228 type_weights = None
228 type_weights = None
229 store_data = False
229 store_data = False
230 latitude = None
230 latitude = None
231 longitude = None
231 longitude = None
232
232
233 vars_mqtt = None
233 vars_mqtt = None
234 vars_gpio = None
234 vars_gpio = None
235 vars = None
235 vars = None
236 weights = None
236 weights = None
237
237
238 def __init__(self):
238 def __init__(self):
239
239
240 self.path_file = '/others/vars.json'
240 self.path_file = '/others/vars.json'
241
241
242 self.load_auth_data()
242 self.load_auth_data()
243
243
244 def load_auth_data(self):
244 def load_auth_data(self):
245 try:
245 try:
246 with open(self.path_file, 'r') as file:
246 with open(self.path_file, 'r') as file:
247 self.data = json.load(file)
247 self.data = json.load(file)
248
248
249 except FileNotFoundError:
249 except FileNotFoundError:
250
250
251 raise FileNotFoundError("Archivo auth.json no encontrado en el directorio.")
251 raise FileNotFoundError("Archivo auth.json no encontrado en el directorio.")
252
252
253 else:
253 else:
254
254
255 self.vars = self.data["vars"]
255 self.vars = self.data["vars"]
256 self.vars_mqtt = self.data['mqtt']
256 self.vars_mqtt = self.data['mqtt']
257 self.vars_gpio = self.data['gpio']
257 self.vars_gpio = self.data['gpio']
258 self.vars_inference = self.data['inference']
258 self.vars_inference = self.data['inference']
259 self.debug = self.data['debug']
259 self.debug = self.data['debug']
260 self.latitude = self.data["latitude"]
260 self.latitude = self.data["latitude"]
261 self.longitude = self.data["longitude"]
261 self.longitude = self.data["longitude"]
262 self.weights = self.data['weights']
262 self.weights = self.data['weights']
263 self.id = self.data['id_device']
263 self.id = self.data['id_device']
264 self.vars_router = self.data.get("router",None)
264 self.vars_router = self.data.get("router",None)
265 self.location = self.data["location"]
265 self.location = self.data["location"]
266 self.router = self.data['router']
266 self.router = self.data['router']
267 self.type_weights = self.data['type_weights']
267 self.type_weights = self.data['type_weights']
268 self.store_data = self.data['store_data']
268 self.store_data = self.data['store_data']
269 self.river_width = self.data['river_width']
269 self.river_width = self.data['river_width']
270 self.camera = self.data['camera']
270 self.camera = self.data['camera']
271
271
272 def save_json(self):
272 def save_json(self):
273
273
274 try:
274 try:
275 self.data["vars"] = self.vars
275 self.data["vars"] = self.vars
276 #self.data["location"] = self.location
276 #self.data["location"] = self.location
277 self.data['mqtt'] = self.vars_mqtt
277 self.data['mqtt'] = self.vars_mqtt
278 self.data["gpio"] = self.vars_gpio
278 self.data["gpio"] = self.vars_gpio
279 self.data['inference'] = self.vars_inference
279 self.data['inference'] = self.vars_inference
280 #self.data['debug'] = self.debug
280 #self.data['debug'] = self.debug
281 self.data["weights"] = self.weights
281 self.data["weights"] = self.weights
282 self.data["id_device"] = self.id
282 self.data["id_device"] = self.id
283 #self.data["type_weights"] = self.type_weights
283 #self.data["type_weights"] = self.type_weights
284 self.data['camera'] = self.camera
284 self.data['camera'] = self.camera
285 self.data['router'] = self.router
285 self.data['router'] = self.router
286 except:
286 except:
287
287
288 pass
288 pass
289
289
290 else:
290 else:
291
291
292 try:
292 try:
293 with open(self.path_file,'w') as file:
293 with open(self.path_file,'w') as file:
294 json.dump(self.data,file,indent=7)
294 json.dump(self.data,file,indent=7)
295
295
296 except:
296 except:
297 pass
297 pass
298
298
299 def on_disconnect(client,userdata,rc):
299 def on_disconnect(client,userdata,rc):
300 def write_status(chain):
300 def write_status(chain):
301 now = datetime.now()
301 now = datetime.now()
302
302
303 formatted_date_time = now.strftime("%d/%m/%Y %H:%M:%S")
303 formatted_date_time = now.strftime("%d/%m/%Y %H:%M:%S")
304
304
305 filename = '/logs/log.txt'
305 filename = '/logs/log.txt'
306
306
307 if not os.path.isdir(os.path.dirname(filename)):
307 if not os.path.isdir(os.path.dirname(filename)):
308 os.makedirs(os.path.dirname(filename))
308 os.makedirs(os.path.dirname(filename))
309
309
310 chain = formatted_date_time + " " + chain
310 chain = formatted_date_time + " " + chain
311
311
312 try:
312 try:
313 with open(filename,'a') as file:
313 with open(filename,'a') as file:
314
314
315 file.write(chain + '\n')
315 file.write(chain + '\n')
316 except:
316 except:
317 pass
317 pass
318
318
319 return
319 return
320
320
321 write_status("Se ha desconectado el MQTT, recuperando conexión.")
321 write_status("Se ha desconectado el MQTT, recuperando conexión.")
322 sleep(0.5)
322 sleep(0.5)
323
323
324 if rc != 0:
324 if rc != 0:
325 count_attempts = 0
325 count_attempts = 0
326
326
327
327
328 while 1:
328 while 1:
329
329
330 if count_attempts > 10000:
330 if count_attempts > 10000:
331 count_attempts = 0
331 count_attempts = 0
332
332
333 try:
333 try:
334 client.reconnect()
334 client.reconnect()
335 except:
335 except:
336
336
337 error = traceback.format_exc()
337 error = traceback.format_exc()
338
338
339 write_status(f"Error al reconectar MQTT broker. Intento {count_attempts+1}. Copia del error: {error}")
339 write_status(f"Error al reconectar MQTT broker. Intento {count_attempts+1}. Copia del error: {error}")
340
340
341 count_attempts +=1
341 count_attempts +=1
342
342
343 time.sleep(5)
343 time.sleep(5)
344
344
345
345
346 else:
346 else:
347 write_status(f"Broker MQTT reconectado con exito.")
347 write_status(f"Broker MQTT reconectado con exito.")
348 return
348 return
349
349
350 MAX_NUMBER_SENSORS = 4
350 MAX_NUMBER_SENSORS = 4
351
351
352 class estimator(object):
352 class estimator(object):
353 '''
353 '''
354 Clase que permite estimar si hay un evento de huayco o lahar
354 Clase que permite estimar si hay un evento de huayco o lahar
355 Solo conserva los ultimos valores
355 Solo conserva los ultimos valores
356 '''
356 '''
357
357
358 timestamp_alert = 0
358 timestamp_alert = 0
359 flag_load_weights = False
359 flag_load_weights = False
360
360
361 _dataOut = None
361 _dataOut = None
362 _image = None
362 _image = None
363 _share = 10
363 _share = 10
364 _video = None
364 _video = None
365
365
366 _string_status = None
366 _string_status = None
367
367
368 activate = False
368 activate = False
369 activate_count = 0
369 activate_count = 0
370
370
371 count_hb = 0
371 count_hb = 0
372 count_HFS = 0
372 count_HFS = 0
373 count_RCWL = 0
373 count_RCWL = 0
374 status_lidar = 0
374 status_lidar = 0
375
375
376 flag_internet = False
376 flag_internet = False
377
377
378 inference_value = None
378 inference_value = None
379
379
380 list_HB = numpy.empty(MAX_NUMBER_SENSORS,dtype=float)
380 list_HB = numpy.empty(MAX_NUMBER_SENSORS,dtype=float)
381 list_HB.fill(numpy.nan)
381 list_HB.fill(numpy.nan)
382
382
383 list_HFS = numpy.empty(MAX_NUMBER_SENSORS,dtype=float)
383 list_HFS = numpy.empty(MAX_NUMBER_SENSORS,dtype=float)
384 list_HFS.fill(numpy.nan)
384 list_HFS.fill(numpy.nan)
385
385
386 list_RCWL = numpy.empty(MAX_NUMBER_SENSORS,dtype=float)
386 list_RCWL = numpy.empty(MAX_NUMBER_SENSORS,dtype=float)
387 list_RCWL.fill(numpy.nan)
387 list_RCWL.fill(numpy.nan)
388 timestamp = None
388 timestamp = None
389
389
390 #Para inferencia por imagen
390 #Para inferencia por imagen
391 TH_UMBRAL = 0.8
391 TH_UMBRAL = 0.8
392
392
393 values_dict = {'photo':{'0':'no_huayco','1':'huayco','10':'Camera Not Working'},
393 values_dict = {'photo':{'0':'no_huayco','1':'huayco','10':'Camera Not Working'},
394 'video':{'1':'huayco','0':'no_huayco','10':'Camera Not Working'},
394 'video':{'1':'huayco','0':'no_huayco','10':'Camera Not Working'},
395 'server':{'1':'huayco','0':'no_huayco','10':'Camera Not Working'}}
395 'server':{'1':'huayco','0':'no_huayco','10':'Camera Not Working'}}
396
396
397 def __init__(self,obj):
397 def __init__(self,obj):
398
398
399 self.obj_vars = obj
399 self.obj_vars = obj
400 self.id = self.obj_vars.id
400 self.id = self.obj_vars.id
401 self.path_save_json = obj.vars.get("path_save",os.path.join(os.getcwd(),'data'))
401 self.path_save_json = obj.vars.get("path_save",os.path.join(os.getcwd(),'data'))
402 self.weights = obj.weights.get(obj.type_weights,None)
402 self.weights = obj.get(obj.type_weights,None)
403
403
404 self.vars_mqtt = self.obj_vars.vars_mqtt
404 self.vars_mqtt = self.obj_vars.vars_mqtt
405
405
406 self.vars_inference = self.obj_vars.vars_inference
406 self.vars_inference = self.obj_vars.vars_inference
407 self.inference_mode = self.vars_inference.get("inference_mode",None)
407 self.inference_mode = self.vars_inference.get("inference_mode",None)
408
408
409 if self.weights is None:
409 if self.weights is None:
410 self.write_status("[ERROR] El atributo weights no puede ser None en el objeto Estimator. Porfavor, asegure de configurar correctamente la variable.")
410 self.write_status("[ERROR] El atributo weights no puede ser None en el objeto Estimator. Porfavor, asegure de configurar correctamente la variable.")
411 raise AttributeError("El atributo weights no puede ser None en el objeto Estimator. Porfavor, asegure de configurar correctamente la variable.")
411 raise AttributeError("El atributo weights no puede ser None en el objeto Estimator. Porfavor, asegure de configurar correctamente la variable.")
412
412
413
413
414 def reset_values(self):
414 def reset_values(self):
415
415
416
416
417 self.list_HFS.fill(numpy.nan)
417 self.list_HFS.fill(numpy.nan)
418 self.list_RCWL.fill(numpy.nan)
418 self.list_RCWL.fill(numpy.nan)
419 self.list_HB.fill(numpy.nan)
419 self.list_HB.fill(numpy.nan)
420
420
421 self.count_hb = 0
421 self.count_hb = 0
422 self.count_HFS = 0
422 self.count_HFS = 0
423 self.count_RCWL = 0
423 self.count_RCWL = 0
424
424
425 gc.collect()
425 gc.collect()
426
426
427 @property
427 @property
428 def video(self):
428 def video(self):
429 return self._video
429 return self._video
430
430
431 @property
431 @property
432 def share(self):
432 def share(self):
433 return self._share
433 return self._share
434
434
435 @property
435 @property
436 def dataOut(self):
436 def dataOut(self):
437 return self._dataOut
437 return self._dataOut
438
438
439 @property
439 @property
440 def image(self):
440 def image(self):
441 return self._image
441 return self._image
442
442
443 @property
443 @property
444 def string_status(self):
444 def string_status(self):
445 tmp = self.values_dict[self.inference_mode]
445 tmp = self.values_dict[self.inference_mode]
446
446
447 if self._share > 0.5 and self._share<= 2:
447 if self._share > 0.5 and self._share<= 2:
448
448
449 self._string_status = tmp['1']
449 self._string_status = tmp['1']
450 elif self._share <= 0.5:
450 elif self._share <= 0.5:
451
451
452 self._string_status = tmp['0']
452 self._string_status = tmp['0']
453 else:
453 else:
454
454
455 self._string_status = tmp['10']
455 self._string_status = tmp['10']
456
456
457
457
458 return self._string_status
458 return self._string_status
459
459
460 @image.setter
460 @image.setter
461 def image(self,value):
461 def image(self,value):
462
462
463 self._image = deepcopy(value['image'])
463 self._image = deepcopy(value['image'])
464 self.timestamp = deepcopy(value['timestamp'])
464 self.timestamp = deepcopy(value['timestamp'])
465
465
466 @video.setter
466 @video.setter
467 def video(self,value):
467 def video(self,value):
468 self._video = deepcopy(value['video'])
468 self._video = deepcopy(value['video'])
469 self.timestamp = deepcopy(value['timestamp'])
469 self.timestamp = deepcopy(value['timestamp'])
470
470
471
471
472
472
473 @share.setter
473 @share.setter
474 def share(self,value):
474 def share(self,value):
475
475
476 self._share = value
476 self._share = value
477
477
478 if self._share>=0.1 and self._share <5 :
478 if self._share>=0.1 and self._share <5 :
479 self._share = value
479 self._share = value
480 else:
480 else:
481 self._share = 0
481 self._share = 0
482
482
483
483
484 #------------- Realizamos la ponderación -----------------
484 #------------- Realizamos la ponderación -----------------
485 count = 0
485 count = 0
486
486
487 tmp_count = round(self.weights['camara']*self._share,2)
487 tmp_count = round(self.weights['camara']*self._share,2)
488
488
489 if tmp_count>1.1:
489 if tmp_count>1.1:
490 tmp_count = 0
490 tmp_count = 0
491
491
492 count = tmp_count + count
492 count = tmp_count + count
493
493
494 tmp = numpy.nanmean(self.list_HFS)
494 tmp = numpy.nanmean(self.list_HFS)
495
495
496 if numpy.isnan(tmp):
496 if numpy.isnan(tmp):
497 tmp = 0
497 tmp = 0
498 if tmp>1:
498 if tmp>1:
499 tmp = 0
499 tmp = 0
500
500
501 count += self.weights['HFS']*tmp
501 count += self.weights['HFS']*tmp
502
502
503 if numpy.isnan(self.status_lidar):
503 if numpy.isnan(self.status_lidar):
504 self.status_lidar = 0
504 self.status_lidar = 0
505
505
506 if self.status_lidar>1:
506 if self.status_lidar>1:
507 self.status_lidar = 1
507 self.status_lidar = 1
508
508
509 count += self.weights['LIDAR']*(self.status_lidar)
509 count += self.weights['LIDAR']*(self.status_lidar)
510
510
511 tmp = numpy.nanmean(self.list_HB)
511 tmp = numpy.nanmean(self.list_HB)
512
512
513 if numpy.isnan(tmp):
513 if numpy.isnan(tmp):
514 tmp = 0
514 tmp = 0
515
515
516 if tmp>1:
516 if tmp>1:
517 tmp = 0
517 tmp = 0
518 count += self.weights['HB100']*tmp
518 count += self.weights['HB100']*tmp
519
519
520 if count>0.7:
520 if count>0.7:
521
521
522 self.activate = True
522 self.activate = True
523 self.activate_count = count
523 self.activate_count = count
524 self.__send_alert_mqtt()
524 self.__send_alert_mqtt()
525
525
526 else:
526 else:
527
527
528 self.activate = False
528 self.activate = False
529 self.activate_count = count
529 self.activate_count = count
530
530
531
531
532
532
533
533
534 def __send_alert_mqtt(self,):
534 def __send_alert_mqtt(self,):
535
535
536 now = datetime.now().timestamp()
536 now = datetime.now().timestamp()
537
537
538
538
539 if (now - self.timestamp_alert > 60 ):
539 if (now - self.timestamp_alert > 60 ):
540
540
541 try:
541 try:
542 #Para no generar repetibilidad de las alertas
542 #Para no generar repetibilidad de las alertas
543 #Se enviará alertas cada minuto
543 #Se enviará alertas cada minuto
544
544
545 CLIENT_MQTT = str(self.id + "_ALERT")
545 CLIENT_MQTT = str(self.id + "_ALERT")
546 mqtt_user = self.vars_mqtt.get("mqtt_user")
546 mqtt_user = self.vars_mqtt.get("mqtt_user")
547 mqtt_pass = self.vars_mqtt.get("mqtt_pass")
547 mqtt_pass = self.vars_mqtt.get("mqtt_pass")
548 mqtt_broker = self.vars_mqtt.get("mqtt_broker")
548 mqtt_broker = self.vars_mqtt.get("mqtt_broker")
549 mqtt_port = self.vars_mqtt.get("mqtt_port")
549 mqtt_port = self.vars_mqtt.get("mqtt_port")
550
550
551 alert_topic = os.path.join(self.vars_mqtt.get("alert_topic","igp/roj/alert"),self.id)
551 alert_topic = os.path.join(self.vars_mqtt.get("alert_topic","igp/roj/alert"),self.id)
552
552
553
553
554 client = mqtt.Client(CLIENT_MQTT)
554 client = mqtt.Client(CLIENT_MQTT)
555
555
556 client.on_connect = on_connect
556 client.on_connect = on_connect
557 client.on_disconnect = on_disconnect
557 client.on_disconnect = on_disconnect
558
558
559 client.username_pw_set(mqtt_user,mqtt_pass)
559 client.username_pw_set(mqtt_user,mqtt_pass)
560 client.connect(mqtt_broker,mqtt_port,keepalive=300)
560 client.connect(mqtt_broker,mqtt_port,keepalive=300)
561
561
562 message = dict()
562 message = dict()
563
563
564 message['timestamp'] = datetime.now().timestamp()
564 message['timestamp'] = datetime.now().timestamp()
565 message['type'] = 'alert'
565 message['type'] = 'alert'
566 message['id'] = self.id
566 message['id'] = self.id
567
567
568 client.publish(alert_topic,json.dumps(message),qos=2)
568 client.publish(alert_topic,json.dumps(message),qos=2)
569
569
570 client.disconnect()
570 client.disconnect()
571
571
572 self.write_status("[ALERT] Datos de alerta se han enviado.")
572 self.write_status("[ALERT] Datos de alerta se han enviado.")
573
573
574
574
575 self.timestamp_alert = datetime.now().timestamp()
575 self.timestamp_alert = datetime.now().timestamp()
576
576
577 except:
577 except:
578
578
579 self.write_status(f"[ERROR] Error enviado alerta de activación al servidor MQTT: {traceback.format_exc()}")
579 self.write_status(f"[ERROR] Error enviado alerta de activación al servidor MQTT: {traceback.format_exc()}")
580
580
581
581
582
582
583
583
584 @dataOut.setter
584 @dataOut.setter
585 def dataOut(self,value):
585 def dataOut(self,value):
586
586
587 self._dataOut = value
587 self._dataOut = value
588
588
589 list_keys = self._dataOut.keys()
589 list_keys = self._dataOut.keys()
590
590
591 self.reset_values()
591 self.reset_values()
592
592
593 for key in list_keys:
593 for key in list_keys:
594
594
595 obj = self._dataOut[key]
595 obj = self._dataOut[key]
596
596
597 y = obj.get_latest()[1]
597 y = obj.get_latest()[1]
598
598
599 if 'sensor_HFS' in key:
599 if 'sensor_HFS' in key:
600 self.list_HFS[self.count_HFS%MAX_NUMBER_SENSORS] = y
600 self.list_HFS[self.count_HFS%MAX_NUMBER_SENSORS] = y
601
601
602 self.count_HFS +=1
602 self.count_HFS +=1
603
603
604 if 'sensor_HB' in key:
604 if 'sensor_HB' in key:
605 self.list_HB[self.count_hb%MAX_NUMBER_SENSORS] = y
605 self.list_HB[self.count_hb%MAX_NUMBER_SENSORS] = y
606 self.count_hb +=1
606 self.count_hb +=1
607
607
608 if 'sensor_RCWL' in key:
608 if 'sensor_RCWL' in key:
609 self.list_RCWL[self.count_RCWL%MAX_NUMBER_SENSORS] = y
609 self.list_RCWL[self.count_RCWL%MAX_NUMBER_SENSORS] = y
610
610
611 self.count_RCWL +=1
611 self.count_RCWL +=1
612
612
613 if 'lidar' in key:
613 if 'lidar' in key:
614
614
615 #Solo contamos con un lidar
615 #Solo contamos con un lidar
616 #Asi que nos es suficiente manejarlo como una variable
616 #Asi que nos es suficiente manejarlo como una variable
617
617
618 self.status_lidar = obj.activate
618 self.status_lidar = obj.activate
619
619
620 if self.status_lidar:
620 if self.status_lidar:
621 self.status_lidar = 1
621 self.status_lidar = 1
622 else:
622 else:
623 self.status_lidar = 0
623 self.status_lidar = 0
624
624
625 def __load_model_photo(self,path_model):
625 def __load_model_photo(self,path_model):
626
626
627 try:
627 try:
628 self.model_IA = lite.Interpreter(model_path=path_model)
628 self.model_IA = lite.Interpreter(model_path=path_model)
629 self.model_IA.allocate_tensors()
629 self.model_IA.allocate_tensors()
630
630
631 except Exception as e:
631 except Exception as e:
632 #Modelo IA no se pudo cargar
632 #Modelo IA no se pudo cargar
633 self.write_status(f"No se pudo cargar el modelo IA de foto. Error: {e}")
633 self.write_status(f"No se pudo cargar el modelo IA de foto. Error: {e}")
634 self.flag_load_weights = False
634 self.flag_load_weights = False
635
635
636 else:
636 else:
637 self.write_status("Modelo IA de photo cargado con éxito.")
637 self.write_status("Modelo IA de photo cargado con éxito.")
638 self.flag_load_weights = True
638 self.flag_load_weights = True
639
639
640 def __load_model_video(self,path):
640 def __load_model_video(self,path):
641
641
642 try:
642 try:
643
643
644
644
645 HEIGHT = 224
645 HEIGHT = 224
646 WIDTH = 224
646 WIDTH = 224
647 input_shape = (None, 10, HEIGHT, WIDTH, 3)
647 input_shape = (None, 10, HEIGHT, WIDTH, 3)
648 input = layers.Input(shape=(input_shape[1:]))
648 input = layers.Input(shape=(input_shape[1:]))
649 x = input
649 x = input
650
650
651 x = Conv2Plus1D(filters=16, kernel_size=(3, 7, 7), padding='same')(x)
651 x = Conv2Plus1D(filters=16, kernel_size=(3, 7, 7), padding='same')(x)
652 x = layers.BatchNormalization()(x)
652 x = layers.BatchNormalization()(x)
653 x = layers.ReLU()(x)
653 x = layers.ReLU()(x)
654 x = Dropout(0.1)(x)
654 x = Dropout(0.1)(x)
655 x = ResizeVideo(HEIGHT // 2, WIDTH // 2)(x)
655 x = ResizeVideo(HEIGHT // 2, WIDTH // 2)(x)
656
656
657 # Block 1
657 # Block 1
658 x = add_residual_block(x, 16, (3, 3, 3))
658 x = add_residual_block(x, 16, (3, 3, 3))
659 x = Dropout(0.1)(x)
659 x = Dropout(0.1)(x)
660 x = ResizeVideo(HEIGHT // 4, WIDTH // 4)(x)
660 x = ResizeVideo(HEIGHT // 4, WIDTH // 4)(x)
661
661
662 # Block 2
662 # Block 2
663 x = add_residual_block(x, 32, (3, 3, 3))
663 x = add_residual_block(x, 32, (3, 3, 3))
664 x = Dropout(0.1)(x)
664 x = Dropout(0.1)(x)
665 x = ResizeVideo(HEIGHT // 8, WIDTH // 8)(x)
665 x = ResizeVideo(HEIGHT // 8, WIDTH // 8)(x)
666
666
667 # Block 3
667 # Block 3
668 x = add_residual_block(x, 64, (3, 3, 3))
668 x = add_residual_block(x, 64, (3, 3, 3))
669 x = Dropout(0.1)(x)
669 x = Dropout(0.1)(x)
670 x = ResizeVideo(HEIGHT // 16, WIDTH // 16)(x)
670 x = ResizeVideo(HEIGHT // 16, WIDTH // 16)(x)
671
671
672 # Block 4
672 # Block 4
673 x = add_residual_block(x, 128, (3, 3, 3))
673 x = add_residual_block(x, 128, (3, 3, 3))
674 x = Dropout(0.1)(x)
674 x = Dropout(0.1)(x)
675 x = ResizeVideo(HEIGHT // 32, WIDTH // 32)(x)
675 x = ResizeVideo(HEIGHT // 32, WIDTH // 32)(x)
676
676
677
677
678 x = layers.AveragePooling3D((10,1,1))(x)
678 x = layers.AveragePooling3D((10,1,1))(x)
679 x = layers.Reshape((x.shape[1]*x.shape[2]*x.shape[3],-1))(x)
679 x = layers.Reshape((x.shape[1]*x.shape[2]*x.shape[3],-1))(x)
680 x = layers.LSTM(128,return_sequences=True)(x)
680 x = layers.LSTM(128,return_sequences=True)(x)
681 x = layers.Flatten()(x)
681 x = layers.Flatten()(x)
682 x = layers.Dense(512)(x)
682 x = layers.Dense(512)(x)
683 x = Dropout(0.1)(x)
683 x = Dropout(0.1)(x)
684 x = layers.Dense(256)(x)
684 x = layers.Dense(256)(x)
685
685
686 x = layers.Dense(1, activation='sigmoid')(x)
686 x = layers.Dense(1, activation='sigmoid')(x)
687
687
688
688
689 self.model_IA = keras.Model(input, x)
689 self.model_IA = keras.Model(input, x)
690
690
691 self.model_IA.load_weights(path)
691 self.model_IA.load_weights(path)
692
692
693 except:
693 except:
694
694
695 self.write_status(f"[ERROR] No se pudo cargar el modelo IA de video. Error: {traceback.format_exc()}")
695 self.write_status(f"[ERROR] No se pudo cargar el modelo IA de video. Error: {traceback.format_exc()}")
696 self.flag_load_weights = False
696 self.flag_load_weights = False
697
697
698 else:
698 else:
699
699
700 self.write_status("Modelo IA de video cargado con exito.")
700 self.write_status("Modelo IA de video cargado con exito.")
701 self.flag_load_weights = True
701 self.flag_load_weights = True
702
702
703
703
704
704
705 def load_weights(self):
705 def load_weights(self):
706 #Usar mobilnet debido a su reducido tamaño
706 #Usar mobilnet debido a su reducido tamaño
707 if self.inference_mode == 'photo':
707 if self.inference_mode == 'photo':
708 path_model = "/tools/models/mobilnet.tflite"
708 path_model = "/tools/models/mobilnet.tflite"
709
709
710 self.__load_model_photo(path_model)
710 self.__load_model_photo(path_model)
711
711
712 elif self.inference_mode == 'video':
712 elif self.inference_mode == 'video':
713 #Peso de videos
713 #Peso de videos
714 path_model = "/tools/models/weights_video.h5"
714 path_model = "/tools/models/weights_video.h5"
715
715
716 self.__load_model_video(path_model)
716 self.__load_model_video(path_model)
717
717
718 elif self.inference_mode == 'server':
718 elif self.inference_mode == 'server':
719 '''
719 '''
720 Aqui se realizará inferencias a la IP publica del OVS
720 Aqui se realizará inferencias a la IP publica del OVS
721 - La inferencia al OVS se realizará mientras se cuente con internet.
721 - La inferencia al OVS se realizará mientras se cuente con internet.
722 - Si no se cuenta con internet, se realizará inferencias con el pequeño modelo siempre y
722 - Si no se cuenta con internet, se realizará inferencias con el pequeño modelo siempre y
723 cuando sea una RPI 4 o superior.
723 cuando sea una RPI 4 o superior.
724 '''
724 '''
725
725
726 self.__model_less_complexity()
726 self.__model_less_complexity()
727
727
728
728
729
729
730 def __model_less_complexity(self,):
730 def __model_less_complexity(self,):
731
731
732 self.model_IA = True
732 self.model_IA = True
733
733
734 return
734 return
735
735
736
736
737
737
738 def check_internet(self,verbose=True):
738 def check_internet(self,verbose=True):
739
739
740 count = 0
740 count = 0
741
741
742 while 1:
742 while 1:
743
743
744 try:
744 try:
745 urllib.request.urlopen('http://www.google.com', timeout=1)
745 urllib.request.urlopen('http://www.google.com', timeout=1)
746
746
747 except:
747 except:
748 count +=1
748 count +=1
749 if (count ==3):
749 if (count ==3):
750 self.flag_internet = False
750 self.flag_internet = False
751 break
751 break
752
752
753 sleep(0.5)
753 sleep(0.5)
754 else:
754 else:
755 if verbose:
755 if verbose:
756 self.write_status("Se cuenta con conexión a internet.")
756 self.write_status("Se cuenta con conexión a internet.")
757
757
758 if self.debug:
758 if self.debug:
759 print("Se cuenta con conexión a internet")
759 print("Se cuenta con conexión a internet")
760
760
761 self.flag_internet = True
761 self.flag_internet = True
762
762
763 return
763 return
764
764
765 return
765 return
766
766
767
767
768 def get_inference(self,):
768 def get_inference(self,):
769
769
770
770
771 self.check_internet(False)
771 self.check_internet(False)
772
772
773 if self.inference_mode == 'video':
773 if self.inference_mode == 'video':
774
774
775 '''
775 '''
776 Se realiza predicción con el modelo de baja complejidad.
776 Se realiza predicción con el modelo de baja complejidad.
777 '''
777 '''
778
778
779 n_frames = 10
779 n_frames = 10
780
780
781 if self._video != None:
781 if self._video != None:
782
782
783 self.write_status("Realizando inferencia del modelo IA con video.")
783 self.write_status("Realizando inferencia del modelo IA con video.")
784
784
785 try:
785 try:
786
786
787 self._video = frames_from_video_file(self._video,n_frames)#result.reshape((1,result.shape[0],result.shape[1],result.shape[2],result.shape[3]))
787 self._video = frames_from_video_file(self._video,n_frames)#result.reshape((1,result.shape[0],result.shape[1],result.shape[2],result.shape[3]))
788 result = 1- self.model_IA.predict(self._video)[0][0]
788 result = 1- self.model_IA.predict(self._video)[0][0]
789
789
790 except:
790 except:
791
791
792 self.write_status(f"[ERROR] Error en la estimación del video. {traceback.format_exc()} ")
792 self.write_status(f"[ERROR] Error en la estimación del video. {traceback.format_exc()} ")
793 self._video = None
793 self._video = None
794
794
795 return None
795 return None
796 else:
796 else:
797
797
798 #------------------ Guardamos las inferencias en video ---------------------#
798 #------------------ Guardamos las inferencias en video ---------------------#
799 #############################################################################
799 #############################################################################
800
800
801 self.__save_inferences(result)
801 self.__save_inferences(result)
802 self._video = None
802 self._video = None
803 return result
803 return result
804
804
805 else:
805 else:
806
806
807 self.write_status("No se puede realizar la inferencia porque el batch es None.")
807 self.write_status("No se puede realizar la inferencia porque el batch es None.")
808
808
809 elif self.inference_mode == 'photo':
809 elif self.inference_mode == 'photo':
810
810
811 '''
811 '''
812 Se realiza inferencias mediante el modelo ML mediante foto.
812 Se realiza inferencias mediante el modelo ML mediante foto.
813 Se va a deprecar este modo debido a que no es suficiente una foto para la estimación
813 Se va a deprecar este modo debido a que no es suficiente una foto para la estimación
814 de huaycos.
814 de huaycos.
815 '''
815 '''
816
816
817 if self._image is not None:
817 if self._image is not None:
818 self.write_status("Realizando inferencia del modelo IA con photo.")
818 self.write_status("Realizando inferencia del modelo IA con photo.")
819
819
820 try:
820 try:
821 input_details = self.model_IA.get_input_details()
821 input_details = self.model_IA.get_input_details()
822 output_details = self.model_IA.get_output_details()
822 output_details = self.model_IA.get_output_details()
823
823
824 input_data = deepcopy(self._image)
824 input_data = deepcopy(self._image)
825
825
826 input_data = Image.fromarray(input_data)
826 input_data = Image.fromarray(input_data)
827
827
828 resize = input_data.resize((256,256))
828 resize = input_data.resize((256,256))
829
829
830 resize = numpy.array(resize)
830 resize = numpy.array(resize)
831
831
832 resize = numpy.expand_dims(resize,axis=0)
832 resize = numpy.expand_dims(resize,axis=0)
833
833
834 resize = resize.astype(numpy.float32)
834 resize = resize.astype(numpy.float32)
835
835
836 self.model_IA.set_tensor(input_details[0]['index'], resize)
836 self.model_IA.set_tensor(input_details[0]['index'], resize)
837 self.model_IA.invoke()
837 self.model_IA.invoke()
838
838
839 output_data = self.model_IA.get_tensor(output_details[0]['index'])[0][0]
839 output_data = self.model_IA.get_tensor(output_details[0]['index'])[0][0]
840
840
841 self.write_status(f"Inferencia realizado con exito. Valor de inferencia: {output_data}.")
841 self.write_status(f"Inferencia realizado con exito. Valor de inferencia: {output_data}.")
842
842
843 if output_data>=0.6:
843 if output_data>=0.6:
844 fpath = r'/data/inferences/img/01'
844 fpath = r'/data/inferences/img/01'
845 else:
845 else:
846 fpath = r'/data/inferences/img/00'
846 fpath = r'/data/inferences/img/00'
847
847
848 if not os.path.isdir:
848 if not os.path.isdir:
849 os.makedirs(fpath)
849 os.makedirs(fpath)
850
850
851 name = f'{self.timestamp}.png'
851 name = f'{self.timestamp}.png'
852
852
853 fpath = os.path.join(fpath,name)
853 fpath = os.path.join(fpath,name)
854 original_image = Image.fromarray(self._image)
854 original_image = Image.fromarray(self._image)
855 original_image.save(fpath)
855 original_image.save(fpath)
856
856
857
857
858
858
859 return output_data
859 return output_data
860
860
861 except:
861 except:
862 exc = traceback.format_exc()
862 exc = traceback.format_exc()
863
863
864 self.write_status(f"[ERROR] Error al realizar inferencia. Copia del error {exc}")
864 self.write_status(f"[ERROR] Error al realizar inferencia. Copia del error {exc}")
865
865
866 return None
866 return None
867
867
868 else:
868 else:
869 self.write_status("No se puede realizar la inferencia porque la imagen es None.")
869 self.write_status("No se puede realizar la inferencia porque la imagen es None.")
870
870
871
871
872 elif self.inference_mode == 'server':
872 elif self.inference_mode == 'server':
873
873
874 '''
874 '''
875 Se realizará la inferencia al servidor.
875 Se realizará la inferencia al servidor.
876 Solo se envía los datos comprimidos en formato json. El servidor se encargará
876 Solo se envía los datos comprimidos en formato json. El servidor se encargará
877 de darle formato a la imagen.
877 de darle formato a la imagen.
878 '''
878 '''
879
879
880 try:
880 try:
881 ip_inference = self.vars_inference.get("server_inference_ML","38.10.105.243")
881 ip_inference = self.vars_inference.get("server_inference_ML","38.10.105.243")
882 port_inference = self.vars_inference.get("port_inference_ML",7777)
882 port_inference = self.vars_inference.get("port_inference_ML",7777)
883
883
884
884
885 url = f"http://{ip_inference}:{port_inference}/predict"
885 url = f"http://{ip_inference}:{port_inference}/predict"
886
886
887
887
888 input_data = {'instances':base64.b64encode(self._video.getvalue()).decode('utf-8'),
888 input_data = {'instances':base64.b64encode(self._video.getvalue()).decode('utf-8'),
889 'id_user':str(self.id),
889 'id_user':str(self.id),
890 'request_format':True,
890 'request_format':True,
891 'shape':(360,640)}
891 'shape':(360,640)}
892
892
893 headers = {
893 headers = {
894 'Content-Type': 'application/json',
894 'Content-Type': 'application/json',
895 'Content-Encoding': 'gzip-B64',
895 'Content-Encoding': 'gzip-B64',
896 }
896 }
897 input_data = json.dumps(input_data)
897 input_data = json.dumps(input_data)
898
898
899 compress = io.BytesIO()
899 compress = io.BytesIO()
900
900
901 with gzip.GzipFile(fileobj=compress, mode='wb', compresslevel=9) as gz2:
901 with gzip.GzipFile(fileobj=compress, mode='wb', compresslevel=9) as gz2:
902 gz2.write(input_data.encode('utf-8'))
902 gz2.write(input_data.encode('utf-8'))
903
903
904
904
905 if self.flag_internet:
905 if self.flag_internet:
906
906
907 '''
907 '''
908 Se cuenta con internet para enviar el video al servidor a fin de realizar la inferencia.
908 Se cuenta con internet para enviar el video al servidor a fin de realizar la inferencia.
909 '''
909 '''
910
910
911 try:
911 try:
912 resp = requests.post(url,data=compress.getvalue(),headers=headers,timeout=15)
912 resp = requests.post(url,data=compress.getvalue(),headers=headers,timeout=15)
913 except:
913 except:
914 self._video = None
914 self._video = None
915 compress = None
915 compress = None
916 gc.collect()
916 gc.collect()
917 self.write_status(f"Error ocurrido al realizar la inferencia al servidor. {traceback.format_exc()}")
917 self.write_status(f"Error ocurrido al realizar la inferencia al servidor. {traceback.format_exc()}")
918
918
919 else:
919 else:
920
920
921 if resp.status_code == 200:
921 if resp.status_code == 200:
922 time1= datetime.now().timestamp()
922 time1= datetime.now().timestamp()
923
923
924 value_inference = round(1-resp.json()['predictions'][0][0],4) # El modelo actual requiere una resta de 1. Debido a que 0 es evento y 1 es no evento.
924 value_inference = round(1-resp.json()['predictions'][0][0],4) # El modelo actual requiere una resta de 1. Debido a que 0 es evento y 1 es no evento.
925
925
926 self.write_status(f"Inferencia al servidor realizado con exito. Valor de inferencia: {value_inference}.")
926 self.write_status(f"Inferencia al servidor realizado con exito. Valor de inferencia: {value_inference}.")
927 self.__save_inferences(value_inference)
927 self.__save_inferences(value_inference)
928 self._video = None
928 self._video = None
929 compress = None
929 compress = None
930 gc.collect()
930 gc.collect()
931
931
932 return value_inference
932 return value_inference
933 else:
933 else:
934
934
935
935
936 self.write_status(f"Se obtuvo otro codigo de respuesta al realizar inferencia al servidor. {resp.status_code}")
936 self.write_status(f"Se obtuvo otro codigo de respuesta al realizar inferencia al servidor. {resp.status_code}")
937 self._video = None
937 self._video = None
938 compress = None
938 compress = None
939 gc.collect()
939 gc.collect()
940
940
941 return None
941 return None
942
942
943 else:
943 else:
944
944
945 '''
945 '''
946 Probamos con el modelo de menor complejidad.
946 Probamos con el modelo de menor complejidad.
947 - No se encuentra desarrollado por el momento.
947 - No se encuentra desarrollado por el momento.
948 '''
948 '''
949
949
950 self.write_status("[IA] Metodo IA de menor complejidad no ha sido implementado para este modo.")
950 self.write_status("[IA] Metodo IA de menor complejidad no ha sido implementado para este modo.")
951
951
952 return None
952 return None
953
953
954 except:
954 except:
955
955
956 self.write_status(f"[Estimator] Existió un error al realizar la inferencia al servidor. Error:{traceback.format_exc()}")
956 self.write_status(f"[Estimator] Existió un error al realizar la inferencia al servidor. Error:{traceback.format_exc()}")
957 return NotImplementedError
957 return NotImplementedError
958 def __save_inferences(self,result):
958 def __save_inferences(self,result):
959
959
960 return
960 return
961 frame_width, frame_height = self._video.shape[1],self._video.shape[2]
961 frame_width, frame_height = self._video.shape[1],self._video.shape[2]
962
962
963 if result>=0.6:
963 if result>=0.6:
964 fpath = r'/data/inferences/video/01'
964 fpath = r'/data/inferences/video/01'
965 else:
965 else:
966 fpath = r'/data/inferences/video/00'
966 fpath = r'/data/inferences/video/00'
967
967
968 if not os.path.isdir(fpath):
968 if not os.path.isdir(fpath):
969 os.makedirs(fpath)
969 os.makedirs(fpath)
970 try:
970 try:
971 name = f'{self.timestamp}.mp4'
971 name = f'{self.timestamp}.mp4'
972 fpath = os.path.join(fpath,name)
972 fpath = os.path.join(fpath,name)
973 out = cv2.VideoWriter(fpath, cv2.VideoWriter_fourcc(*'mp4v'), 10, (frame_width, frame_height))
973 out = cv2.VideoWriter(fpath, cv2.VideoWriter_fourcc(*'mp4v'), 10, (frame_width, frame_height))
974
974
975 batch = self._video[0]
975 batch = self._video[0]
976
976
977 for frame in batch:
977 for frame in batch:
978 if frame.dtype != numpy.uint8:
978 if frame.dtype != numpy.uint8:
979 frame = frame.astype(numpy.uint8)
979 frame = frame.astype(numpy.uint8)
980 out.write(frame)
980 out.write(frame)
981
981
982 out.release()
982 out.release()
983 except:
983 except:
984
984
985 self.write_status(traceback.format_exc())
985 self.write_status(traceback.format_exc())
986
986
987
987
988 def write_status(self,chain):
988 def write_status(self,chain):
989
989
990 now = datetime.now()
990 now = datetime.now()
991
991
992 formatted_date_time = now.strftime("%d/%m/%Y %H:%M:%S")
992 formatted_date_time = now.strftime("%d/%m/%Y %H:%M:%S")
993
993
994 filename = '/logs/log.txt'
994 filename = '/logs/log.txt'
995
995
996 if not os.path.isdir(os.path.dirname(filename)):
996 if not os.path.isdir(os.path.dirname(filename)):
997 os.makedirs(os.path.dirname(filename))
997 os.makedirs(os.path.dirname(filename))
998
998
999 chain = formatted_date_time + " " + chain
999 chain = formatted_date_time + " " + chain
1000
1000
1001 try:
1001 try:
1002 with open(filename,'a') as file:
1002 with open(filename,'a') as file:
1003
1003
1004 file.write(chain + '\n')
1004 file.write(chain + '\n')
1005 except:
1005 except:
1006
1006
1007 if self.debug:
1007 if self.debug:
1008 print("Ocurrió un error al guardar datos logs.")
1008 print("Ocurrió un error al guardar datos logs.")
1009
1009
1010 return
1010 return
1011
1011
1012
1012
1013 def write_data(self,data):
1013 def write_data(self,data):
1014
1014
1015 now = datetime.now()
1015 now = datetime.now()
1016 formatted_date_time = now.strftime("%d/%m/%Y %H:%M:%S") + " |"
1016 formatted_date_time = now.strftime("%d/%m/%Y %H:%M:%S") + " |"
1017
1017
1018 try:
1018 try:
1019 name = 'data.txt'
1019 name = 'data.txt'
1020 filename = os.path.join(self.path_save_json,name)
1020 filename = os.path.join(self.path_save_json,name)
1021
1021
1022 with open(filename,'a') as file:
1022 with open(filename,'a') as file:
1023
1023
1024 file.write(formatted_date_time + str(json.dumps(data)) + '\n')
1024 file.write(formatted_date_time + str(json.dumps(data)) + '\n')
1025
1025
1026 except:
1026 except:
1027
1027
1028 if self.debug:
1028 if self.debug:
1029
1029
1030 print(f"Ocurrió un error al guardar los datos en el archivo {name}")
1030 print(f"Ocurrió un error al guardar los datos en el archivo {name}")
1031
1031
1032 self.write_status(f"[ERROR] Ocurrió un error al guardar los datos en el archivo {name}.")
1032 self.write_status(f"[ERROR] Ocurrió un error al guardar los datos en el archivo {name}.")
1033
1033
1034
1034
1035 def run(self,):
1035 def run(self,):
1036
1036
1037 '''
1037 '''
1038 -----------------------------------------------------------------------------------
1038 -----------------------------------------------------------------------------------
1039 Se ha obtenido un promedio de 0.303 segundos por inferencia para foto con RPI Zero.
1039 Se ha obtenido un promedio de 0.303 segundos por inferencia para foto con RPI Zero.
1040 Se ha obtenido un promedio de 2.4 segundos de inferencia para videos con RPI 4
1040 Se ha obtenido un promedio de 2.4 segundos de inferencia para videos con RPI 4
1041 -----------------------------------------------------------------------------------
1041 -----------------------------------------------------------------------------------
1042 '''
1042 '''
1043 value = None
1043 value = None
1044
1044
1045 if self.flag_load_weights or self.inference_mode == 'server':
1045 if self.flag_load_weights or self.inference_mode == 'server':
1046
1046
1047 #--------------- Realizamos la inferencia ---------------#
1047 #--------------- Realizamos la inferencia ---------------#
1048
1048
1049 self.inference_value = self.get_inference()
1049 self.inference_value = self.get_inference()
1050
1050
1051 #Por ahora solo copiamos los datos
1051 #Por ahora solo copiamos los datos
1052
1052
1053
1053
1054 self.write_data("Inferencia:" + str(self.inference_value) + " Timestamp: " + str(self.timestamp) )
1054 self.write_data("Inferencia:" + str(self.inference_value) + " Timestamp: " + str(self.timestamp) )
1055 self.write_status("Inferencia:" + str(self.inference_value) + " Timestamp: " + str(self.timestamp) )
1055 self.write_status("Inferencia:" + str(self.inference_value) + " Timestamp: " + str(self.timestamp) )
1056
1056
1057
1057
1058
1058
1059
1059
1060
1060
1061 class camera(object):
1061 class camera(object):
1062
1062
1063 data = None
1063 data = None
1064
1064
1065 flag = False
1065 flag = False
1066 activity = False
1066 activity = False
1067 _status = False
1067 _status = False
1068 url_rstp = None
1068 url_rstp = None
1069
1069
1070 camera_available = False
1070 camera_available = False
1071 camera_config = False
1071 camera_config = False
1072 brightness = False
1072 brightness = False
1073 __count_available = 0
1073 __count_available = 0
1074
1074
1075 __timestamp_time_available = 0
1075 __timestamp_time_available = 0
1076
1076
1077 flag_brightness = False
1077 flag_brightness = False
1078
1078
1079 def __check_if_available(self,):
1079 def __check_if_available(self,):
1080 '''
1080 '''
1081 Revisamos por ping si la cámara se encuentra disponible o no. Esto es para evitar menor tipo de errores.
1081 Revisamos por ping si la cámara se encuentra disponible o no. Esto es para evitar menor tipo de errores.
1082 '''
1082 '''
1083 try:
1083 try:
1084 result = subprocess.run(["ping", "-c", "1", self.camera_ip],
1084 result = subprocess.run(["ping", "-c", "1", self.camera_ip],
1085 stdout=subprocess.DEVNULL,
1085 stdout=subprocess.DEVNULL,
1086 stderr=subprocess.DEVNULL,
1086 stderr=subprocess.DEVNULL,
1087 timeout=2) # Dos segundos de timeout
1087 timeout=2) # Dos segundos de timeout
1088
1088
1089 if result.returncode == 0:
1089 if result.returncode == 0:
1090
1090
1091 self.__count_available = 0
1091 self.__count_available = 0
1092
1092
1093 if (datetime.now().timestamp() - self.__timestamp_time_available > 120):
1093 if (datetime.now().timestamp() - self.__timestamp_time_available > 120):
1094 self.write_status("La cámara se encuentra conectada a la red.")
1094 self.write_status("La cámara se encuentra conectada a la red.")
1095 self.__timestamp_time_available = datetime.now().timestamp()
1095 self.__timestamp_time_available = datetime.now().timestamp()
1096
1096
1097 self.camera_available = True
1097 self.camera_available = True
1098 else:
1098 else:
1099 self.camera_available = False
1099 self.camera_available = False
1100 self.__count_available +=1
1100 self.__count_available +=1
1101
1101
1102
1102
1103 if (datetime.now().timestamp() - self.__timestamp_time_available > 120):
1103 if (datetime.now().timestamp() - self.__timestamp_time_available > 120):
1104 self.write_status("No se encontró la cámara en la red.")
1104 self.write_status("No se encontró la cámara en la red.")
1105 self.__timestamp_time_available = datetime.now().timestamp()
1105 self.__timestamp_time_available = datetime.now().timestamp()
1106
1106
1107
1107
1108 except:
1108 except:
1109
1109
1110 self.write_status(f"Hubo un error al realizar el ping a la cámara: {traceback.format_exc()}")
1110 self.write_status(f"Hubo un error al realizar el ping a la cámara: {traceback.format_exc()}")
1111 self.camera_available = False
1111 self.camera_available = False
1112 self.__count_available +=1
1112 self.__count_available +=1
1113
1113
1114 else:
1114 else:
1115
1115
1116 if self.camera_available == True and self.camera_config == False:
1116 if self.camera_available == True and self.camera_config == False:
1117 self.__config() #La cámara se encuentra lista para realizar la configuración
1117 self.__config() #La cámara se encuentra lista para realizar la configuración
1118
1118
1119 finally:
1119 finally:
1120
1120
1121 if self.__count_available == 3:
1121 if self.__count_available == 3:
1122 self.__count_available = 0
1122 self.__count_available = 0
1123
1123
1124 if self.camera_config == True:
1124 if self.camera_config == True:
1125 self.camera_config = False
1125 self.camera_config = False
1126
1126
1127 self.write_status("Es necesario volver a configurar la cámara por desconexión.")
1127 self.write_status("Es necesario volver a configurar la cámara por desconexión.")
1128
1128
1129
1129
1130 def write_status(self,chain):
1130 def write_status(self,chain):
1131
1131
1132 now = datetime.now()
1132 now = datetime.now()
1133
1133
1134 formatted_date_time = now.strftime("%d/%m/%Y %H:%M:%S")
1134 formatted_date_time = now.strftime("%d/%m/%Y %H:%M:%S")
1135
1135
1136 filename = '/logs/log.txt'
1136 filename = '/logs/log.txt'
1137
1137
1138 chain = formatted_date_time + " |" + chain
1138 chain = formatted_date_time + " |" + chain
1139
1139
1140 if not os.path.isdir(os.path.dirname(filename)):
1140 if not os.path.isdir(os.path.dirname(filename)):
1141 os.makedirs(os.path.dirname(filename))
1141 os.makedirs(os.path.dirname(filename))
1142
1142
1143 try:
1143 try:
1144 with open(filename,'a') as file:
1144 with open(filename,'a') as file:
1145
1145
1146 file.write(chain + '\n')
1146 file.write(chain + '\n')
1147 except:
1147 except:
1148
1148
1149 if self.debug:
1149 if self.debug:
1150 print("Ocurrió un error al guardar datos logs.")
1150 print("Ocurrió un error al guardar datos logs.")
1151
1151
1152 return
1152 return
1153
1153
1154 def __init__(self,flag=False, pin= 26,obj=None):
1154 def __init__(self,flag=False, pin= 26,obj=None):
1155
1155
1156 '''
1156 '''
1157 Definiciones
1157 Definiciones
1158 ------------
1158 ------------
1159 flag -> Bandera que condiciona la adquisición de fotografías por la cámara. Permite decidir si se usa o no la cámara.
1159 flag -> Bandera que condiciona la adquisición de fotografías por la cámara. Permite decidir si se usa o no la cámara.
1160 pin -> Pin que controla el relé de alimentación hacia la cámara.
1160 pin -> Pin que controla el relé de alimentación hacia la cámara.
1161 camara always on -> Modo que permite capturar en cualquier estación del año, pero es condicionado por el flag.
1161 camara always on -> Modo que permite capturar en cualquier estación del año, pero es condicionado por el flag.
1162
1162
1163 08-08-24
1163 08-08-24
1164 --------
1164 --------
1165 Se agregan nuevas funciones para la camara HIKVISION usando ISAPI
1165 Se agregan nuevas funciones para la camara HIKVISION usando ISAPI
1166 '''
1166 '''
1167
1167
1168
1168
1169
1169
1170 self.flag = flag
1170 self.flag = flag
1171 self.pin = pin
1171 self.pin = pin
1172
1172
1173
1173
1174 self.debug = obj.debug
1174 self.debug = obj.debug
1175 self.vars = obj.vars
1175 self.vars = obj.vars
1176 self.vars_mqtt = obj.vars_mqtt
1176 self.vars_mqtt = obj.vars_mqtt
1177 self.store_data = obj.store_data
1177 self.store_data = obj.store_data
1178 self.vars_gpio = obj.vars_gpio
1178 self.vars_gpio = obj.vars_gpio
1179 self.camera_keys = obj.camera
1179 self.camera_keys = obj.camera
1180
1180
1181
1181
1182 self.camera_always_on = self.vars_gpio.get("camera_always_on",False)
1182 self.camera_always_on = self.vars_gpio.get("camera_always_on",False)
1183
1183
1184 self.camera_ip = self.camera_keys.get("ip")
1184 self.camera_ip = self.camera_keys.get("ip")
1185 self.username_camera = self.camera_keys.get("username")
1185 self.username_camera = self.camera_keys.get("username")
1186 self.password_camera = self.camera_keys.get("password")
1186 self.password_camera = self.camera_keys.get("password")
1187 self.port_camera = self.camera_keys.get("port")
1187 self.port_camera = self.camera_keys.get("port")
1188
1188
1189 self.__check_if_available()
1189 self.__check_if_available()
1190
1190
1191
1191
1192 def __config(self,):
1192 def __config(self,):
1193
1193
1194 self.__gen__rstp() # Generamos el link rstp
1194 self.__gen__rstp() # Generamos el link rstp
1195 self.__update_time() #Actualizamos la hora del sistema de la cámara
1195 self.__update_time() #Actualizamos la hora del sistema de la cámara
1196 self.__switch_mode_to_night() #Modificamos a modo noche de la cámara.
1196 self.__switch_mode_to_night() #Modificamos a modo noche de la cámara.
1197 self.__update_brightness(brightness=0) #Apagamos la luz de la cámara
1197 self.__update_brightness(brightness=0) #Apagamos la luz de la cámara
1198
1198
1199 self.camera_config = True
1199 self.camera_config = True
1200
1200
1201 def __update_time(self,):
1201 def __update_time(self,):
1202
1202
1203 if self.camera_ip != None:
1203 if self.camera_ip != None:
1204 url_supplement_light = f'http://{self.camera_ip}/ISAPI/System/time'
1204 url_supplement_light = f'http://{self.camera_ip}/ISAPI/System/time'
1205
1205
1206
1206
1207 now = datetime.now(pytz.utc).astimezone(pytz.timezone('Etc/GMT+5'))
1207 now = datetime.now(pytz.utc).astimezone(pytz.timezone('Etc/GMT+5'))
1208 hora_actual = now.strftime('%Y-%m-%dT%H:%M:%S')
1208 hora_actual = now.strftime('%Y-%m-%dT%H:%M:%S')
1209 zona_horaria = "EST5"
1209 zona_horaria = "EST5"
1210
1210
1211 xml_data = f"""<Time>
1211 xml_data = f"""<Time>
1212 <timeMode>manual</timeMode>
1212 <timeMode>manual</timeMode>
1213 <localTime>{hora_actual}</localTime>
1213 <localTime>{hora_actual}</localTime>
1214 <timeZone>{zona_horaria}</timeZone>
1214 <timeZone>{zona_horaria}</timeZone>
1215 </Time>"""
1215 </Time>"""
1216 try:
1216 try:
1217 response = requests.put(
1217 response = requests.put(
1218 url_supplement_light,
1218 url_supplement_light,
1219 data=xml_data,
1219 data=xml_data,
1220 headers={'Content-Type': 'application/xml'},
1220 headers={'Content-Type': 'application/xml'},
1221 auth=HTTPDigestAuth(self.username_camera, self.password_camera),
1221 auth=HTTPDigestAuth(self.username_camera, self.password_camera),
1222 timeout=5
1222 timeout=5
1223 )
1223 )
1224
1224
1225 if response.status_code == 200:
1225 if response.status_code == 200:
1226 print(f"Hora actualizada.")
1226 print(f"Hora actualizada.")
1227 else:
1227 else:
1228 raise RuntimeError(f"Error {response.status_code}: {response.text}")
1228 raise RuntimeError(f"Error {response.status_code}: {response.text}")
1229
1229
1230 except:
1230 except:
1231
1231
1232 self.write_status(f"[Camera] Error producido al actualizar la fecha. Error: {traceback.format_exc()}.")
1232 self.write_status(f"[Camera] Error producido al actualizar la fecha. Error: {traceback.format_exc()}.")
1233
1233
1234 else:
1234 else:
1235
1235
1236 self.write_status(f"[Camera] Fecha actualizada.")
1236 self.write_status(f"[Camera] Fecha actualizada.")
1237
1237
1238
1238
1239
1239
1240 def __gen__rstp(self):
1240 def __gen__rstp(self):
1241 self.url_rstp = f'rtsp://{self.username_camera}:{self.password_camera}@{self.camera_ip}:{self.port_camera}/streaming/channels/1'
1241 self.url_rstp = f'rtsp://{self.username_camera}:{self.password_camera}@{self.camera_ip}:{self.port_camera}/streaming/channels/1'
1242
1242
1243 def __update_brightness(self,brightness=100):
1243 def __update_brightness(self,brightness=100):
1244
1244
1245
1245
1246 if self.camera_ip != None:
1246 if self.camera_ip != None:
1247 url_supplement_light = f'http://{self.camera_ip}/ISAPI/Image/channels/1/supplementLight'
1247 url_supplement_light = f'http://{self.camera_ip}/ISAPI/Image/channels/1/supplementLight'
1248
1248
1249 xml_data = f'''
1249 xml_data = f'''
1250 <SupplementLight>
1250 <SupplementLight>
1251 <supplementLightMode>colorVuWhiteLight</supplementLightMode>
1251 <supplementLightMode>colorVuWhiteLight</supplementLightMode>
1252 <mixedLightBrightnessRegulatMode>manual</mixedLightBrightnessRegulatMode>
1252 <mixedLightBrightnessRegulatMode>manual</mixedLightBrightnessRegulatMode>
1253 <whiteLightBrightness>{brightness}</whiteLightBrightness>
1253 <whiteLightBrightness>{brightness}</whiteLightBrightness>
1254 </SupplementLight>
1254 </SupplementLight>
1255 '''
1255 '''
1256
1256
1257 try:
1257 try:
1258 response = requests.put(
1258 response = requests.put(
1259 url_supplement_light,
1259 url_supplement_light,
1260 data=xml_data,
1260 data=xml_data,
1261 headers={'Content-Type': 'application/xml'},
1261 headers={'Content-Type': 'application/xml'},
1262 auth=HTTPDigestAuth(self.username_camera, self.password_camera),
1262 auth=HTTPDigestAuth(self.username_camera, self.password_camera),
1263 timeout=7
1263 timeout=7
1264 )
1264 )
1265
1265
1266 if response.status_code == 200:
1266 if response.status_code == 200:
1267 print(f"Brillo ajustado a {brightness}%.")
1267 print(f"Brillo ajustado a {brightness}%.")
1268 else:
1268 else:
1269 raise RuntimeError(f"Error {response.status_code}: {response.text}")
1269 raise RuntimeError(f"Error {response.status_code}: {response.text}")
1270
1270
1271 except:
1271 except:
1272
1272
1273 self.write_status(f"[Camera] Error producido al actualizar el brillo. Error {traceback.format_exc()}.")
1273 self.write_status(f"[Camera] Error producido al actualizar el brillo. Error {traceback.format_exc()}.")
1274
1274
1275 else:
1275 else:
1276
1276
1277 self.write_status(f"[Camera] Brillo de luz actualizado a {brightness}.")
1277 self.write_status(f"[Camera] Brillo de luz actualizado a {brightness}.")
1278 if brightness >50:
1278 if brightness >50:
1279 sleep(3)
1279 sleep(3)
1280
1280
1281
1281
1282
1282
1283
1283
1284
1284
1285
1285
1286 def __switch_mode_to_night(self,):
1286 def __switch_mode_to_night(self,):
1287
1287
1288 '''
1288 '''
1289 En este modulo, se configura a la cámara para que pueda cambiar el modo switch a modo noche.
1289 En este modulo, se configura a la cámara para que pueda cambiar el modo switch a modo noche.
1290 '''
1290 '''
1291 xml_data = """
1291 xml_data = """
1292 <?xml version:"1.0" encoding="UTF-8"?>
1292 <?xml version:"1.0" encoding="UTF-8"?>
1293 <IrcutFilter>
1293 <IrcutFilter>
1294 <IrcutFilterType>night</IrcutFilterType>
1294 <IrcutFilterType>night</IrcutFilterType>
1295 </IrcutFilter>
1295 </IrcutFilter>
1296 """
1296 """
1297
1297
1298 headers ={'Content-Type': 'application/xml'}
1298 headers ={'Content-Type': 'application/xml'}
1299 url = f'http://{self.camera_ip}/ISAPI/Image/channels/1/ircutFilter'
1299 url = f'http://{self.camera_ip}/ISAPI/Image/channels/1/ircutFilter'
1300
1300
1301 username = self.username_camera
1301 username = self.username_camera
1302 password = self.password_camera
1302 password = self.password_camera
1303
1303
1304
1304
1305 if self.camera_ip != None:
1305 if self.camera_ip != None:
1306
1306
1307 try:
1307 try:
1308 response = requests.put(url, data=xml_data, auth=HTTPDigestAuth(username, password), headers=headers,timeout=7)
1308 response = requests.put(url, data=xml_data, auth=HTTPDigestAuth(username, password), headers=headers,timeout=7)
1309 except:
1309 except:
1310
1310
1311 self.write_status(f"[ERROR] Error al cambiar modo de la camara a noche. Error: {traceback.format_exc()}")
1311 self.write_status(f"[ERROR] Error al cambiar modo de la camara a noche. Error: {traceback.format_exc()}")
1312 else:
1312 else:
1313 if response.status_code == 200:
1313 if response.status_code == 200:
1314 self.write_status("[Camera] Modo ha sido cambiado a Noche.")
1314 self.write_status("[Camera] Modo ha sido cambiado a Noche.")
1315
1315
1316 else:
1316 else:
1317 self.write_status("[Camera] Error al cambiar a modo noche.")
1317 self.write_status("[Camera] Error al cambiar a modo noche.")
1318
1318
1319
1319
1320
1320
1321 def __on_camera(self,):
1321 def __on_camera(self,):
1322
1322
1323 GPIO.setmode(GPIO.BCM)
1323 GPIO.setmode(GPIO.BCM)
1324 GPIO.setwarnings(False)
1324 GPIO.setwarnings(False)
1325 GPIO.setup(self.pin,GPIO.OUT)
1325 GPIO.setup(self.pin,GPIO.OUT)
1326 GPIO.output(self.pin,GPIO.LOW)
1326 GPIO.output(self.pin,GPIO.LOW)
1327
1327
1328 self.activity = True
1328 self.activity = True
1329
1329
1330 def __off_camera(self,):
1330 def __off_camera(self,):
1331
1331
1332 GPIO.setmode(GPIO.BCM)
1332 GPIO.setmode(GPIO.BCM)
1333 GPIO.setwarnings(False)
1333 GPIO.setwarnings(False)
1334 GPIO.setup(self.pin,GPIO.OUT)
1334 GPIO.setup(self.pin,GPIO.OUT)
1335 GPIO.output(self.pin,GPIO.HIGH)
1335 GPIO.output(self.pin,GPIO.HIGH)
1336
1336
1337 self.activity = False
1337 self.activity = False
1338
1338
1339
1339
1340 def __is_night(self):
1340 def __is_night(self):
1341
1341
1342 '''
1342 '''
1343 Se establecen las condiciones para que tiempos sea declarado noche
1343 Se establecen las condiciones para que tiempos sea declarado noche
1344 '''
1344 '''
1345
1345
1346 now = datetime.now(pytz.utc).astimezone(pytz.timezone('Etc/GMT+5')).time()
1346 now = datetime.now(pytz.utc).astimezone(pytz.timezone('Etc/GMT+5')).time()
1347
1347
1348 flag = False
1348 flag = False
1349 flag = (time(9,0)<=now<=time(23,59)) or (time(0,0)<=now<=time(6,50))
1349 flag = (time(9,0)<=now<=time(23,59)) or (time(0,0)<=now<=time(6,50))
1350
1350
1351 return flag
1351 return flag
1352
1352
1353 @property
1353 @property
1354 def status(self):
1354 def status(self):
1355
1355
1356 if self.flag == False:
1356 if self.flag == False:
1357
1357
1358 self.__off_camera()
1358 self.__off_camera()
1359 return False
1359 return False
1360
1360
1361 if self.camera_always_on:
1361 if self.camera_always_on:
1362
1362
1363 '''La cámara siempre estará prendida'''
1363 '''La cámara siempre estará prendida'''
1364
1364
1365 self.__on_camera()
1365 self.__on_camera()
1366 self.__process_on()
1366 self.__process_on()
1367
1367
1368 return True
1368 return True
1369
1369
1370 #------ Establecemos UTC -5 ---------#
1370 #------ Establecemos UTC -5 ---------#
1371 utc_minus_5 = pytz.timezone('Etc/GMT+5')
1371 utc_minus_5 = pytz.timezone('Etc/GMT+5')
1372
1372
1373 now = datetime.now(pytz.utc).astimezone(utc_minus_5).time()
1373 now = datetime.now(pytz.utc).astimezone(utc_minus_5).time()
1374
1374
1375 '''
1375 '''
1376 Aqui establecemos criterío de activación de la cámara
1376 Aqui establecemos criterío de activación de la cámara
1377 -----------------------------------------------------
1377 -----------------------------------------------------
1378 - Por ejemplo, aqui se define que la cámara funciona entre las 6 am y 18pm
1378 - Por ejemplo, aqui se define que la cámara funciona entre las 6 am y 18pm
1379 de cada día. La activación y desactivación de la cámara será controlada mediante un relé.
1379 de cada día. La activación y desactivación de la cámara será controlada mediante un relé.
1380
1380
1381 - Se puede establecer otros criterios como activar la cámara durante ciertos
1381 - Se puede establecer otros criterios como activar la cámara durante ciertos
1382 periodos de meses por inactividad o menor radiación.
1382 periodos de meses por inactividad o menor radiación.
1383 '''
1383 '''
1384
1384
1385 #------------------- Criterio ----------------------------#
1385 #------------------- Criterio ----------------------------#
1386 # self._status = False
1386 # self._status = False
1387 # self._status = time(6, 00) <= now <= time(7, 10)
1387 # self._status = time(6, 00) <= now <= time(7, 10)
1388 # self._status = time(10, 00) <= now <= time(10, 10)
1388 # self._status = time(10, 00) <= now <= time(10, 10)
1389 # self._status = time(12, 00) <= now <= time(12, 10)
1389 # self._status = time(12, 00) <= now <= time(12, 10)
1390 # self._status = time(16, 00) <= now <= time(16, 10)
1390 # self._status = time(16, 00) <= now <= time(16, 10)
1391 # self._status = time(17, 30) <= now <= time(18,30)
1391 # self._status = time(17, 30) <= now <= time(18,30)
1392 # self._status = time(21, 00) <= now <= time(21,10)
1392 # self._status = time(21, 00) <= now <= time(21,10)
1393 # self._status = time(1, 00) <= now <= time(1,10)
1393 # self._status = time(1, 00) <= now <= time(1,10)
1394 # self._status = time(4, 00) <= now <= time(4,10)
1394 # self._status = time(4, 00) <= now <= time(4,10)
1395
1395
1396 self._status = True
1396 self._status = True
1397
1397
1398 #-------------------- Condiciones ------------------------#
1398 #-------------------- Condiciones ------------------------#
1399
1399
1400
1400
1401
1401
1402 if self._status ==True and self.pin != None and self.activity == False:
1402 if self._status ==True and self.pin != None and self.activity == False:
1403
1403
1404 #Prendemos la cámara del relé.
1404 #Prendemos la cámara del relé.
1405
1405
1406 self._status = True
1406 self._status = True
1407
1407
1408 self.__on_camera()
1408 self.__on_camera()
1409
1409
1410
1410
1411
1411
1412 self.write_status("[CAMERA] Se prendió la cámara.")
1412 self.write_status("[CAMERA] Se prendió la cámara.")
1413
1413
1414 elif self._status == False and self.pin != None and self.activity == True:
1414 elif self._status == False and self.pin != None and self.activity == True:
1415
1415
1416 # Operaciones para desactivar la salida del relé
1416 # Operaciones para desactivar la salida del relé
1417
1417
1418 self.__off_camera()
1418 self.__off_camera()
1419
1419
1420 self.write_status("[CAMERA] Se apagó la cámara.")
1420 self.write_status("[CAMERA] Se apagó la cámara.")
1421
1421
1422 ###############################################################
1422 ###############################################################
1423
1423
1424 self.__check_if_available()
1424 self.__check_if_available()
1425
1425
1426 self._status = self._status & self.camera_available
1426 self._status = self._status & self.camera_available
1427
1427
1428 return self._status
1428 return self._status
1429
1429
1430 def control_brightness(self,brightness=100):
1430 def control_brightness(self,brightness=100):
1431
1431
1432 try:
1432 try:
1433 flag_night = self.__is_night()
1433 flag_night = self.__is_night()
1434
1434
1435 if flag_night == True and brightness>0:
1435 if flag_night == True and brightness>0:
1436
1436
1437
1437
1438 #Realizamos el cambio de brillo
1438 #Realizamos el cambio de brillo
1439 self.brightness = True
1439 self.brightness = True
1440 self.__update_brightness(brightness=brightness)
1440 self.__update_brightness(brightness=brightness)
1441
1441
1442 elif brightness == 0:
1442 elif brightness == 0:
1443 self.brightness = False
1443 self.brightness = False
1444 self.__update_brightness(brightness=0)
1444 self.__update_brightness(brightness=0)
1445 except:
1445 except:
1446
1446
1447 self.write_status("[CAMERA_ERROR] Ocurrió un error al controlar el brillo de la camara.")
1447 self.write_status("[CAMERA_ERROR] Ocurrió un error al controlar el brillo de la camara.")
1448
1448
1449 return
1449 return
1450
1450
1451
1451
1452 def __process_on(self,):
1452 def __process_on(self,):
1453
1453
1454 '''
1454 '''
1455 Procesos que se ejecutan o validan cuando la cámara está prendida.
1455 Procesos que se ejecutan o validan cuando la cámara está prendida.
1456 '''
1456 '''
1457
1457
1458 flag_night = self.__is_night()
1458 flag_night = self.__is_night()
1459
1459
1460 if flag_night == True and self.flag_brightness == False:
1460 if flag_night == True and self.flag_brightness == False:
1461
1461
1462
1462
1463 self.flag_brightness = True
1463 self.flag_brightness = True
1464 self.__update_brightness(brightness=100)
1464 self.__update_brightness(brightness=100)
1465
1465
1466 if flag_night==False and self.flag_brightness == True:
1466 if flag_night==False and self.flag_brightness == True:
1467
1467
1468 self.flag_brightness = False
1468 self.flag_brightness = False
1469 self.__update_brightness(brightness=0)
1469 self.__update_brightness(brightness=0)
1470
1470
1471 class sensor(object):
1471 class sensor(object):
1472
1472
1473 max_size = 300
1473 max_size = 300
1474 name = ""
1474 name = ""
1475 key = None
1475 key = None
1476
1476
1477 H0 = None
1477 H0 = None
1478
1478
1479 y_value = list()
1479 y_value = list()
1480 x_value = list()
1480 x_value = list()
1481
1481
1482 FLAG_CALIBRATION_LIDAR = False
1482 FLAG_CALIBRATION_LIDAR = False
1483
1483
1484 array_calibration = list()
1484 array_calibration = list()
1485
1485
1486 def write_status(self,chain):
1486 def write_status(self,chain):
1487
1487
1488 now = datetime.now()
1488 now = datetime.now()
1489
1489
1490 formatted_date_time = now.strftime("%d/%m/%Y %H:%M:%S")
1490 formatted_date_time = now.strftime("%d/%m/%Y %H:%M:%S")
1491
1491
1492 filename = '/logs/log.txt'
1492 filename = '/logs/log.txt'
1493
1493
1494 chain = formatted_date_time + " |" + chain
1494 chain = formatted_date_time + " |" + chain
1495
1495
1496 if not os.path.isdir(os.path.dirname(filename)):
1496 if not os.path.isdir(os.path.dirname(filename)):
1497 os.makedirs(os.path.dirname(filename))
1497 os.makedirs(os.path.dirname(filename))
1498
1498
1499 try:
1499 try:
1500 with open(filename,'a') as file:
1500 with open(filename,'a') as file:
1501
1501
1502 file.write(chain + '\n')
1502 file.write(chain + '\n')
1503 except:
1503 except:
1504
1504
1505 if self.debug:
1505 if self.debug:
1506 print("Ocurrió un error al guardar datos logs.")
1506 print("Ocurrió un error al guardar datos logs.")
1507
1507
1508 return
1508 return
1509
1509
1510
1510
1511 def __init__(self,name,key):
1511 def __init__(self,name,key):
1512
1512
1513 self.name = name
1513 self.name = name
1514 self.key = key
1514 self.key = key
1515
1515
1516
1516
1517
1517
1518 def __logic(self,value):
1518 def __logic(self,value):
1519
1519
1520 '''
1520 '''
1521 Se implementará en las clases hijas.
1521 Se implementará en las clases hijas.
1522 '''
1522 '''
1523 self.write_status("[ERROR SENSOR] No se encuentra implementado el método lógic.")
1523 self.write_status("[ERROR SENSOR] No se encuentra implementado el método lógic.")
1524
1524
1525 raise NotImplementedError("No se encuentra implementado el método logic.")
1525 raise NotImplementedError("No se encuentra implementado el método logic.")
1526
1526
1527
1527
1528 def insert_value(self,value):
1528 def insert_value(self,value):
1529
1529
1530
1530
1531 if 'lidar' in self.name:
1531 if 'lidar' in self.name:
1532
1532
1533 self.__load_H0()
1533 self.__load_H0()
1534
1534
1535 if self.FLAG_CALIBRATION_LIDAR == False:
1535 if self.FLAG_CALIBRATION_LIDAR == False:
1536 self.__calibration(value)
1536 self.__calibration(value)
1537
1537
1538
1538
1539 timestamp = datetime.now().timestamp()
1539 timestamp = datetime.now().timestamp()
1540
1540
1541 size = len(self.x_value)
1541 size = len(self.x_value)
1542
1542
1543 if(size>self.max_size):
1543 if(size>self.max_size):
1544
1544
1545 self.x_value = self.x_value[1:]
1545 self.x_value = self.x_value[1:]
1546 self.y_value = self.y_value[1:]
1546 self.y_value = self.y_value[1:]
1547
1547
1548 self.x_value.append(timestamp)
1548 self.x_value.append(timestamp)
1549 self.y_value.append(value)
1549 self.y_value.append(value)
1550
1550
1551 gc.collect()
1551 gc.collect()
1552
1552
1553
1553
1554 def get_values(self,):
1554 def get_values(self,):
1555
1555
1556 return numpy.array(self.x_value,dtype=float), numpy.array(self.y_value,dtype=float)
1556 return numpy.array(self.x_value,dtype=float), numpy.array(self.y_value,dtype=float)
1557
1557
1558 def get_latest(self,):
1558 def get_latest(self,):
1559
1559
1560 if len(self.x_value)>0:
1560 if len(self.x_value)>0:
1561 return self.x_value[-1], self.y_value[-1]
1561 return self.x_value[-1], self.y_value[-1]
1562 else:
1562 else:
1563 return None,None
1563 return None,None
1564
1564
1565 class sensor_HFS(sensor):
1565 class sensor_HFS(sensor):
1566
1566
1567
1567
1568 activate = False
1568 activate = False
1569 timestamp_init = 0
1569 timestamp_init = 0
1570 timestamp_fin = 0
1570 timestamp_fin = 0
1571 timestamp = 0
1571 timestamp = 0
1572
1572
1573 timestamp_off = 0
1573 timestamp_off = 0
1574 status = False
1574 status = False
1575 prev_status = False
1575 prev_status = False
1576 THRESHOLD_BETWEEN_OFF_SENSOR = 3
1576 THRESHOLD_BETWEEN_OFF_SENSOR = 3
1577 THRESHOLD_BETWEEN_ON_SENSOR = 5
1577 THRESHOLD_BETWEEN_ON_SENSOR = 5
1578
1578
1579
1579
1580 pull_down = True
1580 pull_down = True
1581
1581
1582 def __init__(self,name,key,pin,**kwargs):
1582 def __init__(self,name,key,pin,**kwargs):
1583
1583
1584 self.name = name
1584 self.name = name
1585 self.key = key
1585 self.key = key
1586 self.pin = pin
1586 self.pin = pin
1587
1587
1588 if pin == None:
1588 if pin == None:
1589 self.write_status("[ERROR] Pin no debe de ser None para el sensor HFS.")
1589 self.write_status("[ERROR] Pin no debe de ser None para el sensor HFS.")
1590 raise AttributeError("Valor de Pin es None.")
1590 raise AttributeError("Valor de Pin es None.")
1591
1591
1592 self.pull_down = False
1592 self.pull_down = False
1593
1593
1594
1594
1595 self.__config()
1595 self.__config()
1596
1596
1597 def __config(self,):
1597 def __config(self,):
1598
1598
1599 GPIO.setwarnings(False)
1599 GPIO.setwarnings(False)
1600 GPIO.setmode(GPIO.BCM)
1600 GPIO.setmode(GPIO.BCM)
1601
1601
1602 if self.pull_down:
1602 if self.pull_down:
1603 GPIO.setup(self.pin,GPIO.IN,pull_up_down=GPIO.PUD_DOWN)
1603 GPIO.setup(self.pin,GPIO.IN,pull_up_down=GPIO.PUD_DOWN)
1604 else:
1604 else:
1605 GPIO.setup(self.pin,GPIO.IN)
1605 GPIO.setup(self.pin,GPIO.IN)
1606
1606
1607 chain = f"[Settings] Sensor HFS configurado con valores key:{self.key} name:{self.name} pin{self.pin}"
1607 chain = f"[Settings] Sensor HFS configurado con valores key:{self.key} name:{self.name} pin{self.pin}"
1608 self.write_status(chain)
1608 self.write_status(chain)
1609
1609
1610 def run(self,):
1610 def run(self,):
1611
1611
1612 value = GPIO.input(self.pin)
1612 value = GPIO.input(self.pin)
1613
1613
1614 self.__logic(value)
1614 self.__logic(value)
1615
1615
1616 def current_sensor(self,):
1616 def current_sensor(self,):
1617
1617
1618 return GPIO.input(self.pin)
1618 return GPIO.input(self.pin)
1619
1619
1620 def __logic(self,status):
1620 def __logic(self,status):
1621
1621
1622 timestamp = datetime.now().timestamp()
1622 timestamp = datetime.now().timestamp()
1623
1623
1624 self.prev_status = self.status
1624 self.prev_status = self.status
1625
1625
1626 self.status = status
1626 self.status = status
1627 self.timestamp = timestamp
1627 self.timestamp = timestamp
1628
1628
1629 if(self.prev_status == False and self.status == True):
1629 if(self.prev_status == False and self.status == True):
1630
1630
1631 self.timestamp_init = timestamp
1631 self.timestamp_init = timestamp
1632
1632
1633 elif(self.prev_status == False and self.status == False):
1633 elif(self.prev_status == False and self.status == False):
1634 #sensor desactivado
1634 #sensor desactivado
1635 if self.activate:
1635 if self.activate:
1636 if ((timestamp - self.timestamp_off)>=self.THRESHOLD_BETWEEN_OFF_SENSOR):
1636 if ((timestamp - self.timestamp_off)>=self.THRESHOLD_BETWEEN_OFF_SENSOR):
1637 self.activate = False
1637 self.activate = False
1638
1638
1639
1639
1640 elif(self.prev_status == True and self.status == False):
1640 elif(self.prev_status == True and self.status == False):
1641 #se desactivó el sensor
1641 #se desactivó el sensor
1642 if self.activate:
1642 if self.activate:
1643 self.timestamp_off = timestamp
1643 self.timestamp_off = timestamp
1644
1644
1645 elif(self.prev_status == True and self.status == True):
1645 elif(self.prev_status == True and self.status == True):
1646 if (timestamp - self.timestamp_init>=self.THRESHOLD_BETWEEN_ON_SENSOR):
1646 if (timestamp - self.timestamp_init>=self.THRESHOLD_BETWEEN_ON_SENSOR):
1647 #sensor activado
1647 #sensor activado
1648 self.activate = True
1648 self.activate = True
1649
1649
1650
1650
1651
1651
1652 class ina(sensor):
1652 class ina(sensor):
1653
1653
1654
1654
1655 bus_voltage = 0
1655 bus_voltage = 0
1656 shunt_voltage = 0
1656 shunt_voltage = 0
1657 current = 0
1657 current = 0
1658
1658
1659 def __init__(self,name,key,address):
1659 def __init__(self,name,key,address):
1660
1660
1661 if address == None:
1661 if address == None:
1662
1662
1663 self.write_status("[ERROR] Se debe de asignar la dirección al atributo INA.")
1663 self.write_status("[ERROR] Se debe de asignar la dirección al atributo INA.")
1664 raise AttributeError("Se debe de asignar la dirección al atributo INA.")
1664 raise AttributeError("Se debe de asignar la dirección al atributo INA.")
1665
1665
1666 self.address = address
1666 self.address = address
1667 self.name = name
1667 self.name = name
1668 self.key = key
1668 self.key = key
1669
1669
1670 self.__config()
1670 self.__config()
1671
1671
1672 def __config(self,):
1672 def __config(self,):
1673
1673
1674
1674
1675 self.sensor = adafruit_ina219.INA219(i2c,self.address)
1675 self.sensor = adafruit_ina219.INA219(i2c,self.address)
1676 #Aumentamos resolución del ina219
1676 #Aumentamos resolución del ina219
1677 self.sensor.bus_adc_resolution = ADCResolution.ADCRES_12BIT_32S
1677 self.sensor.bus_adc_resolution = ADCResolution.ADCRES_12BIT_32S
1678 self.sensor.shunt_adc_resolution = ADCResolution.ADCRES_12BIT_32S
1678 self.sensor.shunt_adc_resolution = ADCResolution.ADCRES_12BIT_32S
1679 #self.sensor.bus_voltage_range = BusVoltageRange.RANGE_16V
1679 #self.sensor.bus_voltage_range = BusVoltageRange.RANGE_16V
1680
1680
1681
1681
1682 def run(self,):
1682 def run(self,):
1683
1683
1684 self.bus_voltage = self.sensor.bus_voltage #V
1684 self.bus_voltage = self.sensor.bus_voltage #V
1685 self.shunt_voltage = self.sensor.shunt_voltage / 1000 #mV
1685 self.shunt_voltage = self.sensor.shunt_voltage / 1000 #mV
1686 self.current = self.sensor.current #mA
1686 self.current = self.sensor.current #mA
1687
1687
1688
1688
1689
1689
1690 class lidar(sensor):
1690 class lidar(sensor):
1691
1691
1692
1692
1693
1693
1694 H0 = 0
1694 H0 = 0
1695 dH_ = None
1695 dH_ = None
1696
1696
1697 minus_H = -6 #Desnivel para realizar una nueva calibración.
1697 minus_H = -6 #Desnivel para realizar una nueva calibración.
1698
1698
1699 TIME_LIDAR_ON = 30 #Segundos para considerar activado el sensor.
1699 TIME_LIDAR_ON = 30 #Segundos para considerar activado el sensor.
1700 TIME_LIDAR_OFF = 60 #Segundos para considerar desactivado el sensor
1700 TIME_LIDAR_OFF = 60 #Segundos para considerar desactivado el sensor
1701
1701
1702 TIME_RARE_EVENT = 60 #Silenciamos la activación por 1 minutos
1702 TIME_RARE_EVENT = 60 #Silenciamos la activación por 1 minutos
1703 NUM_SAMPLES_CALIBRATION = 15
1703 NUM_SAMPLES_CALIBRATION = 15
1704 NUM_SAMPLES_MEAN = 10
1704 NUM_SAMPLES_MEAN = 10
1705
1705
1706 TIMEOUT_CALIBRATION = 60*60*24*1 #Se calibrará automaticamente cada 1 dia.
1706 TIMEOUT_CALIBRATION = 60*60*24*1 #Se calibrará automaticamente cada 1 dia.
1707 rare_height = 60
1707 rare_height = 60
1708 min_H = 10 # Centimetros como minimo de columna de agua
1708 min_H = 10 # Centimetros como minimo de columna de agua
1709
1709
1710
1710
1711 #---------------------------------------------------------------------------------#
1711 #---------------------------------------------------------------------------------#
1712 mode_calibration = False
1712 mode_calibration = False
1713 ERROR_WIRE = False
1713 ERROR_WIRE = False
1714 activate = False
1714 activate = False
1715 FLAG_RARE_EVENT = False
1715 FLAG_RARE_EVENT = False
1716
1716
1717 timestamp_init = None
1717 timestamp_init = None
1718 timestamp_fin = None
1718 timestamp_fin = None
1719 timestamp_calibrate = None
1719 timestamp_calibrate = None
1720 timestamp_rare_event = None
1720 timestamp_rare_event = None
1721 timestamp_init_calibration = 0 #Aseguramos de calibrar el sensor en cada encendido.
1721 timestamp_init_calibration = 0 #Aseguramos de calibrar el sensor en cada encendido.
1722 #---------------------------------------------------------------------------------#
1722 #---------------------------------------------------------------------------------#
1723
1723
1724 array_samples = list()
1724 array_samples = list()
1725
1725
1726 def __load_H0(self,):
1726 def __load_H0(self,):
1727
1727
1728 try:
1728 try:
1729 timestamp = datetime.now().timestamp()
1729 timestamp = datetime.now().timestamp()
1730 path = "/others/h0.txt"
1730 path = "/others/h0.txt"
1731
1731
1732 flag = os.path.exists(path)
1732 flag = os.path.exists(path)
1733
1733
1734 if (flag):
1734 if (flag):
1735
1735
1736 with open(path,'r') as file:
1736 with open(path,'r') as file:
1737
1737
1738 string_ = (file.readline())
1738 string_ = (file.readline())
1739 values = string_.split("|")
1739 values = string_.split("|")
1740
1740
1741 self.timestamp_init_calibration = float(values[0])
1741 self.timestamp_init_calibration = float(values[0])
1742 self.H0 = float(values[1].strip())
1742 self.H0 = float(values[1].strip())
1743
1743
1744 if(timestamp - self.timestamp_init_calibration>self.TIMEOUT_CALIBRATION):
1744 if(timestamp - self.timestamp_init_calibration>self.TIMEOUT_CALIBRATION):
1745
1745
1746 self.FLAG_CALIBRATION_LIDAR = False
1746 self.FLAG_CALIBRATION_LIDAR = False
1747
1747
1748 elif self.H0 > 10000:
1748 elif self.H0 > 10000:
1749 self.FLAG_CALIBRATION_LIDAR = False
1749 self.FLAG_CALIBRATION_LIDAR = False
1750 else:
1750 else:
1751
1751
1752 self.FLAG_CALIBRATION_LIDAR = True
1752 self.FLAG_CALIBRATION_LIDAR = True
1753
1753
1754 else:
1754 else:
1755 # Se debe de realizar su calibración de H0
1755 # Se debe de realizar su calibración de H0
1756 self.FLAG_CALIBRATION_LIDAR = False
1756 self.FLAG_CALIBRATION_LIDAR = False
1757
1757
1758 except Exception as e:
1758 except Exception as e:
1759
1759
1760 print(f"Error producido al leer H0 del lidar. Copia del error {e}.")
1760 print(f"Error producido al leer H0 del lidar. Copia del error {e}.")
1761
1761
1762 def __calibration(self,value):
1762 def __calibration(self,value):
1763
1763
1764 self.array_calibration.append(value)
1764 self.array_calibration.append(value)
1765
1765
1766 if(len(self.array_calibration)==self.NUM_SAMPLES_CALIBRATION):
1766 if(len(self.array_calibration)==self.NUM_SAMPLES_CALIBRATION):
1767
1767
1768 self.H0 = numpy.nanmedian(numpy.array(self.array_calibration))
1768 self.H0 = numpy.nanmedian(numpy.array(self.array_calibration))
1769 self.FLAG_CALIBRATION_LIDAR = True
1769 self.FLAG_CALIBRATION_LIDAR = True
1770 self.array_calibration = list()
1770 self.array_calibration = list()
1771
1771
1772
1772
1773 #Guardamos el archivo de calibración
1773 #Guardamos el archivo de calibración
1774
1774
1775 try:
1775 try:
1776 path = "/others/h0.txt"
1776 path = "/others/h0.txt"
1777
1777
1778 flag = os.path.exists(path)
1778 flag = os.path.exists(path)
1779
1779
1780 if flag:
1780 if flag:
1781 try:
1781 try:
1782 os.remove(path)
1782 os.remove(path)
1783 except:
1783 except:
1784 pass
1784 pass
1785
1785
1786 with open(path,"w") as file:
1786 with open(path,"w") as file:
1787
1787
1788 timestamp = datetime.now().timestamp()
1788 timestamp = datetime.now().timestamp()
1789 file.write(str(timestamp)+"|"+str(self.H0))
1789 file.write(str(timestamp)+"|"+str(self.H0))
1790
1790
1791
1791
1792 self.timestamp_init_calibration = timestamp
1792 self.timestamp_init_calibration = timestamp
1793
1793
1794 self.timestamp_calibrate = None
1794 self.timestamp_calibrate = None
1795 self.timestamp_init = None
1795 self.timestamp_init = None
1796 self.timestamp_fin = None
1796 self.timestamp_fin = None
1797 self.timestamp_rare_event= None
1797 self.timestamp_rare_event= None
1798
1798
1799 self.FLAG_RARE_EVENT = False
1799 self.FLAG_RARE_EVENT = False
1800 self.activate = False
1800 self.activate = False
1801 self.mode_calibration = False
1801 self.mode_calibration = False
1802
1802
1803 except:
1803 except:
1804 pass
1804 pass
1805
1805
1806 finally:
1806 finally:
1807 gc.collect()
1807 gc.collect()
1808
1808
1809
1809
1810 def __config(self,):
1810 def __config(self,):
1811
1811
1812
1812
1813 self.sensor_lidar = adafruit_lidarlite.LIDARLite(i2c, sensor_type=adafruit_lidarlite.TYPE_V3HP)
1813 self.sensor_lidar = adafruit_lidarlite.LIDARLite(i2c, sensor_type=adafruit_lidarlite.TYPE_V3HP)
1814
1814
1815
1815
1816
1816
1817 def __init__(self,name,key):
1817 def __init__(self,name,key):
1818
1818
1819 super().__init__(name,key)
1819 super().__init__(name,key)
1820
1820
1821 self.__config()
1821 self.__config()
1822 self.__load_H0()
1822 self.__load_H0()
1823
1823
1824 if self.FLAG_CALIBRATION_LIDAR == False:
1824 if self.FLAG_CALIBRATION_LIDAR == False:
1825
1825
1826 self.mode_calibration = True
1826 self.mode_calibration = True
1827
1827
1828 else:
1828 else:
1829 self.mode_calibration = False
1829 self.mode_calibration = False
1830
1830
1831 def run(self,):
1831 def run(self,):
1832 timestamp = datetime.now().timestamp()
1832 timestamp = datetime.now().timestamp()
1833
1833
1834 diff = timestamp- self.timestamp_init_calibration
1834 diff = timestamp- self.timestamp_init_calibration
1835
1835
1836 value = self.sensor_lidar.distance
1836 value = self.sensor_lidar.distance
1837
1837
1838 if self.mode_calibration:
1838 if self.mode_calibration:
1839 self.__calibration(value)
1839 self.__calibration(value)
1840
1840
1841 elif (diff> self.TIMEOUT_CALIBRATION):
1841 elif (diff> self.TIMEOUT_CALIBRATION):
1842 #Es necesario realizar una calibración
1842 #Es necesario realizar una calibración
1843 self.mode_calibration = True
1843 self.mode_calibration = True
1844
1844
1845 else:
1845 else:
1846
1846
1847 if (value > 10000 and self.ERROR_WIRE == False):
1847 if (value > 10000 and self.ERROR_WIRE == False):
1848
1848
1849 '''
1849 '''
1850 Error de sensor lidar en la obtención de datos. Puede ser problema de cables
1850 Error de sensor lidar en la obtención de datos. Puede ser problema de cables
1851 Se desabilita hasta que sea corregido manualmente.
1851 Se desabilita hasta que sea corregido manualmente.
1852 '''
1852 '''
1853
1853
1854 self.ERROR_WIRE = True
1854 self.ERROR_WIRE = True
1855 self.dH_ = None
1855 self.dH_ = None
1856
1856
1857
1857
1858 path = "/others/h0.txt"
1858 path = "/others/h0.txt"
1859
1859
1860 with open(path,"w") as file:
1860 with open(path,"w") as file:
1861
1861
1862 timestamp = datetime.now().timestamp()
1862 timestamp = datetime.now().timestamp()
1863 file.write(str(0)+"|"+str(0))
1863 file.write(str(0)+"|"+str(0))
1864
1864
1865 elif (value < 10000 ):
1865 elif (value < 10000 ):
1866 if(self.ERROR_WIRE):
1866 if(self.ERROR_WIRE):
1867 self.ERROR_WIRE = False
1867 self.ERROR_WIRE = False
1868 self.mode_calibration = True
1868 self.mode_calibration = True
1869 else:
1869 else:
1870
1870
1871 self.array_samples.append(value)
1871 self.array_samples.append(value)
1872 self.array_samples.append(self.sensor_lidar.distance)
1872 self.array_samples.append(self.sensor_lidar.distance)
1873
1873
1874 if(len(self.array_samples)>=self.NUM_SAMPLES_MEAN):
1874 if(len(self.array_samples)>=self.NUM_SAMPLES_MEAN):
1875
1875
1876 value = numpy.nanmedian(numpy.array(self.array_samples))
1876 value = numpy.nanmedian(numpy.array(self.array_samples))
1877
1877
1878 self.array_samples = list()
1878 self.array_samples = list()
1879 size = len(self.x_value)
1879 size = len(self.x_value)
1880
1880
1881 if(size>self.max_size):
1881 if(size>self.max_size):
1882
1882
1883 self.x_value = self.x_value[1:]
1883 self.x_value = self.x_value[1:]
1884 self.y_value = self.y_value[1:]
1884 self.y_value = self.y_value[1:]
1885
1885
1886 self.x_value.append(timestamp)
1886 self.x_value.append(timestamp)
1887 self.y_value.append(value)
1887 self.y_value.append(value)
1888
1888
1889 #---------------------- logica -------------------------#
1889 #---------------------- logica -------------------------#
1890
1890
1891 self.__logic(value)
1891 self.__logic(value)
1892
1892
1893 def __logic(self,value):
1893 def __logic(self,value):
1894
1894
1895
1895
1896 timestamp = datetime.now().timestamp()
1896 timestamp = datetime.now().timestamp()
1897
1897
1898 dH = self.H0 - value
1898 dH = self.H0 - value
1899
1899
1900 self.dH_ = dH
1900 self.dH_ = dH
1901
1901
1902 '''
1902 '''
1903 Si dH>0, entonces el sistema ha detectado evento
1903 Si dH>0, entonces el sistema ha detectado evento
1904 Si dH<0, hay un desnivel en el suelo o referencia por lo que es necesario volver a calibrar
1904 Si dH<0, hay un desnivel en el suelo o referencia por lo que es necesario volver a calibrar
1905 '''
1905 '''
1906
1906
1907 if dH>= self.min_H and self.timestamp_init == None:
1907 if dH>= self.min_H and self.timestamp_init == None:
1908
1908
1909 '''
1909 '''
1910 Comienza el evento
1910 Comienza el evento
1911 '''
1911 '''
1912 self.timestamp_init = timestamp
1912 self.timestamp_init = timestamp
1913
1913
1914 elif dH<self.min_H and dH>=0 :
1914 elif dH<self.min_H and dH>=0 :
1915
1915
1916 if self.timestamp_init != None:
1916 if self.timestamp_init != None:
1917
1917
1918 diff_timestamp = datetime.now().timestamp() - self.timestamp_init # Calculamos cuanto tiempo va activado la señal.
1918 diff_timestamp = datetime.now().timestamp() - self.timestamp_init # Calculamos cuanto tiempo va activado la señal.
1919
1919
1920 if self.timestamp_init != None and dH>1 and diff_timestamp<15:
1920 if self.timestamp_init != None and dH>1 and diff_timestamp<15:
1921 '''
1921 '''
1922 Al inicio del evento se puede considerar pequeñas variaciones
1922 Al inicio del evento se puede considerar pequeñas variaciones
1923 '''
1923 '''
1924 pass
1924 pass
1925
1925
1926 elif self.timestamp_init !=None and self.timestamp_fin == None:
1926 elif self.timestamp_init !=None and self.timestamp_fin == None:
1927
1927
1928 '''
1928 '''
1929 El tiempo que lleva activado la señal de alerta es más de 15 segundos.
1929 El tiempo que lleva activado la señal de alerta es más de 15 segundos.
1930 '''
1930 '''
1931
1931
1932 self.timestamp_fin = timestamp
1932 self.timestamp_fin = timestamp
1933
1933
1934 elif self.timestamp_init!=None and self.timestamp_fin !=None:
1934 elif self.timestamp_init!=None and self.timestamp_fin !=None:
1935
1935
1936 '''
1936 '''
1937 En caso la diferencia de altura es menor a lo establecido como emergencia,
1937 En caso la diferencia de altura es menor a lo establecido como emergencia,
1938 entonces se desactiva la señal de alerta pero ya pasado un tiempo.
1938 entonces se desactiva la señal de alerta pero ya pasado un tiempo.
1939
1939
1940 '''
1940 '''
1941
1941
1942 if (timestamp - self.timestamp_fin>=self.TIME_LIDAR_OFF):
1942 if (timestamp - self.timestamp_fin>=self.TIME_LIDAR_OFF):
1943
1943
1944 self.timestamp_fin = None
1944 self.timestamp_fin = None
1945 self.timestamp_init = None
1945 self.timestamp_init = None
1946 self.timestamp_rare_event = None
1946 self.timestamp_rare_event = None
1947
1947
1948 self.activate = False
1948 self.activate = False
1949
1949
1950
1950
1951 elif dH>= self.min_H and self.timestamp_init != None:
1951 elif dH>= self.min_H and self.timestamp_init != None:
1952
1952
1953 #Consideramos que debe de ser constante tal cambio al menos 30 segundos
1953 #Consideramos que debe de ser constante tal cambio al menos 30 segundos
1954 #Se puede configurar en el archivo vars.json
1954 #Se puede configurar en el archivo vars.json
1955 timestamp = datetime.now().timestamp()
1955 timestamp = datetime.now().timestamp()
1956
1956
1957 diff_timestamp = timestamp - self.timestamp_init
1957 diff_timestamp = timestamp - self.timestamp_init
1958
1958
1959 if dH>= self.rare_height and diff_timestamp<=10:
1959 if dH>= self.rare_height and diff_timestamp<=10:
1960
1960
1961 '''
1961 '''
1962 En este caso consideramos que la altura aumentó rapidamente en menos de 10 segundos.
1962 En este caso consideramos que la altura aumentó rapidamente en menos de 10 segundos.
1963 Este suceso puede ser producido por un mantenimiento o por seres vivos en el cauce.
1963 Este suceso puede ser producido por un mantenimiento o por seres vivos en el cauce.
1964 '''
1964 '''
1965
1965
1966 self.FLAG_RARE_EVENT = True
1966 self.FLAG_RARE_EVENT = True
1967 self.timestamp_rare_event = timestamp
1967 self.timestamp_rare_event = timestamp
1968 self.timestamp_init = None
1968 self.timestamp_init = None
1969 self.timestamp_fin = None
1969 self.timestamp_fin = None
1970 self.activate = False
1970 self.activate = False
1971
1971
1972
1972
1973 elif diff_timestamp >= self.TIME_LIDAR_ON:
1973 elif diff_timestamp >= self.TIME_LIDAR_ON:
1974
1974
1975 '''
1975 '''
1976 El tiempo de activación fue superado, por lo que se validará la activación.
1976 El tiempo de activación fue superado, por lo que se validará la activación.
1977 '''
1977 '''
1978
1978
1979 if(self.timestamp_rare_event == None):
1979 if(self.timestamp_rare_event == None):
1980 self.timestamp_rare_event = 0
1980 self.timestamp_rare_event = 0
1981
1981
1982 diff = timestamp - self.timestamp_rare_event
1982 diff = timestamp - self.timestamp_rare_event
1983
1983
1984 if (diff>self.TIME_RARE_EVENT):
1984 if (diff>self.TIME_RARE_EVENT):
1985 self.timestamp_rare_event = 0
1985 self.timestamp_rare_event = 0
1986 self.FLAG_RARE_EVENT = False
1986 self.FLAG_RARE_EVENT = False
1987
1987
1988 if not self.FLAG_RARE_EVENT:
1988 if not self.FLAG_RARE_EVENT:
1989 self.activate = True
1989 self.activate = True
1990 self.timestamp_rare_event = None
1990 self.timestamp_rare_event = None
1991
1991
1992 elif dH <=self.minus_H and self.timestamp_calibrate == None:
1992 elif dH <=self.minus_H and self.timestamp_calibrate == None:
1993 '''
1993 '''
1994 Verificamos si es necesario realizar una calibración.
1994 Verificamos si es necesario realizar una calibración.
1995 '''
1995 '''
1996 self.timestamp_calibrate = timestamp
1996 self.timestamp_calibrate = timestamp
1997
1997
1998 elif dH <=self.minus_H and self.timestamp_calibrate != None:
1998 elif dH <=self.minus_H and self.timestamp_calibrate != None:
1999
1999
2000 '''
2000 '''
2001 Si se sobrepasa el tiempo necesario para una nueva calibración,
2001 Si se sobrepasa el tiempo necesario para una nueva calibración,
2002 entonces se seleccion
2002 entonces se seleccion
2003 '''
2003 '''
2004 diff = timestamp - self.timestamp_calibrate
2004 diff = timestamp - self.timestamp_calibrate
2005 if diff >= 30:
2005 if diff >= 30:
2006 self.mode_calibration = True
2006 self.mode_calibration = True
2007
2007
2008
2008
2009 else:
2009 else:
2010 '''
2010 '''
2011 En el unico caso que el lidar marque dH=0.
2011 En el unico caso que el lidar marque dH=0.
2012 '''
2012 '''
2013 self.timestamp_calibrate = None
2013 self.timestamp_calibrate = None
2014 self.timestamp_init = None
2014 self.timestamp_init = None
2015 self.timestamp_fin = None
2015 self.timestamp_fin = None
2016 self.timestamp_rare_event= None
2016 self.timestamp_rare_event= None
2017
2017
2018 gc.collect()
2018 gc.collect()
2019 No newline at end of file
2019
General Comments 0
You need to be logged in to leave comments. Login now