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