##// END OF EJS Templates
ATRAD actualizando títulos
Renato Huallpa -
r397:e40954e05ac0
parent child
Show More
@@ -1,35 +1,36
1 1
2 2 REDIS_HOST=radarsys-redis
3 3 REDIS_PORT=6300
4 4 POSTGRES_PORT_5432_TCP_ADDR=radarsys-postgres
5 5 POSTGRES_PORT_5432_TCP_PORT=5432
6 6 #POSTGRES_HOST=postgres
7 7 POSTGRES_HOST=localhost
8 8 POSTGRES_USER=docker
9 9 POSTGRES_PASSWORD=docker
10 10 POSTGRES_DB=radarsys
11 11
12 12 # DB_NAME=radarsys
13 13 # DB_USER=docker
14 14 # DB_PASSWORD=docker
15 15 PGDATA=/var/lib/postgresql/data
16 16 LC_ALL=C.UTF-8
17 17 TZ=America/Lima
18 18 DOCKER_DATA=/data/dockers/radarsys/
19 19 LOCAL_IP=192.168.1.128
20 20
21 21 MQTT_SERVER=10.10.10.200
22 22 # MQTT_SERVER = 192.168.100.5
23 23 MQTT_PORT = 1883
24 24 MQTT_KEEPALIVE = 3660
25 25
26 26 MQTT_USER_ATRAD=''
27 27 MQTT_PASSWORD_ATRAD = ''
28 28 MQTT_TOPIC_ATRAD_RECIEVE = "atrad/test4"
29 MQTT_TOPIC_ATRAD_CONTROL = "atrad/test2"
29 30
30 31 MQTT_USER = abs
31 32 MQTT_PASSWORD = abs
32 33
33 34 TOPIC_ABS=abs/beams
34 35 TOPIC_ABS_ACK=abs/beams_ack
35 36 TOPIC_ABS_CHANGE=abs/change_beam
@@ -1,1190 +1,1164
1 1 from django.db import models
2 2 from apps.main.models import Configuration , User
3 3 from django.urls import reverse
4 4 from celery.execute import send_task
5 5 from datetime import datetime
6 6 import ast
7 7 import socket
8 8 import json
9 9 import requests
10 10 import struct
11 11 import os, sys, time
12 12
13 13 from .mqtt import client as mqtt_client
14 14 from radarsys.socketconfig import sio as sio
15 15 import json
16 16
17 17 antenna_default = json.dumps({
18 18 "antenna_up": [[0.0,0.0,0.0,0.0,0.5,0.5,0.5,0.5],
19 19 [0.0,0.0,0.0,0.0,0.5,0.5,0.5,0.5],
20 20 [0.0,0.0,0.0,0.0,0.5,0.5,0.5,0.5],
21 21 [0.0,0.0,0.0,0.0,0.5,0.5,0.5,0.5],
22 22 [0.5,0.5,0.5,0.5,1.0,1.0,1.0,1.0],
23 23 [0.5,0.5,0.5,0.5,1.0,1.0,1.0,1.0],
24 24 [0.5,0.5,0.5,0.5,1.0,1.0,1.0,1.0],
25 25 [0.5,0.5,0.5,0.5,1.0,1.0,1.0,1.0]
26 26 ]
27 27 ,
28 28 "antenna_down": [[0.0,0.0,0.0,0.0,0.5,0.5,0.5,0.5],
29 29 [0.0,0.0,0.0,0.0,0.5,0.5,0.5,0.5],
30 30 [0.0,0.0,0.0,0.0,0.5,0.5,0.5,0.5],
31 31 [0.0,0.0,0.0,0.0,0.5,0.5,0.5,0.5],
32 32 [0.5,0.5,0.5,0.5,3.0,3.0,3.0,3.0],
33 33 [0.5,0.5,0.5,0.5,3.0,3.0,3.0,3.0],
34 34 [0.5,0.5,0.5,0.5,3.0,3.0,3.0,3.0],
35 35 [0.5,0.5,0.5,0.5,3.0,3.0,3.0,3.0]],
36 36 })
37 37
38 38
39 39 tx_default = json.dumps({
40 40 "up": [[1,1,1,1,0,0,0,0],
41 41 [1,1,1,1,0,0,0,0],
42 42 [1,1,1,1,0,0,0,0],
43 43 [1,1,1,1,0,0,0,0],
44 44 [0,0,0,0,1,1,1,1],
45 45 [0,0,0,0,1,1,1,1],
46 46 [0,0,0,0,1,1,1,1],
47 47 [0,0,0,0,1,1,1,1]],
48 48
49 49 "down": [[1,1,1,1,0,0,0,0],
50 50 [1,1,1,1,0,0,0,0],
51 51 [1,1,1,1,0,0,0,0],
52 52 [1,1,1,1,0,0,0,0],
53 53 [0,0,0,0,1,1,1,1],
54 54 [0,0,0,0,1,1,1,1],
55 55 [0,0,0,0,1,1,1,1],
56 56 [0,0,0,0,1,1,1,1]],
57 57 })
58 58
59 59 rx_default = json.dumps({
60 60 "up": [[1,1,1,1,0,0,0,0],
61 61 [1,1,1,1,0,0,0,0],
62 62 [1,1,1,1,0,0,0,0],
63 63 [1,1,1,1,0,0,0,0],
64 64 [0,0,0,0,1,1,1,1],
65 65 [0,0,0,0,1,1,1,1],
66 66 [0,0,0,0,1,1,1,1],
67 67 [0,0,0,0,1,1,1,1]],
68 68
69 69 "down": [[1,1,1,1,0,0,0,0],
70 70 [1,1,1,1,0,0,0,0],
71 71 [1,1,1,1,0,0,0,0],
72 72 [1,1,1,1,0,0,0,0],
73 73 [0,0,0,0,1,1,1,1],
74 74 [0,0,0,0,1,1,1,1],
75 75 [0,0,0,0,1,1,1,1],
76 76 [0,0,0,0,1,1,1,1]],
77 77 })
78 78
79 79 status_default = '0000000000000000000000000000000000000000000000000000000000000000'
80 80 default_messages = {}
81 81
82 82 for i in range(1,65):
83 83 default_messages[str(i)] = "Module "+str(i)
84 84
85 85
86 86 ues_default = json.dumps({
87 87 "up": [0.533333,0.00000,1.06667,0.00000],
88 88 "down": [0.533333,0.00000,1.06667,0.00000]
89 89 })
90 90
91 91 onlyrx_default = json.dumps({
92 92 "up": False,
93 93 "down": False
94 94 })
95 95
96 96 def up_convertion(cadena):
97 97 valores = []
98 98 for c in cadena:
99 99 if c == 1.0: valores=valores+['000']
100 100 if c == 2.0: valores=valores+['001']
101 101 if c == 3.0: valores=valores+['010']
102 102 if c == 0.0: valores=valores+['011']
103 103 if c == 0.5: valores=valores+['100']
104 104 if c == 1.5: valores=valores+['101']
105 105 if c == 2.5: valores=valores+['110']
106 106 if c == 3.5: valores=valores+['111']
107 107
108 108 return valores
109 109
110 110 def up_conv_bits(value):
111 111
112 112 if value == 1.0: bits="000"
113 113 if value == 2.0: bits="001"
114 114 if value == 3.0: bits="010"
115 115 if value == 0.0: bits="011"
116 116 if value == 0.5: bits="100"
117 117 if value == 1.5: bits="101"
118 118 if value == 2.5: bits="110"
119 119 if value == 3.5: bits="111"
120 120
121 121 return bits
122 122
123 123 def down_convertion(cadena):
124 124 valores = []
125 125 for c in cadena:
126 126 if c == 1.0: valores=valores+['000']
127 127 if c == 2.0: valores=valores+['001']
128 128 if c == 3.0: valores=valores+['010']
129 129 if c == 0.0: valores=valores+['011']
130 130 if c == 0.5: valores=valores+['100']
131 131 if c == 1.5: valores=valores+['101']
132 132 if c == 2.5: valores=valores+['110']
133 133 if c == 3.5: valores=valores+['111']
134 134
135 135 return valores
136 136
137 137 def down_conv_bits(value):
138 138
139 139 if value == 1.0: bits="000"
140 140 if value == 2.0: bits="001"
141 141 if value == 3.0: bits="010"
142 142 if value == 0.0: bits="011"
143 143 if value == 0.5: bits="100"
144 144 if value == 1.5: bits="101"
145 145 if value == 2.5: bits="110"
146 146 if value == 3.5: bits="111"
147 147
148 148 return bits
149 149
150 150 def up_conv_value(bits):
151 151
152 152 if bits == "000": value=1.0
153 153 if bits == "001": value=2.0
154 154 if bits == "010": value=3.0
155 155 if bits == "011": value=0.0
156 156 if bits == "100": value=0.5
157 157 if bits == "101": value=1.5
158 158 if bits == "110": value=2.5
159 159 if bits == "111": value=3.5
160 160
161 161 return value
162 162
163 163 def down_conv_value(bits):
164 164
165 165 if bits == "000": value=1.0
166 166 if bits == "001": value=2.0
167 167 if bits == "010": value=3.0
168 168 if bits == "011": value=0.0
169 169 if bits == "100": value=0.5
170 170 if bits == "101": value=1.5
171 171 if bits == "110": value=2.5
172 172 if bits == "111": value=3.5
173 173
174 174 return value
175 175
176 176 def ip2position(module_number):
177 177 j=0
178 178 i=0
179 179 for x in range(0,module_number-1):
180 180 j=j+1
181 181 if j==8:
182 182 i=i+1
183 183 j=0
184 184
185 185 pos = [i,j]
186 186 return pos
187 187
188 188
189 189 def fromBinary2Char(binary_string):
190 190 number = int(binary_string, 2)
191 191 #Plus 33 to avoid more than 1 characters values such as: '\x01'-'\x1f'
192 192 number = number + 33
193 193 char = chr(number)
194 194 return char
195 195
196 196 def fromChar2Binary(char):
197 197 number = ord(char) - 33
198 198 #Minus 33 to get the real value
199 199 bits = bin(number)[2:]
200 200 #To ensure we have a string with 6bits
201 201 if len(bits) < 6:
202 202 bits = bits.zfill(6)
203 203 return bits
204 204
205 205 OPERATION_MODES = (
206 206 (0, 'Manual'),
207 207 (1, 'Automatic'),
208 208 )
209 209
210 210 class ABSConfiguration(Configuration):
211 211 active_beam = models.PositiveSmallIntegerField(verbose_name='Active Beam', default=0)
212 212 module_status = models.CharField(verbose_name='Module Status', max_length=10000, default=status_default)
213 213 operation_mode = models.PositiveSmallIntegerField(verbose_name='Operation Mode', choices=OPERATION_MODES, default = 0)
214 214 operation_value = models.FloatField(verbose_name='Periodic (seconds)', default="10", null=True, blank=True)
215 215 module_messages = models.CharField(verbose_name='Modules Messages', max_length=10000, default=json.dumps(default_messages))
216 216
217 217 class Meta:
218 218 db_table = 'abs_configurations'
219 219
220 220 def get_absolute_url_plot(self):
221 221 return reverse('url_plot_abs_patterns', args=[str(self.id)])
222 222
223 223
224 224 def parms_to_dict(self):
225 225
226 226 parameters = {}
227 227
228 228 parameters['device_id'] = self.device.id
229 229 parameters['label'] = self.label
230 230 parameters['device_type'] = self.device.device_type.name
231 231 parameters['beams'] = {}
232 232
233 233 beams = ABSBeam.objects.filter(abs_conf=self)
234 234 b=1
235 235 for beam in beams:
236 236 #absbeam = ABSBeam.objects.get(pk=beams[beam])
237 237 parameters['beams']['beam'+str(b)] = beam.parms_to_dict()#absbeam.parms_to_dict()
238 238 b+=1
239 239
240 240 return parameters
241 241
242 242
243 243 def dict_to_parms(self, parameters):
244 244
245 245 self.label = parameters['label']
246 246
247 247 absbeams = ABSBeam.objects.filter(abs_conf=self)
248 248 beams = parameters['beams']
249 249
250 250 if absbeams:
251 251 beams_number = len(beams)
252 252 absbeams_number = len(absbeams)
253 253 if beams_number==absbeams_number:
254 254 i = 1
255 255 for absbeam in absbeams:
256 256 absbeam.dict_to_parms(beams['beam'+str(i)])
257 257 i = i+1
258 258 elif beams_number > absbeams_number:
259 259 i = 1
260 260 for absbeam in absbeams:
261 261 absbeam.dict_to_parms(beams['beam'+str(i)])
262 262 i=i+1
263 263 for x in range(i,beams_number+1):
264 264 new_beam = ABSBeam(
265 265 name =beams['beam'+str(i)]['name'],
266 266 antenna =json.dumps(beams['beam'+str(i)]['antenna']),
267 267 abs_conf = self,
268 268 tx =json.dumps(beams['beam'+str(i)]['tx']),
269 269 rx =json.dumps(beams['beam'+str(i)]['rx']),
270 270 ues =json.dumps(beams['beam'+str(i)]['ues']),
271 271 only_rx =json.dumps(beams['beam'+str(i)]['only_rx'])
272 272 )
273 273 new_beam.save()
274 274 i=i+1
275 275 else: #beams_number < absbeams_number:
276 276 i = 1
277 277 for absbeam in absbeams:
278 278 if i <= beams_number:
279 279 absbeam.dict_to_parms(beams['beam'+str(i)])
280 280 i=i+1
281 281 else:
282 282 absbeam.delete()
283 283 else:
284 284 for beam in beams:
285 285 new_beam = ABSBeam(
286 286 name =beams[beam]['name'],
287 287 antenna =json.dumps(beams[beam]['antenna']),
288 288 abs_conf = self,
289 289 tx =json.dumps(beams[beam]['tx']),
290 290 rx =json.dumps(beams[beam]['rx']),
291 291 ues =json.dumps(beams[beam]['ues']),
292 292 only_rx =json.dumps(beams[beam]['only_rx'])
293 293 )
294 294 new_beam.save()
295 295
296 296
297 297
298 298 def update_from_file(self, parameters):
299 299
300 300 self.dict_to_parms(parameters)
301 301 self.save()
302 302
303 303
304 304 def get_beams(self, **kwargs):
305 305 '''
306 306 This function returns ABS Configuration beams
307 307 '''
308 308 return ABSBeam.objects.filter(abs_conf=self.pk, **kwargs)
309 309
310 310 def clone(self, **kwargs):
311 311
312 312 beams = self.get_beams()
313 313 self.pk = None
314 314 self.id = None
315 315 for attr, value in kwargs.items():
316 316 setattr(self, attr, value)
317 317 self.save()
318 318
319 319 for beam in beams:
320 320 beam.clone(abs_conf=self)
321 321
322 322 #-----For Active Beam-----
323 323 new_beams = ABSBeam.objects.filter(abs_conf=self)
324 324 self.active_beam = new_beams[0].id
325 325 self.save()
326 326 #-----For Active Beam-----
327 327 #-----For Device Status---
328 328 self.device.status = 3
329 329 self.device.save()
330 330 #-----For Device Status---
331 331
332 332 return self
333 333
334 334
335 335 def start_device(self):
336 336
337 337 if self.device.status == 3:
338 338
339 339 try:
340 340 #self.write_device()
341 341 send_task('task_change_beam', [self.id],)
342 # print("*************************RUNNING ABS**************************",flush=True)
343 342 self.message = 'ABS running'
344 343
345 344 except Exception as e:
346 345 self.message = str(e)
347 346 return False
348 347
349 348 return True
350 349
351 350 else:
352 351 self.message = 'Please, select Write ABS Device first.'
353 352 return False
354 353
355 354
356 355 def stop_device(self):
357 356 self.device.status = 2
358 357 self.active_beam = 0
359 358 self.device.save()
360 359 self.message = 'ABS has been stopped.'
361 360 self.save()
362 361
363 362 return True
364 363
365 364 def stop_device_mqtt(self):
366 365
367 366 self.device.status = 2
368 367 self.active_beam = 0
369 368 # conf_active = None
370 369 # conf_active.save()
371 370 self.device.save()
372 371 self.message = 'ABS has been stopped.'
373 372 self.save()
374 373
375 374 mqtt_client.publish(os.environ.get('TOPIC_ABS', 'abs/beams'),"STOP")
376 375
377 376 return True
378 377
379 378 def write_device(self):
380 379
381 380 """
382 381 This function sends the beams list to every abs module.
383 382 It needs 'module_conf' function
384 383 """
385 384
386 385 beams = ABSBeam.objects.filter(abs_conf=self)
387 386 nbeams = len(beams)
388 387
389 388 # Se manda a cero RC para poder realizar cambio de beam
390 389 if self.experiment is None:
391 390 confs = []
392 391 else:
393 392 confs = Configuration.objects.filter(experiment = self.experiment).filter(type=0)
394 393 confdds = ''
395 394 confjars = ''
396 395 confrc = ''
397 396 #TO STOP DEVICES: DDS-JARS-RC
398 397 for i in range(0,len(confs)):
399 398 if i==0:
400 399 for conf in confs:
401 400 if conf.device.device_type.name == 'dds':
402 401 confdds = conf
403 402 confdds.stop_device()
404 403 break
405 404 if i==1:
406 405 for conf in confs:
407 406 if conf.device.device_type.name == 'jars':
408 407 confjars = conf
409 408 confjars.stop_device()
410 409 break
411 410 if i==2:
412 411 for conf in confs:
413 412 if conf.device.device_type.name == 'rc':
414 413 confrc = conf
415 414 confrc.stop_device()
416 415 break
417 416
418 417 '''
419 418 if self.connected_modules() == 0 :
420 419 print("No encuentra modulos")
421 420 self.message = "No ABS Module detected."
422 421 return False
423 422 '''
424 423 #-------------Write each abs module-----------
425 424
426 425 if beams:
427 426 block_id = 0
428 427 message = 'SNDF{:03d}{:02d}{:02d}'.format(nbeams, nbeams, block_id)
429 428 for i, status in enumerate(self.module_status):
430 429 message += ''.join([fromBinary2Char(beam.module_6bits(i)) for beam in beams])
431 430 status = ['0'] * 64
432 431 n = 0
433 print("Estoy en write_device normal",flush=True)
434 432 sock = self.send_multicast(message)
435 433
436 434 while True:
437 435 #for i in range(32):
438 436 try:
439 437 data, address = sock.recvfrom(1024)
440 438 print (address, data)
441 439 data = data.decode("utf-8")
442 440 if data == '1':
443 441 status[int(address[0][10:])-1] = '3'
444 442 #print (int(address[0][10:])-1)
445 443 elif data == '0':
446 444 status[int(address[0][10:])-1] = '1'
447 445 except socket.timeout:
448 446 print('Timeout')
449 447 break
450 448 except Exception as e:
451 449 print ('Error {}'.format(e))
452 450 n += 1
453 451 sock.close()
454 452 else:
455 453 self.message = "ABS Configuration does not have beams"
456 454 # print('No beams')
457 455 #Start DDS-RC-JARS
458 456 if confdds:
459 457 confdds.start_device()
460 458 if confrc:
461 459 #print confrc
462 460 confrc.start_device()
463 461 if confjars:
464 462 confjars.start_device()
465 463 return False
466 464
467 465 if n == 64:
468 466 self.message = "Could not write ABS Modules"
469 467 self.device.status = 0
470 468 self.module_status = ''.join(status)
471 469 self.save()
472 470 # print('Could not write ABS')
473 471 #Start DDS-RC-JARS
474 472 if confdds:
475 473 confdds.start_device()
476 474 if confrc:
477 475 #print confrc
478 476 confrc.start_device()
479 477 if confjars:
480 478 confjars.start_device()
481 479 return False
482 480 else:
483 481 self.message = "ABS Beams List have been sent to ABS Modules"
484 482 print('ABS beams list sent')
485 483 self.active_beam = beams[0].pk
486 484
487 485 #Start DDS-RC-JARS
488 486 if confdds:
489 487 confdds.start_device()
490 488 if confrc:
491 489 #print confrc
492 490 confrc.start_device()
493 491 if confjars:
494 492 confjars.start_device()
495 493
496 494 # print('Inicia intento de salvar device.status')
497 495 self.device.status = 3
498 496 self.module_status = ''.join(status)
499 497 #print(status)
500 498 self.save()
501 499 # print('Estatus salvado')
502 500 conf_active, __ = ABSActive.objects.get_or_create(pk=1)
503 501 conf_active.conf = self
504 502 conf_active.save()
505 503 return True
506 504
507 505
508 506 # DEV_STATES = (
509 507 # (0, 'No connected'),
510 508 # (1, 'Connected'),
511 509 # (2, 'Configured'),
512 510 # (3, 'Running'),
513 511 # (4, 'Unknown'),
514 512 # (5, 'Busy')
515 513 # )
516 514
517 515 def write_device_mqtt(self):
518 516
519 517 if self.experiment is None:
520 518 confs = []
521 519 else:
522 520 confs = Configuration.objects.filter(experiment = self.experiment).filter(type=0)
523 521 confdds = ''
524 522 confjars = ''
525 523 confrc = ''
526 524 #TO STOP DEVICES: DDS-JARS-RC
527 525 for i in range(0,len(confs)):
528 526 if i==0:
529 527 for conf in confs:
530 528 if conf.device.device_type.name == 'dds':
531 529 confdds = conf
532 530 confdds.stop_device()
533 531 break
534 532 if i==1:
535 533 for conf in confs:
536 534 if conf.device.device_type.name == 'jars':
537 535 confjars = conf
538 536 confjars.stop_device()
539 537 break
540 538 if i==2:
541 539 for conf in confs:
542 540 if conf.device.device_type.name == 'rc':
543 541 confrc = conf
544 542 confrc.stop_device()
545 543 break
546 544
547 545 apuntes_up_down=''
548 546 beams = ABSBeam.objects.filter(abs_conf=self)
549 547
550 548 inicializacion="{\"beams\":["
551 549 finalizacion="]}"
552 550
553 551 for beam in beams:
554 552 beam.antenna=beam.antenna[1:]
555 553 info="{\"id\":"+str(beam.id)+","+beam.antenna + ","
556 554 apuntes_up_down=apuntes_up_down+info
557 555
558 556 apuntes_up_down=apuntes_up_down[:len(apuntes_up_down)-1]
559 557 apuntes_up_down=inicializacion+ apuntes_up_down+finalizacion
560 558 mqtt_client.publish(os.environ.get('TOPIC_ABS', 'abs/beams'),apuntes_up_down)
561 559
562 560 self.active_beam = beams[0].pk
563 561
564 562 #Start DDS-RC-JARS
565 563 if confdds:
566 564 confdds.start_device()
567 565 if confrc:
568 566 #print confrc
569 567 confrc.start_device()
570 568 if confjars:
571 569 confjars.start_device()
572 570
573 571 self.device.status = 3
574 572 self.save()
575 573
576 574 conf_active, __ = ABSActive.objects.get_or_create(pk=1)
577 575 conf_active.conf = self
578 576 conf_active.save()
579 577 return True
580 578
581 579 def read_module(self, module):
582 580
583 581 """
584 582 Read out-bits (up-down) of 1 abs module NOT for Configuration
585 583 """
586 584
587 585 ip_address = self.device.ip_address
588 586 ip_address = ip_address.split('.')
589 587 module_seq = (ip_address[0],ip_address[1],ip_address[2])
590 588 dot = '.'
591 589 module_ip = dot.join(module_seq)+'.'+str(module)
592 590 module_port = self.device.port_address
593 591 read_route = 'http://'+module_ip+':'+str(module_port)+'/read'
594 592
595 593 module_status = json.loads(self.module_status)
596 594 print(read_route)
597 595
598 596 module_bits = ''
599 597
600 598 try:
601 599 r_read = requests.get(read_route, timeout=0.5)
602 600 answer = r_read.json()
603 601 module_bits = answer['allbits']
604 602 except:
605 603 return {}
606 604
607 605 return module_bits
608 606
609 607 def read_device(self):
610 608
611 609 parms = {}
612 610 # Reads active modules.
613 611 module_status = json.loads(self.module_status)
614 612 total = 0
615 613 for status in module_status:
616 614 if module_status[status] != 0:
617 615 module_bits = self.read_module(int(status))
618 616 bits={}
619 617 if module_bits:
620 618 bits = (str(module_bits['um2']) + str(module_bits['um1']) + str(module_bits['um0']) +
621 619 str(module_bits['dm2']) + str(module_bits['dm1']) + str(module_bits['dm0']) )
622 620 parms[str(status)] = bits
623 621
624 622 total +=1
625 623
626 624 if total==0:
627 625 self.message = "No ABS Module detected. Please select 'Status'."
628 626 return False
629 627
630 628
631 629
632 630 self.message = "ABS Modules have been read"
633 631 #monitoreo_tx = JROABSClnt_01CeCnMod000000MNTR10
634 632 return parms
635 633
636 634
637 635 def connected_modules(self):
638 636 """
639 637 This function returns the number of connected abs-modules without updating.
640 638 """
641 639 num = 0
642 640 print(self.module_status)
643 641 for i, status in enumerate(self.module_status):
644 642 if status != '0':
645 643 num += 1
646 644 #print('status {}:{}'.format(i+1, status))
647 645 return num
648 646
649 647 def send_multicast(self, message):
650 648 #print("Send multicast")
651 649 multicast_group = ('224.3.29.71', 10000)
652 650 # Create the datagram socket
653 651 sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
654 652 sock.settimeout(1)
655 653 local_ip = os.environ.get('LOCAL_IP', '0.0.0.0')
656 654 local_ip = '0.0.0.0'
657 655 print("He llegado a IP local")
658 656
659 657 sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_IF, socket.inet_aton(local_ip))
660 658 sock.sendto(message.encode(), multicast_group)
661 659 print('Sending ' + message)
662 660 return sock
663 661
664 662 def status_device(self):
665 663 """
666 664 This function returns the status of all abs-modules as one.
667 665 If at least one module is connected, its answer is "1"
668 666 """
669 667 print ('Status device')
670 668 print (self.active_beam)
671 669 beams = ABSBeam.objects.filter(abs_conf=self)
672 670 #print beams[self.active_beam-1].module_6bits(0)
673 671 active = ABSActive.objects.get(pk=1)
674 672 if active.conf != self:
675 673 self.message = 'La configuracion actual es la del siguiente enlace %s.' % active.conf.get_absolute_url()
676 674 self.message += "\n"
677 675 self.message += 'Se debe realizar un write en esta configuracion para luego obtener un status valido.'
678 676
679 677 return False
680 678
681 679 sock = self.send_multicast('MNTR')
682 print("Estoy en status_deice",flush=True)
680 # print("Estoy en status_deice",flush=True)
683 681
684 682 n = 0
685 683 status = ['0'] * 64
686 684
687 685 while True:
688 686 #for i in range(32):
689 687 #if True:
690 688 try:
691 689 print("Recibiendo")
692 690 address = None
693 691 data, address = sock.recvfrom(2)
694 692 print (address, data)
695 693 print("!!!!")
696 694 data = data.decode()
697 695 aux_mon = "1"
698 696 aux_expected = aux_mon
699 697 if(len(data)==2):
700 698 print ("data[1]: ")
701 699 print (data[1])
702 700 aux_mon = fromChar2Binary(data[1])
703 701 print (aux_mon)
704 702 aux_i = (str(address[0]).split('.'))[3]
705 703 print (aux_i)
706 704 print ('Active beam')
707 705 beam_active = ABSBeam.objects.get(pk=self.active_beam)
708 706 print (beam_active)
709 707 aux_expected = beam_active.module_6bits(int(aux_i)-1)
710 708 print (aux_expected)
711 709
712 710 print ("data[0]: ")
713 711 print (data[0])
714 712
715 713 if data[0] == '1':
716 714 status[int(address[0][10:])-1] = '3'
717 715 if aux_mon == aux_expected:
718 716 print ('Es igual')
719 717 else:
720 718 print ('Es diferente')
721 719 status[int(address[0][10:])-1] = '2'
722 720
723 721 elif data[0] == '0':
724 722 status[int(address[0][10:])-1] = '1'
725 723 n += 1
726 724 print('Module: {} connected'.format(address))
727 725 except socket.timeout:
728 726 print('Timeout')
729 727 break
730 728 except:
731 729 print('Module: {} error'.format(address))
732 730 pass
733 731
734 732 sock.close()
735 733
736 734 if n > 0:
737 735 self.message = 'ABS modules Status have been updated.'
738 736 self.device.status = 1
739 737 else:
740 738 self.device.status = 0
741 739 self.message = 'No ABS module is connected.'
742 740 self.module_status = ''.join(status)
743 741 self.save()
744 742
745 743 return self.device.status
746 744
747 745
748 746 def send_beam(self, beam_pos):
749 747 """
750 748 This function connects to a multicast group and sends the beam number
751 749 to all abs modules.
752 750 """
753 751 print ('Send beam')
754 752 print (self.active_beam)
755 753 beams = ABSBeam.objects.filter(abs_conf=self)
756 754 #print beams[self.active_beam-1].module_6bits(0)
757 755 active = ABSActive.objects.get(pk=1)
758 756 if active.conf != self:
759 757 self.message = 'La configuracion actual es la del siguiente enlace %s.' % active.conf.get_absolute_url()
760 758 self.message += "\n"
761 759 self.message += 'Se debe realizar un write en esta configuracion para luego obtener un status valido.'
762 760
763 761 return False
764 762
765 763 # Se manda a cero RC para poder realizar cambio de beam
766 764 if self.experiment is None:
767 765 confs = []
768 766 else:
769 767 confs = Configuration.objects.filter(experiment = self.experiment).filter(type=0)
770 768 confdds = ''
771 769 confjars = ''
772 770 confrc = ''
773 771 #TO STOP DEVICES: DDS-JARS-RC
774 772 for i in range(0,len(confs)):
775 773 if i==0:
776 774 for conf in confs:
777 775 if conf.device.device_type.name == 'dds':
778 776 confdds = conf
779 777 confdds.stop_device()
780 778 break
781 779 if i==1:
782 780 for conf in confs:
783 781 if conf.device.device_type.name == 'jars':
784 782 confjars = conf
785 783 confjars.stop_device()
786 784 break
787 785 if i==2:
788 786 for conf in confs:
789 787 if conf.device.device_type.name == 'rc':
790 788 confrc = conf
791 789 confrc.stop_device()
792 790 break
793 791 if beam_pos > 0:
794 792 beam_pos = beam_pos - 1
795 793 else:
796 794 beam_pos = 0
797 795
798 796 #El indice del apunte debe ser menor que el numero total de apuntes
799 797 #El servidor tcp en el embebido comienza a contar desde 0
800 798 status = ['0'] * 64
801 799 message = 'CHGB{}'.format(beam_pos)
802 800 sock = self.send_multicast(message)
803 801 print("Estoy en send_beam ",flush=True)
804 802 while True:
805 803 #for i in range(32):
806 804 try:
807 805 data, address = sock.recvfrom(1024)
808 806 print (address, data)
809 807 data = data.decode()
810 808 if data == '1':
811 809 status[int(address[0][10:])-1] = '3'
812 810 elif data == '0':
813 811 status[int(address[0][10:])-1] = '1'
814 812 except socket.timeout:
815 813 print('Timeout')
816 814 break
817 815 except Exception as e:
818 816 print ('Error {}'.format(e))
819 817 pass
820 818
821 819 sock.close()
822 820
823 821 #Start DDS-RC-JARS
824 822 if confdds:
825 823 confdds.start_device()
826 824 if confrc:
827 825 #print confrc
828 826 confrc.start_device()
829 827 if confjars:
830 828 confjars.start_device()
831 829
832 830 self.message = "ABS Beam has been changed"
833 831 self.module_status = ''.join(status)
834 832 self.save()
835 833 return True
836 834
837 835 def change_beam_mqtt(self, beam_pos):
838 836 """
839 837 This function connects send through mqtt the order of change_beam (id of beam).
840 838 """
841 839 print ('Change beam MQTT')
842 840 print (self.active_beam)
843 841 beams = ABSBeam.objects.filter(abs_conf=self)
844 842 #print beams[self.active_beam-1].module_6bits(0)
845 843 active = ABSActive.objects.get(pk=1)
846 844 if active.conf != self:
847 845 self.message = 'La configuracion actual es la del siguiente enlace %s.' % active.conf.get_absolute_mqtt_url()
848 846 self.message += "\n"
849 847 self.message += 'Se debe realizar un write en esta configuracion para luego obtener un status valido.'
850 848
851 849 return False
852 850
853 851 # Se manda a cero RC para poder realizar cambio de beam
854 852 if self.experiment is None:
855 853 confs = []
856 854 else:
857 855 confs = Configuration.objects.filter(experiment = self.experiment).filter(type=0)
858 856 confdds = ''
859 857 confjars = ''
860 858 confrc = ''
861 859 #TO STOP DEVICES: DDS-JARS-RC
862 860 for i in range(0,len(confs)):
863 861 if i==0:
864 862 for conf in confs:
865 863 if conf.device.device_type.name == 'dds':
866 864 confdds = conf
867 865 confdds.stop_device()
868 866 break
869 867 if i==1:
870 868 for conf in confs:
871 869 if conf.device.device_type.name == 'jars':
872 870 confjars = conf
873 871 confjars.stop_device()
874 872 break
875 873 if i==2:
876 874 for conf in confs:
877 875 if conf.device.device_type.name == 'rc':
878 876 confrc = conf
879 877 confrc.stop_device()
880 878 break
881 879 if beam_pos > 0:
882 880 beam_pos = beam_pos - 1
883 881 else:
884 882 beam_pos = 0
885 883
886 #El indice del apunte debe ser menor que el numero total de apuntes
887 #El servidor tcp en el embebido comienza a contar desde 0
888 # status = ['0'] * 64
889 # message = 'CHGB{}'.format(beam_pos)
890 # sock = self.send_multicast(message)
891 # while True:
892 # #for i in range(32):
893 # try:
894 # data, address = sock.recvfrom(1024)
895 # print (address, data)
896 # data = data.decode()
897 # if data == '1':
898 # status[int(address[0][10:])-1] = '3'
899 # elif data == '0':
900 # status[int(address[0][10:])-1] = '1'
901 # except socket.timeout:
902 # print('Timeout')
903 # break
904 # except Exception as e:
905 # print ('Error {}'.format(e))
906 # pass
907
908 # sock.close()
909 884 mqtt_client.publish('abs/change_beam',str(beam_pos))
910 885
911 886
912 887 #Start DDS-RC-JARS
913 888 if confdds:
914 889 confdds.start_device()
915 890 if confrc:
916 #print confrc
917 891 confrc.start_device()
918 892 if confjars:
919 893 confjars.start_device()
920 894
921 895 self.message = "ABS Beam has been changed"
922 896 self.save()
923 897 return True
924 898
925 899 def get_absolute_url_import(self):
926 900 return reverse('url_import_abs_conf', args=[str(self.id)])
927 901
928 902 class ABSActive(models.Model):
929 903 conf = models.ForeignKey(ABSConfiguration, null=True, verbose_name='ABS Configuration', on_delete=models.CASCADE)
930 904
931 905 class Meta:
932 906 db_table = 'abs_absactive'
933 907
934 908 class ABSBeam(models.Model):
935 909
936 910 name = models.CharField(max_length=60, default='Beam')
937 911 antenna = models.CharField(verbose_name='Antenna', max_length=1000, default=antenna_default)
938 912 abs_conf = models.ForeignKey('ABSConfiguration', null=True,
939 913 verbose_name='ABS Configuration', on_delete=models.CASCADE)
940 914 tx = models.CharField(verbose_name='Tx', max_length=1000, default=tx_default)
941 915 rx = models.CharField(verbose_name='Rx', max_length=1000, default=rx_default)
942 916 s_time = models.TimeField(verbose_name='Star Time', default='00:00:00')
943 917 e_time = models.TimeField(verbose_name='End Time', default='23:59:59')
944 918 ues = models.CharField(verbose_name='Ues', max_length=100, default=ues_default)
945 919 only_rx = models.CharField(verbose_name='Only RX', max_length=40, default=onlyrx_default)
946 920
947 921 class Meta:
948 922 db_table = 'abs_beams'
949 923
950 924 def __unicode__(self):
951 925 return u'%s' % (self.name)
952 926
953 927 def parms_to_dict(self):
954 928
955 929 parameters = {}
956 930 parameters['name'] = self.name
957 931 parameters['antenna'] = ast.literal_eval(self.antenna)
958 932 parameters['abs_conf'] = self.abs_conf.name
959 933 parameters['tx'] = ast.literal_eval(self.tx)
960 934 parameters['rx'] = ast.literal_eval(self.rx)
961 935 parameters['s_time'] = self.s_time.strftime("%H:%M:%S")
962 936 parameters['e_time'] = self.e_time.strftime("%H:%M:%S")
963 937 parameters['ues'] = ast.literal_eval(self.ues)
964 938 parameters['only_rx'] = json.loads(self.only_rx)
965 939
966 940 return parameters
967 941
968 942 def dict_to_parms(self, parameters):
969 943
970 944 self.name = parameters['name']
971 945 self.antenna = json.dumps(parameters['antenna'])
972 946 #self.abs_conf = parameters['abs_conf']
973 947 self.tx = json.dumps(parameters['tx'])
974 948 self.rx = json.dumps(parameters['rx'])
975 949 #self.s_time = parameters['s_time']
976 950 #self.e_time = parameters['e_time']
977 951 self.ues = json.dumps(parameters['ues'])
978 952 self.only_rx = json.dumps(parameters['only_rx'])
979 953 self.save()
980 954
981 955
982 956 def clone(self, **kwargs):
983 957
984 958 self.pk = None
985 959 self.id = None
986 960 for attr, value in kwargs.items():
987 961 setattr(self, attr, value)
988 962
989 963 self.save()
990 964
991 965 return self
992 966
993 967
994 968 def module_6bits(self, module):
995 969 """
996 970 This function reads antenna pattern and choose 6bits (upbits-downbits) for one abs module
997 971 """
998 972 module += 1
999 973 if module > 64:
1000 974 beam_bits = ""
1001 975 return beam_bits
1002 976
1003 977 data = ast.literal_eval(self.antenna)
1004 978 up_data = data['antenna_up']
1005 979 down_data = data['antenna_down']
1006 980
1007 981 pos = ip2position(module)
1008 982 up_value = up_data[pos[0]][pos[1]]
1009 983 down_value = down_data[pos[0]][pos[1]]
1010 984
1011 985 up_bits = up_conv_bits(up_value)
1012 986 down_bits = down_conv_bits(down_value)
1013 987 beam_bits = up_bits+down_bits
1014 988
1015 989 return beam_bits
1016 990
1017 991
1018 992 @property
1019 993 def get_upvalues(self):
1020 994 """
1021 995 This function reads antenna pattern and show the up-value of one abs module
1022 996 """
1023 997
1024 998 data = ast.literal_eval(self.antenna)
1025 999 up_data = data['antenna_up']
1026 1000
1027 1001 up_values = []
1028 1002 for data in up_data:
1029 1003 for i in range(0,8):
1030 1004 up_values.append(data[i])
1031 1005
1032 1006 return up_values
1033 1007
1034 1008 @property
1035 1009 def antenna_upvalues(self):
1036 1010 """
1037 1011 This function reads antenna pattern and show the up - values of one abs beam
1038 1012 in a particular order
1039 1013 """
1040 1014 data = ast.literal_eval(self.antenna)
1041 1015 up_data = data['antenna_up']
1042 1016
1043 1017 return up_data
1044 1018
1045 1019 @property
1046 1020 def antenna_downvalues(self):
1047 1021 """
1048 1022 This function reads antenna pattern and show the down - values of one abs beam
1049 1023 in a particular order
1050 1024 """
1051 1025 data = ast.literal_eval(self.antenna)
1052 1026 down_data = data['antenna_down']
1053 1027
1054 1028 return down_data
1055 1029
1056 1030 @property
1057 1031 def get_downvalues(self):
1058 1032 """
1059 1033 This function reads antenna pattern and show the down-value of one abs module
1060 1034 """
1061 1035
1062 1036 data = ast.literal_eval(self.antenna)
1063 1037 down_data = data['antenna_down']
1064 1038
1065 1039 down_values = []
1066 1040 for data in down_data:
1067 1041 for i in range(0,8):
1068 1042 down_values.append(data[i])
1069 1043
1070 1044 return down_values
1071 1045
1072 1046 @property
1073 1047 def get_up_ues(self):
1074 1048 """
1075 1049 This function shows the up-ues-value of one beam
1076 1050 """
1077 1051 data = ast.literal_eval(self.ues)
1078 1052 up_ues = data['up']
1079 1053
1080 1054 return up_ues
1081 1055
1082 1056 @property
1083 1057 def get_down_ues(self):
1084 1058 """
1085 1059 This function shows the down-ues-value of one beam
1086 1060 """
1087 1061 data = ast.literal_eval(self.ues)
1088 1062 down_ues = data['down']
1089 1063
1090 1064 return down_ues
1091 1065
1092 1066 @property
1093 1067 def get_up_onlyrx(self):
1094 1068 """
1095 1069 This function shows the up-onlyrx-value of one beam
1096 1070 """
1097 1071 data = json.loads(self.only_rx)
1098 1072 up_onlyrx = data['up']
1099 1073
1100 1074 return up_onlyrx
1101 1075
1102 1076 @property
1103 1077 def get_down_onlyrx(self):
1104 1078 """
1105 1079 This function shows the down-onlyrx-value of one beam
1106 1080 """
1107 1081 data = json.loads(self.only_rx)
1108 1082 down_onlyrx = data['down']
1109 1083
1110 1084 return down_onlyrx
1111 1085
1112 1086 @property
1113 1087 def get_tx(self):
1114 1088 """
1115 1089 This function shows the tx-values of one beam
1116 1090 """
1117 1091 data = json.loads(self.tx)
1118 1092
1119 1093 return data
1120 1094
1121 1095 @property
1122 1096 def get_uptx(self):
1123 1097 """
1124 1098 This function shows the up-tx-values of one beam
1125 1099 """
1126 1100 data = json.loads(self.tx)
1127 1101 up_data = data['up']
1128 1102
1129 1103 up_values = []
1130 1104 for data in up_data:
1131 1105 for i in range(0,8):
1132 1106 up_values.append(data[i])
1133 1107
1134 1108 return up_values
1135 1109
1136 1110 @property
1137 1111 def get_downtx(self):
1138 1112 """
1139 1113 This function shows the down-tx-values of one beam
1140 1114 """
1141 1115 data = json.loads(self.tx)
1142 1116 down_data = data['down']
1143 1117
1144 1118 down_values = []
1145 1119 for data in down_data:
1146 1120 for i in range(0,8):
1147 1121 down_values.append(data[i])
1148 1122
1149 1123 return down_values
1150 1124
1151 1125
1152 1126
1153 1127 @property
1154 1128 def get_rx(self):
1155 1129 """
1156 1130 This function shows the rx-values of one beam
1157 1131 """
1158 1132 data = json.loads(self.rx)
1159 1133
1160 1134 return data
1161 1135
1162 1136 @property
1163 1137 def get_uprx(self):
1164 1138 """
1165 1139 This function shows the up-rx-values of one beam
1166 1140 """
1167 1141 data = json.loads(self.rx)
1168 1142 up_data = data['up']
1169 1143
1170 1144 up_values = []
1171 1145 for data in up_data:
1172 1146 for i in range(0,8):
1173 1147 up_values.append(data[i])
1174 1148
1175 1149 return up_values
1176 1150
1177 1151 @property
1178 1152 def get_downrx(self):
1179 1153 """
1180 1154 This function shows the down-rx-values of one beam
1181 1155 """
1182 1156 data = json.loads(self.rx)
1183 1157 down_data = data['down']
1184 1158
1185 1159 down_values = []
1186 1160 for data in down_data:
1187 1161 for i in range(0,8):
1188 1162 down_values.append(data[i])
1189 1163
1190 1164 return down_values
@@ -1,574 +1,574
1 1 from django.shortcuts import render
2 2 from django.template import RequestContext
3 3 from django.shortcuts import redirect, render, get_object_or_404
4 4 from django.contrib import messages
5 5 from django.conf import settings
6 6 from django.http import HttpResponse
7 7 from django.urls import reverse
8 8 from django.views.decorators.csrf import csrf_exempt
9 9 from django.utils.safestring import mark_safe
10 10
11 11 from datetime import datetime
12 12 from time import sleep
13 13 import os
14 14 import io
15 15
16 16 from apps.main.models import Device, Configuration, Experiment
17 17 from apps.main.views import sidebar
18 18
19 19 from .models import ABSConfiguration, ABSBeam
20 20 from .forms import ABSConfigurationForm, ABSBeamEditForm, ABSBeamAddForm, ABSImportForm
21 21
22 22 from .utils.overJroShow import overJroShow
23 23 #from .utils.OverJRO import OverJRO
24 24 #Create your views here.
25 25 import json, ast
26 26
27 27 from .mqtt import client as mqtt_client
28 28 from radarsys.socketconfig import sio as sio
29 29
30 30 def get_values_from_form(form_data):
31 31
32 32 sublistup = []
33 33 sublistdown = []
34 34 subtxlistup = []
35 35 subtxlistdown = []
36 36 subrxlistup = []
37 37 subrxlistdown = []
38 38
39 39 up_values_list = []
40 40 down_values_list = []
41 41 up_txvalues_list = []
42 42 down_txvalues_list = []
43 43 up_rxvalues_list = []
44 44 down_rxvalues_list = []
45 45
46 46 values_list = {}
47 47 cont = 1
48 48
49 49 for i in range(1,65):
50 50 x = float(form_data['abs_up'+str(i)])
51 51 y = float(form_data['abs_down'+str(i)])
52 52 sublistup.append(x)
53 53 sublistdown.append(y)
54 54
55 55 if str(i) in form_data.getlist('uptx_checks'):
56 56 subtxlistup.append(1)
57 57 else:
58 58 subtxlistup.append(0)
59 59 if str(i) in form_data.getlist('downtx_checks'):
60 60 subtxlistdown.append(1)
61 61 else:
62 62 subtxlistdown.append(0)
63 63
64 64 if str(i) in form_data.getlist('uprx_checks'):
65 65 subrxlistup.append(1)
66 66 else:
67 67 subrxlistup.append(0)
68 68 if str(i) in form_data.getlist('downrx_checks'):
69 69 subrxlistdown.append(1)
70 70 else:
71 71 subrxlistdown.append(0)
72 72
73 73 cont = cont+1
74 74
75 75 if cont == 9:
76 76 up_values_list.append(sublistup)
77 77 down_values_list.append(sublistdown)
78 78 sublistup = []
79 79 sublistdown = []
80 80
81 81 up_txvalues_list.append(subtxlistup)
82 82 down_txvalues_list.append(subtxlistdown)
83 83 subtxlistup = []
84 84 subtxlistdown = []
85 85 up_rxvalues_list.append(subrxlistup)
86 86 down_rxvalues_list.append(subrxlistdown)
87 87 subrxlistup = []
88 88 subrxlistdown = []
89 89 cont = 1
90 90
91 91
92 92 list_uesup = []
93 93 list_uesdown = []
94 94 for i in range(1,5):
95 95 if form_data['ues_up'+str(i)] == '':
96 96 list_uesup.append(0.0)
97 97 else:
98 98 list_uesup.append(float(form_data['ues_up'+str(i)]))
99 99
100 100 if form_data['ues_down'+str(i)] == '':
101 101 list_uesdown.append(0.0)
102 102 else:
103 103 list_uesdown.append(float(form_data['ues_down'+str(i)]))
104 104
105 105 onlyrx_list = form_data.getlist('onlyrx')
106 106 only_rx = {}
107 107 if '1' in onlyrx_list:
108 108 only_rx['up'] = True
109 109 else:
110 110 only_rx['up'] = False
111 111 if '2' in onlyrx_list:
112 112 only_rx['down'] = True
113 113 else:
114 114 only_rx['down'] = False
115 115
116 116 antenna = {'antenna_up': up_values_list, 'antenna_down': down_values_list}
117 117 tx = {'up': up_txvalues_list, 'down': down_txvalues_list}
118 118 rx = {'up': up_rxvalues_list, 'down': down_rxvalues_list}
119 119 ues = {'up': list_uesup, 'down': list_uesdown}
120 120 name = str(form_data['beam_name'])
121 121
122 122 beam_data = {'name': name, 'antenna': antenna, 'tx': tx, 'rx': rx, 'ues': ues, 'only_rx': only_rx}
123 123
124 124 return beam_data
125 125
126 126
127 127 def abs_conf(request, id_conf):
128 128
129 129 conf = get_object_or_404(ABSConfiguration, pk=id_conf)
130 130 beams = ABSBeam.objects.filter(abs_conf=conf)
131 131 #------------Colors for Active Beam:-------------
132 132 all_status = {}
133 133 module_messages = json.loads(conf.module_messages)
134 134
135 135 color_status = {}
136 136 for i, status in enumerate(conf.module_status):
137 137 if status == '3': #Running background-color: #00cc00;
138 138 all_status['{}'.format(i+1)] = 2
139 139 color_status['{}'.format(i+1)] = 'class=text-success'#'bgcolor=#00cc00'
140 140 elif status == '2':
141 141 all_status['{}'.format(i+1)] = 1
142 142 color_status['{}'.format(i+1)] = 'class=text-info'
143 143 elif status == '1': #Connected background-color: #ee902c;
144 144 all_status['{}'.format(i+1)] = 1
145 145 color_status['{}'.format(i+1)] = 'class=text-warning'#'bgcolor=#ee902c'
146 146 else: #Disconnected background-color: #ff0000;
147 147 all_status['{}'.format(i+1)] = 0
148 148 color_status['{}'.format(i+1)] = 'class=text-danger'#'bgcolor=#FF0000'
149 149 #------------------------------------------------
150 150
151 151 kwargs = {}
152 152 kwargs['connected_modules'] = str(conf.connected_modules())+'/64'
153 153 kwargs['dev_conf'] = conf
154 154
155 155 if conf.operation_mode == 0:
156 156 kwargs['dev_conf_keys'] = ['label', 'operation_mode']
157 157 else:
158 158 kwargs['dev_conf_keys'] = ['label', 'operation_mode', 'operation_value']
159 159
160 160 kwargs['title'] = 'ABS Configuration'
161 161 kwargs['suptitle'] = 'Details'
162 162 kwargs['button'] = 'Edit Configuration'
163 163
164 164 if conf.active_beam != 0:
165 165 kwargs['active_beam'] = int(conf.active_beam)
166 166
167 167 kwargs['beams'] = beams
168 168 kwargs['modules_status'] = all_status
169 169 kwargs['color_status'] = color_status
170 170 kwargs['module_messages'] = module_messages
171 171 ###### SIDEBAR ######
172 172 kwargs.update(sidebar(conf=conf))
173 173
174 174 return render(request, 'abs_conf.html', kwargs)
175 175
176 176 def abs_conf_mqtt(request, id_conf):
177 print("Estoy en abs_conf_mqtt",flush=True)
177 # print("Estoy en abs_conf_mqtt",flush=True)
178 178 conf = get_object_or_404(ABSConfiguration, pk=id_conf)
179 179 beams = ABSBeam.objects.filter(abs_conf=conf)
180 180 #------------Colors for Active Beam:-------------
181 181 all_status = {}
182 182 module_messages = json.loads(conf.module_messages)
183 183
184 184 kwargs = {}
185 185 kwargs['connected_modules'] = str(conf.connected_modules())+'/64'
186 186 kwargs['dev_conf'] = conf
187 187
188 188 if conf.operation_mode == 0:
189 189 kwargs['dev_conf_keys'] = ['label', 'operation_mode']
190 190 else:
191 191 kwargs['dev_conf_keys'] = ['label', 'operation_mode', 'operation_value']
192 192
193 193 kwargs['title'] = 'ABS Configuration'
194 194 kwargs['suptitle'] = 'Details'
195 195 kwargs['button'] = 'Edit Configuration'
196 196
197 197 if conf.active_beam != 0:
198 198 kwargs['active_beam'] = int(conf.active_beam)
199 199
200 200 kwargs['mqtt']=True
201 201 kwargs['beams'] = beams
202 202 kwargs['modules_status'] = all_status
203 203 kwargs['module_messages'] = module_messages
204 204 ###### SIDEBAR ######
205 205 kwargs.update(sidebar(conf=conf))
206 206 print("conf.active_beam: {}",format(conf.active_beam))
207 207
208 208 # print(conf.beam.pk)
209 209
210 210 return render(request, 'abs_conf_mqtt.html', kwargs)
211 211 # // console.log(beam.pk);
212 212 # // console.log(active_beam);
213 213 # def abs_conf_mqtt(request, id_conf):
214 214 # # socket.on('beams_ack',function(data){
215 215 # ack=data;
216 216 # console.log("ack")
217 217 # console.log(ack)
218 218 # })
219 219
220 220
221 221 def abs_conf_edit(request, id_conf):
222 222
223 223 conf = get_object_or_404(ABSConfiguration, pk=id_conf)
224 224
225 225 beams = ABSBeam.objects.filter(abs_conf=conf)
226 226
227 227 if request.method=='GET':
228 228 form = ABSConfigurationForm(instance=conf)
229 229
230 230 if request.method=='POST':
231 231 form = ABSConfigurationForm(request.POST, instance=conf)
232 232
233 233 if form.is_valid():
234 234 conf = form.save(commit=False)
235 235 conf.save()
236 236 return redirect('url_abs_conf_mqtt', id_conf=conf.id)
237 237
238 238 ###### SIDEBAR ######
239 239 kwargs = {}
240 240
241 241 kwargs['dev_conf'] = conf
242 242 #kwargs['id_dev'] = conf.id
243 243 kwargs['id_conf'] = conf.id
244 244 kwargs['form'] = form
245 245 kwargs['abs_beams'] = beams
246 246 kwargs['title'] = 'Device Configuration'
247 247 kwargs['suptitle'] = 'Edit'
248 248 kwargs['button'] = 'Save'
249 249 kwargs['mqtt']=True
250 250
251 251 kwargs['edit'] = True
252 252
253 253 return render(request, 'abs_conf_edit.html', kwargs)
254 254
255 255 @csrf_exempt
256 256 def abs_conf_alert(request):
257 257
258 258 if request.method == 'POST':
259 259 print (request.POST)
260 260 return HttpResponse(json.dumps({'result':1}), content_type='application/json')
261 261 else:
262 262 return redirect('index')
263 263
264 264
265 265 def import_file(request, id_conf):
266 266
267 267 conf = get_object_or_404(ABSConfiguration, pk=id_conf)
268 268 if request.method=='POST':
269 269 form = ABSImportForm(request.POST, request.FILES)
270 270 if form.is_valid():
271 271 try:
272 272 parms = conf.import_from_file(request.FILES['file_name'])
273 273
274 274 if parms:
275 275 conf.update_from_file(parms)
276 276 messages.success(request, 'Configuration "%s" loaded succesfully' % request.FILES['file_name'])
277 277 return redirect(conf.get_absolute_url_edit())
278 278
279 279 except Exception as e:
280 280 messages.error(request, 'Error parsing file: "%s" - %s' % (request.FILES['file_name'], e))
281 281
282 282 else:
283 283 messages.warning(request, 'Your current configuration will be replaced')
284 284 form = ABSImportForm()
285 285
286 286 kwargs = {}
287 287 kwargs['form'] = form
288 288 kwargs['title'] = 'ABS Configuration'
289 289 kwargs['suptitle'] = 'Import file'
290 290 kwargs['button'] = 'Upload'
291 291 kwargs['previous'] = conf.get_absolute_url()
292 292
293 293 return render(request, 'abs_import.html', kwargs)
294 294
295 295
296 296 def send_beam(request, id_conf, id_beam):
297 297
298 298 conf = get_object_or_404(ABSConfiguration, pk=id_conf)
299 299
300 300 abs = Configuration.objects.filter(pk=conf.device.conf_active).first()
301 301 if abs!=conf:
302 302 url = '#' if abs is None else abs.get_absolute_url()
303 303 label = 'None' if abs is None else abs.label
304 304 messages.warning(
305 305 request,
306 306 mark_safe('The current configuration has not been written in the modules, the active configuration is <a href="{}">{}</a>'.format(
307 307 url,
308 308 label
309 309 ))
310 310 )
311 311 return redirect(conf.get_absolute_url())
312 312
313 313 beam = get_object_or_404(ABSBeam, pk=id_beam)
314 314
315 315 if request.method == 'POST':
316 316
317 317 beams_list = ABSBeam.objects.filter(abs_conf=conf)
318 318 conf.active_beam = id_beam
319 319
320 320 i = 0
321 321 for b in beams_list:
322 322 if b.id == int(id_beam):
323 323 break
324 324 else:
325 325 i += 1
326 326 beam_pos = i + 1 #Estandarizar
327 327 print('{} Position {}'.format(beam.name,str(beam_pos)))
328 328 conf.send_beam(beam_pos)
329 329
330 330 return redirect('url_abs_conf', conf.id)
331 331
332 332 kwargs = {
333 333 'title': 'ABS',
334 334 'suptitle': conf.label,
335 335 'message': 'Are you sure you want to change ABS Beam through SEND BEAM to: {}?'.format(beam.name),
336 336 'delete': False
337 337 }
338 338 kwargs['menu_configurations'] = 'active'
339 339
340 340 return render(request, 'confirm.html', kwargs)
341 341
342 342 def change_beam_mqtt(request, id_conf, id_beam):
343 343
344 344 conf = get_object_or_404(ABSConfiguration, pk=id_conf)
345 print("conf: {}".format(conf),flush=True)
345 # print("conf: {}".format(conf),flush=True)
346 346
347 347 abs = Configuration.objects.filter(pk=conf.device.conf_active).first()
348 print("abs: {}".format(abs),flush=True)
348 # print("abs: {}".format(abs),flush=True)
349 349 if abs!=conf:
350 350 url = '#' if abs is None else abs.get_absolute_url()
351 351 label = 'None' if abs is None else abs.label
352 352 messages.warning(
353 353 request,
354 354 mark_safe('The current configuration has not been written in the modules, the active configuration is <a href="{}">{}</a>'.format(
355 355 url,
356 356 label
357 357 ))
358 358 )
359 359 return redirect(conf.get_absolute_mqtt_url())
360 360
361 361 beams = ABSBeam.objects.filter(abs_conf=conf)
362 362 beam = get_object_or_404(ABSBeam, pk=id_beam)
363 363
364 364 if request.method == 'POST':
365 365
366 366 beams_list = ABSBeam.objects.filter(abs_conf=conf)
367 367 conf.active_beam = id_beam
368 368
369 369 i = 0
370 370 for b in beams_list:
371 371 if b.id == int(id_beam):
372 372 break
373 373 else:
374 374 i += 1
375 375 beam_pos = i + 1 #Estandarizar
376 376
377 377 print('{} Position {}'.format(beam.name,str(beam_pos)),flush=True)
378 378 conf.change_beam_mqtt(beam_pos)
379 379
380 380 # return redirect('url_abs_conf', conf.id)
381 381 return redirect('url_abs_conf_mqtt', conf.id)
382 382 # return render(request, 'abs_conf_mqtt.html',kwargs)
383 383
384 384 kwargs = {
385 385 'title': 'ABS',
386 386 'mqtt':True,
387 387 'suptitle': conf.label,
388 388 'message': 'Are you sure you want to change ABS Beam through MQTT to: {}?'.format(beam.name),
389 389 'delete': False
390 390 }
391 391 kwargs['menu_configurations'] = 'active'
392 392
393 393 return render(request, 'confirm.html', kwargs)
394 394
395 395 def add_beam(request, id_conf):
396 396
397 397 conf = get_object_or_404(ABSConfiguration, pk=id_conf)
398 398 confs = Configuration.objects.all()
399 399
400 400 if request.method=='GET':
401 401 form = ABSBeamAddForm()
402 402
403 403 if request.method=='POST':
404 404 form = ABSBeamAddForm(request.POST)
405 405
406 406 beam_data = get_values_from_form(request.POST)
407 407
408 408 new_beam = ABSBeam(
409 409 name = beam_data['name'],
410 410 antenna = json.dumps(beam_data['antenna']),
411 411 abs_conf = conf,
412 412 tx = json.dumps(beam_data['tx']),
413 413 rx = json.dumps(beam_data['rx']),
414 414 ues = json.dumps(beam_data['ues']),
415 415 only_rx = json.dumps(beam_data['only_rx'])
416 416 )
417 417 new_beam.save()
418 418 messages.success(request, 'Beam: "%s" has been added.' % new_beam.name)
419 419
420 420 return redirect('url_edit_abs_conf', conf.id)
421 421
422 422 ###### SIDEBAR ######
423 423 kwargs = {}
424 424
425 425 #kwargs['dev_conf'] = conf.device
426 426 #kwargs['id_dev'] = conf.device
427 427 #kwargs['previous'] = conf.get_absolute_url_edit()
428 428 kwargs['id_conf'] = conf.id
429 429 kwargs['form'] = form
430 430 kwargs['title'] = 'ABS Beams'
431 431 kwargs['suptitle'] = 'Add Beam'
432 432 kwargs['button'] = 'Add'
433 433 kwargs['no_sidebar'] = True
434 434 kwargs['edit'] = True
435 435
436 436 return render(request, 'abs_add_beam.html', kwargs)
437 437
438 438
439 439 def edit_beam(request, id_conf, id_beam):
440 440
441 441 conf = get_object_or_404(ABSConfiguration, pk=id_conf)
442 442 beam = get_object_or_404(ABSBeam, pk=id_beam)
443 443
444 444 if request.method=='GET':
445 445 form = ABSBeamEditForm(initial={'beam': beam})
446 446
447 447 if request.method=='POST':
448 448 form = ABSBeamEditForm(request.POST)
449 449
450 450 beam_data = get_values_from_form(request.POST)
451 451
452 452 beam.dict_to_parms(beam_data)
453 453 beam.save()
454 454
455 455 messages.success(request, 'Beam: "%s" has been updated.' % beam.name)
456 456
457 457 return redirect('url_edit_abs_conf', conf.id)
458 458
459 459 ###### SIDEBAR ######
460 460 kwargs = {}
461 461
462 462 kwargs['id_conf'] = conf.id
463 463 kwargs['form'] = form
464 464 kwargs['title'] = 'ABS Beams'
465 465 kwargs['suptitle'] = 'Edit Beam'
466 466 kwargs['button'] = 'Save'
467 467 kwargs['no_sidebar'] = True
468 468
469 469 #kwargs['previous'] = conf.get_absolute_url_edit()
470 470 kwargs['edit'] = True
471 471
472 472 return render(request, 'abs_edit_beam.html', kwargs)
473 473
474 474
475 475
476 476 def remove_beam(request, id_conf, id_beam):
477 477
478 478 conf = get_object_or_404(ABSConfiguration, pk=id_conf)
479 479 beam = get_object_or_404(ABSBeam, pk=id_beam)
480 480
481 481 if request.method=='POST':
482 482 if beam:
483 483 try:
484 484 beam.delete()
485 485 messages.success(request, 'Beam: "%s" has been deleted.' % beam)
486 486 except:
487 487 messages.error(request, 'Unable to delete beam: "%s".' % beam)
488 488
489 489 return redirect('url_edit_abs_conf', conf.id)
490 490
491 491 ###### SIDEBAR ######
492 492 kwargs = {}
493 493
494 494 kwargs['object'] = beam
495 495 kwargs['delete'] = True
496 496 kwargs['title'] = 'Delete'
497 497 kwargs['suptitle'] = 'Beam'
498 498 kwargs['previous'] = conf.get_absolute_url_edit()
499 499 return render(request, 'confirm.html', kwargs)
500 500
501 501
502 502
503 503 def plot_patterns(request, id_conf, id_beam=None):
504 504
505 505 kwargs = {}
506 506 conf = get_object_or_404(ABSConfiguration, pk=id_conf)
507 507 beams = ABSBeam.objects.filter(abs_conf=conf)
508 508
509 509 if id_beam:
510 510 beam = get_object_or_404(ABSBeam, pk=id_beam)
511 511 kwargs['beam'] = beam
512 512
513 513 ###### SIDEBAR ######
514 514
515 515 kwargs['dev_conf'] = conf.device
516 516 kwargs['id_dev'] = conf.device
517 517 kwargs['id_conf'] = conf.id
518 518 kwargs['abs_beams'] = beams
519 519 kwargs['title'] = 'ABS Patterns'
520 520 kwargs['suptitle'] = conf.name
521 521 kwargs['no_sidebar'] = True
522 522
523 523 return render(request, 'abs_patterns.html', kwargs)
524 524
525 525
526 526 def plot_pattern(request, id_conf, id_beam, antenna):
527 527
528 528 if antenna=='down':
529 529 sleep(3)
530 530
531 531 conf = get_object_or_404(ABSConfiguration, pk=id_conf)
532 532 beam = get_object_or_404(ABSBeam, pk=id_beam)
533 533 just_rx = 1 if json.loads(beam.only_rx)[antenna] else 0
534 534 phases = json.loads(beam.antenna)['antenna_{}'.format(antenna)]
535 535 gain_tx = json.loads(beam.tx)[antenna]
536 536 gain_rx = json.loads(beam.rx)[antenna]
537 537 ues = json.loads(beam.ues)[antenna]
538 538 newOverJro = overJroShow(beam.name)
539 539 fig = newOverJro.plotPattern2(datetime.today(), phases, gain_tx, gain_rx, ues, just_rx)
540 540 buf = io.BytesIO()
541 541 fig.savefig(buf, format='png')
542 542 response = HttpResponse(buf.getvalue(), content_type='image/png')
543 543 return response
544 544
545 545 import os
546 546 from django.http import HttpResponse
547 547
548 548 @sio.on('connection-bind')
549 549 def abs_connection_bind(sid, data):
550 550 print("sid:",sid,"data",data)
551 551
552 552 @sio.on('disconnect')
553 553 def abs_test_disconnect(sid):
554 554 print("Disconnected")
555 555
556 556 @sio.event
557 557 def abs_send_beam_up(sid, message):
558 558 mqtt_client.publish('abs/beams_up', message['data'])
559 559
560 560 @sio.event
561 561 def abs_send_beam_down(sid, message):
562 562 mqtt_client.publish('abs/beams_down', message['data'])
563 563
564 564 # @sio.event
565 565 # def change_beam(sid,message):
566 566 # data=str(message['data'])
567 567 # data=data[16]
568 568 # mqtt_client.publish('abs/change_beam',data)
569 569
570 570
571 571
572 572
573 573
574 574
@@ -1,284 +1,289
1 1 from django.db import models
2 2 from apps.main.models import Configuration
3 3 from apps.main.utils import Params
4 4 from django.core.validators import MinValueValidator, MaxValueValidator
5 5
6 6 from .files import read_json_file
7 7 import requests
8 8
9 9 class ATRADData(models.Model):
10 10 datetime = models.DateTimeField()
11 11
12 12 nstx = models.SmallIntegerField()
13 13
14 14 status_1 = models.SmallIntegerField()
15 15 temp_cll_1 = models.SmallIntegerField()
16 16 nboards_1 = models.SmallIntegerField()
17 17 tempdvr_1 = models.SmallIntegerField()
18 18 potincdvr_1 = models.SmallIntegerField()
19 19 potretdvr_1 = models.SmallIntegerField()
20 20
21 21 temp1_1 = models.SmallIntegerField()
22 22 potinc1_1 = models.SmallIntegerField()
23 23 potret1_1 = models.SmallIntegerField()
24 24 temp2_1 = models.SmallIntegerField()
25 25 potinc2_1 = models.SmallIntegerField()
26 26 potret2_1 = models.SmallIntegerField()
27 27 temp3_1 = models.SmallIntegerField()
28 28 potinc3_1 = models.SmallIntegerField()
29 29 potret3_1 = models.SmallIntegerField()
30 30 temp4_1 = models.SmallIntegerField()
31 31 potinc4_1 = models.SmallIntegerField()
32 32 potret4_1 = models.SmallIntegerField()
33 33 temp5_1 = models.SmallIntegerField()
34 34 potinc5_1 = models.SmallIntegerField()
35 35 potret5_1 = models.SmallIntegerField()
36 36 temp6_1 = models.SmallIntegerField()
37 37 potinc6_1 = models.SmallIntegerField()
38 38 potret6_1 = models.SmallIntegerField()
39 39
40 40 status_2 = models.SmallIntegerField()
41 41 temp_cll_2 = models.SmallIntegerField()
42 42 nboards_2 = models.SmallIntegerField()
43 43 tempdvr_2 = models.SmallIntegerField()
44 44 potincdvr_2 = models.SmallIntegerField()
45 45 potretdvr_2 = models.SmallIntegerField()
46 46
47 47 temp1_2 = models.SmallIntegerField()
48 48 potinc1_2 = models.SmallIntegerField()
49 49 potret1_2 = models.SmallIntegerField()
50 50 temp2_2 = models.SmallIntegerField()
51 51 potinc2_2 = models.SmallIntegerField()
52 52 potret2_2 = models.SmallIntegerField()
53 53 temp3_2 = models.SmallIntegerField()
54 54 potinc3_2 = models.SmallIntegerField()
55 55 potret3_2 = models.SmallIntegerField()
56 56 temp4_2 = models.SmallIntegerField()
57 57 potinc4_2 = models.SmallIntegerField()
58 58 potret4_2 = models.SmallIntegerField()
59 59 temp5_2 = models.SmallIntegerField()
60 60 potinc5_2 = models.SmallIntegerField()
61 61 potret5_2 = models.SmallIntegerField()
62 62 temp6_2 = models.SmallIntegerField()
63 63 potinc6_2 = models.SmallIntegerField()
64 64 potret6_2 = models.SmallIntegerField()
65 65
66 66 status_3 = models.SmallIntegerField()
67 67 temp_cll_3 = models.SmallIntegerField()
68 68 nboards_3 = models.SmallIntegerField()
69 69 tempdvr_3 = models.SmallIntegerField()
70 70 potincdvr_3 = models.SmallIntegerField()
71 71 potretdvr_3 = models.SmallIntegerField()
72 72
73 73 temp1_3 = models.SmallIntegerField()
74 74 potinc1_3 = models.SmallIntegerField()
75 75 potret1_3 = models.SmallIntegerField()
76 76 temp2_3 = models.SmallIntegerField()
77 77 potinc2_3 = models.SmallIntegerField()
78 78 potret2_3 = models.SmallIntegerField()
79 79 temp3_3 = models.SmallIntegerField()
80 80 potinc3_3 = models.SmallIntegerField()
81 81 potret3_3 = models.SmallIntegerField()
82 82 temp4_3 = models.SmallIntegerField()
83 83 potinc4_3 = models.SmallIntegerField()
84 84 potret4_3 = models.SmallIntegerField()
85 85 temp5_3 = models.SmallIntegerField()
86 86 potinc5_3 = models.SmallIntegerField()
87 87 potret5_3 = models.SmallIntegerField()
88 88 temp6_3 = models.SmallIntegerField()
89 89 potinc6_3 = models.SmallIntegerField()
90 90 potret6_3 = models.SmallIntegerField()
91 91
92 92 status_4 = models.SmallIntegerField()
93 93 temp_cll_4 = models.SmallIntegerField()
94 94 nboards_4 = models.SmallIntegerField()
95 95 tempdvr_4 = models.SmallIntegerField()
96 96 potincdvr_4 = models.SmallIntegerField()
97 97 potretdvr_4 = models.SmallIntegerField()
98 98
99 99 temp1_4 = models.SmallIntegerField()
100 100 potinc1_4 = models.SmallIntegerField()
101 101 potret1_4 = models.SmallIntegerField()
102 102 temp2_4 = models.SmallIntegerField()
103 103 potinc2_4 = models.SmallIntegerField()
104 104 potret2_4 = models.SmallIntegerField()
105 105 temp3_4 = models.SmallIntegerField()
106 106 potinc3_4 = models.SmallIntegerField()
107 107 potret3_4 = models.SmallIntegerField()
108 108 temp4_4 = models.SmallIntegerField()
109 109 potinc4_4 = models.SmallIntegerField()
110 110 potret4_4 = models.SmallIntegerField()
111 111 temp5_4 = models.SmallIntegerField()
112 112 potinc5_4 = models.SmallIntegerField()
113 113 potret5_4 = models.SmallIntegerField()
114 114 temp6_4 = models.SmallIntegerField()
115 115 potinc6_4 = models.SmallIntegerField()
116 116 potret6_4 = models.SmallIntegerField()
117 117
118 combiner1 = models.SmallIntegerField()
119 combiner2 = models.SmallIntegerField()
120 combiner3 = models.SmallIntegerField()
121 combiner4 = models.SmallIntegerField()
122
118 123 class Meta:
119 124 db_table = 'atrad_datas'
120 125
121 126 def __unicode__(self):
122 127 return u'%s' % (self.name)
123 128
124 129 class ATRADConfiguration(Configuration):
125 130
126 131 topic = models.PositiveIntegerField(verbose_name='Topic',validators=[MaxValueValidator(10)], default = 0)
127 132
128 133 def status_device(self):
129 134
130 135 ip=self.device.ip_address
131 136 port=self.device.port_address
132 137
133 138 route = "http://" + str(ip) + ":" + str(port) + "/status/"
134 139 try:
135 140 r = requests.get(route, timeout=0.7)
136 141 except Exception as e:
137 142 self.device.status = 0
138 143 self.device.save()
139 144 self.message = 'Could not read TX status: ' + str(e)
140 145 return False
141 146
142 147 response = r.json()
143 148 self.device.status = response['status']
144 149 self.message = response['message']
145 150 self.device.save()
146 151
147 152 if response['components_status']==0:
148 153 return False
149 154
150 155 return True
151 156
152 157
153 158 def start_device(self):
154 159
155 160 ip=self.device.ip_address
156 161 port=self.device.port_address
157 162
158 163 #---Device must be configured
159 164 if not self.device.status == 2:
160 165 self.message = 'TX Device must be configured.'
161 166 return False
162 167 #---Frequencies from form
163 168 post_data = self.parms_to_dict()
164 169 route = "http://" + str(ip) + ":" + str(port) + "/write/"
165 170
166 171 try:
167 172 r = requests.post(route, post_data, timeout=0.7)
168 173 except Exception as e:
169 174 self.message = "Could not start TX device. "+str(e)
170 175 return False
171 176
172 177 response = r.json()
173 178 if response['status']==1:
174 179 self.device.status = 1
175 180 self.device.save()
176 181 self.message = response['message']
177 182 return False
178 183
179 184 self.device.status = response['status']
180 185 self.device.save()
181 186 self.message = response['message']
182 187
183 188 return True
184 189
185 190
186 191 def stop_device(self):
187 192
188 193 ip=self.device.ip_address
189 194 port=self.device.port_address
190 195
191 196 if self.device.status == 2: #Configured
192 197 self.message = 'TX device is already stopped.'
193 198 return False
194 199
195 200 post_data = {"topic":0}
196 201 route = "http://" + str(ip) + ":" + str(port) + "/write/"
197 202
198 203 try:
199 204 r = requests.post(route, post_data, timeout=0.7)
200 205 except Exception as e:
201 206 self.message = "Could not write TX parameters. "+str(e)
202 207 self.device.status = 0
203 208 self.device.save()
204 209 return False
205 210
206 211 response = r.json()
207 212 status = response['status']
208 213 if status == 1:
209 214 self.device.status = status
210 215 self.device.save()
211 216 self.message = 'Could not stop TX device.'
212 217 return False
213 218
214 219 self.message = 'TX device has been stopped successfully.'
215 220 self.device.status = 2
216 221 self.device.save()
217 222
218 223 return True
219 224
220 225
221 226 def read_device(self):
222 227
223 228 ip=self.device.ip_address
224 229 port=self.device.port_address
225 230
226 231 route = "http://" + str(ip) + ":" + str(port) + "/read/"
227 232 try:
228 233 frequencies = requests.get(route,timeout=0.7)
229 234 except:
230 235 self.message = "Could not read TX parameters from this device"
231 236 return None
232 237
233 238 frequencies = frequencies.json()
234 239 if frequencies:
235 240 frequencies = frequencies.get("Frequencies")
236 241 topic = frequencies.get("topic")
237 242
238 243 parms = {'topic': topic}
239 244
240 245 self.message = "TX parameters have been successfully read"
241 246 return parms
242 247 else:
243 248 self.message = "Error reading TX parameters"
244 249 return None
245 250
246 251
247 252 def write_device(self):
248 253
249 254 ip=self.device.ip_address
250 255 port=self.device.port_address
251 256
252 257 #---Frequencies from form
253 258 parms = self.parms_to_dict()['configurations']
254 259 for parm in parms['allIds']:
255 260 byid = parm
256 261 frequencies = parms['byId'][byid]
257 262 post_data = {}
258 263 for data in frequencies:
259 264 if data in ['topic']:
260 265 post_data[data] = frequencies[data]
261 266
262 267 route = "http://" + str(ip) + ":" + str(port) + "/write/"
263 268 print (post_data)
264 269 try:
265 270 r = requests.post(route, post_data, timeout=0.7)
266 271 except:
267 272 self.message = "Could not write TX parameters"
268 273 self.device.status = 0
269 274 self.device.save()
270 275 return False
271 276
272 277 response = r.json()
273 278 self.message = response['message']
274 279 self.device.status = response['status']
275 280 self.device.save()
276 281
277 282 if self.device.status==1:
278 283 return False
279 284
280 285 return True
281 286
282 287
283 288 class Meta:
284 289 db_table = 'atrad_configurations' No newline at end of file
@@ -1,127 +1,129
1 1 import paho.mqtt.client as mqtt
2 2 from radarsys import settings
3 3 from radarsys.socketconfig import sio as sio
4 4 import numpy as np
5 5 import psycopg2
6 6 import os
7 7
8 8 def insert(time,data):
9 9 sql = """INSERT INTO atrad_datas(
10 10 datetime,nstx,status_1,temp_cll_1,nboards_1,tempdvr_1,potincdvr_1,potretdvr_1,
11 11 temp1_1,potinc1_1,potret1_1,temp2_1,potinc2_1,potret2_1,temp3_1,potinc3_1,potret3_1,
12 12 temp4_1,potinc4_1,potret4_1,temp5_1,potinc5_1,potret5_1,temp6_1,potinc6_1,potret6_1,
13 13 status_2,temp_cll_2,nboards_2,tempdvr_2,potincdvr_2,potretdvr_2,
14 14 temp1_2,potinc1_2,potret1_2,temp2_2,potinc2_2,potret2_2,temp3_2,potinc3_2,potret3_2,
15 15 temp4_2,potinc4_2,potret4_2,temp5_2,potinc5_2,potret5_2,temp6_2,potinc6_2,potret6_2,
16 16 status_3,temp_cll_3,nboards_3,tempdvr_3,potincdvr_3,potretdvr_3,
17 17 temp1_3,potinc1_3,potret1_3,temp2_3,potinc2_3,potret2_3,temp3_3,potinc3_3,potret3_3,
18 18 temp4_3,potinc4_3,potret4_3,temp5_3,potinc5_3,potret5_3,temp6_3,potinc6_3,potret6_3,
19 19 status_4,temp_cll_4,nboards_4,tempdvr_4,potincdvr_4,potretdvr_4,
20 20 temp1_4,potinc1_4,potret1_4,temp2_4,potinc2_4,potret2_4,temp3_4,potinc3_4,potret3_4,
21 temp4_4,potinc4_4,potret4_4,temp5_4,potinc5_4,potret5_4,temp6_4,potinc6_4,potret6_4)
21 temp4_4,potinc4_4,potret4_4,temp5_4,potinc5_4,potret5_4,temp6_4,potinc6_4,potret6_4,
22 combiner1,combiner2,combiner3,combiner4)
22 23 VALUES(%s,%s,%s,%s,%s,%s,%s,%s,
23 24 %s,%s,%s,%s,%s,%s,%s,%s,%s,
24 25 %s,%s,%s,%s,%s,%s,%s,%s,%s,
25 26 %s,%s,%s,%s,%s,%s,
26 27 %s,%s,%s,%s,%s,%s,%s,%s,%s,
27 28 %s,%s,%s,%s,%s,%s,%s,%s,%s,
28 29 %s,%s,%s,%s,%s,%s,
29 30 %s,%s,%s,%s,%s,%s,%s,%s,%s,
30 31 %s,%s,%s,%s,%s,%s,%s,%s,%s,
31 32 %s,%s,%s,%s,%s,%s,
32 33 %s,%s,%s,%s,%s,%s,%s,%s,%s,
33 %s,%s,%s,%s,%s,%s,%s,%s,%s);"""
34 %s,%s,%s,%s,%s,%s,%s,%s,%s,
35 %s,%s,%s,%s);"""
34 36 try:
35 37 # connect to the PostgreSQL database
36 38 conn = psycopg2.connect(database="radarsys", user='docker', password='docker', host='radarsys-postgres', port= '5432')
37 39 # create a new cursor
38 40 cur = conn.cursor()
39 41 # execute the INSERT statement
40 42 #data_tuple = [tuple(i[:]) for i in a]
41 values = (time,) + tuple(data[0][:25])+tuple(data[1][1:25])+tuple(data[2][1:25])+tuple(data[3][1:25])
43 values = (time,) + tuple(data[0][:25])+tuple(data[1][1:25])+tuple(data[2][1:25])+tuple(data[3][1:25]) + tuple(data[0][29:31]) +tuple(data[2][27:29])
42 44 cur.execute(sql, values)
43 45
44 46 # get the generated id back
45 47 #vendor_id = cur.fetchone()[0]
46 48
47 49 # commit the changes to the database
48 50 conn.commit()
49 51 # close communication with the database
50 52 cur.close()
51 53 except (Exception, psycopg2.DatabaseError) as error:
52 54 print(error)
53 55 finally:
54 56 if conn is not None:
55 57 conn.close()
56 58
57 59 def maxTemperature(trs):
58 60 temps = GetTemperatures(trs)
59 61 maxT_STX = [max(i) for i in temps]
60 62 maxT = max(maxT_STX)
61 63 STXnum = maxT_STX.index(maxT)
62 64 STXloc = temps[STXnum].index(maxT)
63 65 maxT_loc = 'Amp ' + str(STXnum+1)
64 66
65 67 if STXloc == 0:
66 68 maxT_loc = maxT_loc + " Controller"
67 69 elif STXloc == 1:
68 70 maxT_loc = maxT_loc + " Driver"
69 71 elif STXloc<8:
70 72 maxT_loc = maxT_loc + " PA " + str(STXloc-1)
71 73 else:
72 74 maxT_loc = maxT_loc + " Combiners"
73 75
74 76 return maxT,maxT_loc,temps
75 77
76 78 def dataConvert(msg):
77 79 msgStr = str(msg.payload)
78 80 msgClean = [i for i in msgStr[21:-1].split("*")]
79 81 dataSTX = [[],[],[],[]]
80 82 for trs,i in zip(msgClean,[0,1,2,3]) :
81 83 dataSTX[i]= [int(i) for i in trs[1:-1].split(",")]
82 84 # Data to database
83 85 insert(msgStr[2:21],dataSTX)
84 86 # Data to send by socket
85 87 id_STX = dataSTX[0][0] // 4
86 88 status = ''.join([msgClean[i][3] for i in [0,1,2,3]])
87 89 powers = [dataSTX[0][34],dataSTX[0][36],dataSTX[2][32],dataSTX[2][34],0,0,0,0]
88 90 # alerta
89 91 for i in range(4):
90 92 if powers[i] < 10000 and status == '1111':
91 93 power[4+i] = 1
92 94
93 95 tmax,index,tempData = maxTemperature(dataSTX)
94 96 #Json to send
95 97 data = {'time':msgStr[2:21],'num':id_STX,'pow':powers,'tmax':[str(tmax),index],'status':status}
96 98 data_temp = {'time':msgStr[2:21],'temp':tempData}
97 99 return data, data_temp
98 100
99 101 def GetTemperatures(data):
100 102 np_data = [np.array(i) for i in data]
101 103 temps = [i[i<40] for i in np_data]
102 104 return [i[i>15].tolist() for i in temps]
103 105
104 106 def on_connect(mqtt_client, userdata, flags, rc):
105 107 if rc == 0:
106 print('Connected successfullyasdss')
107 mqtt_client.subscribe("atrad/test4")
108 print("Exito")
108 # print('Connected successfullyasdss')
109 mqtt_client.subscribe(os.environ.get('MQTT_TOPIC_ATRAD_RECIEVE', 'atrad/test4'))
110 # print("Exito")
109 111 else:
110 112 print('Bad connection. Code:', rc)
111 113
112 114 def on_message(mqtt_client, userdata, msg):
113 115 print('Received message on topic: {} with payload: {}'.format(msg.topic,msg.payload), flush=True)
114 116 mainData, tempData = dataConvert(msg)
115 117 sio.emit('test',data = mainData)
116 118 #socket for temperature details
117 119 sio.emit('temptx'+str(mainData['num'] + 1),data = tempData)
118 120
119 121 client = mqtt.Client()
120 122 client.on_connect = on_connect
121 123 client.on_message = on_message
122 124 client.username_pw_set( '','')
123 125 client.connect(
124 126 host=os.environ.get('MQTT_SERVER', '10.10.10.200'),
125 127 port=int(settings.os.environ.get('MQTT_PORT', 1883)),
126 128 keepalive=int(os.environ.get('MQTT_KEEPALIVE', 60))
127 129 ) No newline at end of file
@@ -1,283 +1,283
1 1 {% extends "dev_conf.html" %}
2 2 {% load static %}
3 3 {% block extra-head %}
4 4 <style>
5 5 .dot {
6 6 height: 25px;
7 7 width: 25px;
8 8 background-color: #b0b3af;
9 9 border-radius: 50%;
10 10 display: inline-block;
11 11 }
12 12 .row{
13 13 margin-top: 3px;
14 14 margin-bottom: 3px;
15 15 }
16 16 .th {
17 17 vertical-align: middle;
18 18 }
19 19 </style>
20 20 <link href="https://cdn.jsdelivr.net/gh/gitbrent/bootstrap4-toggle@3.6.1/css/bootstrap4-toggle.min.css" rel="stylesheet">
21 21 {% endblock %}
22 22
23 23 {% block content-graph %}
24 24 <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.3/jquery.min.js"></script>
25 25 <script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/socket.io/4.4.1/socket.io.min.js"></script>
26 26
27 27 <div class="container-fluid">
28 28 <h1 class="py-4 text-center" >ATRAD Monitoring</h1>
29 29
30 30 <!-- First row : Control-->
31 31 <div class="row">
32 32 <div class="card border-light">
33 33 <div class="card-body">
34 34 <h3 class="card-title">Control</h3>
35 35 <table class="table table-borderless">
36 36 <tbody>
37 37 <tr>
38 38 <th class="align-middle">Tx1</th>
39 39 <td>
40 40 <button type="button" class="btn btn-outline-success" id="ONBtn1"> ON </button>
41 41 <button type="button" class="btn btn-outline-danger" id="OFFBtn1"> OFF </button>
42 42 </td>
43 43 </tr>
44 44 <tr>
45 45 <th class="align-middle">Tx2</th>
46 46 <td>
47 47 <button type="button" class="btn btn-outline-success" id="ONBtn2"> ON </button>
48 48 <button type="button" class="btn btn-outline-danger" id="OFFBtn2"> OFF </button>
49 49 </td>
50 50 </tr>
51 51 </tbody>
52 52 </table>
53 53 </div>
54 54 </div>
55 55 </div>
56 56
57 57 <!-- Second row : Status and alerts -->
58 58 <div class="row">
59 <div class="card-deck" style="width: 90%;">
59 <div class="card-deck" style="width: 100%;">
60 60 <div class="card border-light">
61 61 <div class="card-body">
62 62 <h4 class="card-title">Status</h4>
63 63 <table class="table table-borderless">
64 64 <tbody>
65 65 <tr>
66 66 <th scope="row">Tx1</th>
67 67 <td><span id="status1" class="dot"></span></td>
68 68 <td><p id="status-text1" class="font-weight-bold">No data</p></td>
69 69 </tr>
70 70 <tr>
71 71 <th scope="row">Tx2</th>
72 72 <td><span id="status2" class="dot"></span></td>
73 73 <td><p id="status-text2" class="font-weight-bold">No data</p></td>
74 74 </tr>
75 75 </tbody>
76 76 </table>
77 77 </div>
78 78 </div>
79 79 <div class="card border-light">
80 80 <div class="card-body">
81 81 <h4 class="card-title">High Temperature Alerts</h4>
82 82 <table class="table table-borderless">
83 83 <tbody>
84 84 <tr>
85 85 <th scope="row"><p id="alerttemp-time1" class="font-weight-bold"></p></th>
86 86 <td><p id="alerttemp-1" class="font-weight-bold"></p></td>
87 87 <td><p id="alerttemp-loc1" class="font-weight-bold"></p></td>
88 88 </tr>
89 89 <tr>
90 90 <th scope="row"><p id="alerttemp-time2" class="font-weight-bold"></p></th>
91 91 <td><p id="alerttemp-2" class="font-weight-bold"></p></td>
92 92 <td><p id="alerttemp-loc2" class="font-weight-bold"></p></td>
93 93 </tr>
94 94 </tbody>
95 95 </table>
96 96 </div>
97 97 </div>
98 98 <div class="card border-light">
99 99 <div class="card-body">
100 100 <h4 class="card-title">Power Alerts</h4>
101 101 <table class="table table-borderless">
102 102 <tbody>
103 103 <tr>
104 104 <th scope="row"><p id="alertpot-time1" class="font-weight-bold"></p></th>
105 105 <td><p id="alertpot-1" class="font-weight-bold"></p></td>
106 106 <td><p id="alertpot-loc1" class="font-weight-bold"></p></td>
107 107 </tr>
108 108 <tr>
109 109 <th scope="row"><p id="alertpot-time2" class="font-weight-bold"></p></th>
110 110 <td><p id="alertpot-2" class="font-weight-bold"></p></td>
111 111 <td><p id="alertpot-loc2" class="font-weight-bold"></p></td>
112 112 </tr>
113 113 </tbody>
114 114 </table>
115 115 </div>
116 116 </div>
117 117 </div>
118 118 </div>
119 119
120 120 <!-- Third row : power graph-->
121 121 <div class="row ">
122 122 <div class="card border-light">
123 123 <div class="card-body">
124 124 <h3 class="card-title">Power graph</h3>
125 125 <div class="row justify-content-md-center">
126 126 <div class="col-md-9">
127 127 <div id="plot-pot"></div>
128 128 </div>
129 129 <div class="col-md-3 text-end">
130 130 <div class="card-body">
131 131 <table class="table" style="max-width:170px;">
132 132 <tbody>
133 133 <tr>
134 134 <th scope="col"># Tx</th>
135 135 <th scope="col">Power (kW)</th>
136 136 </tr>
137 137 <tr>
138 138 <th scope="row">1</th>
139 139 <td><p id="pot1"></p></td>
140 140 </tr>
141 141 <tr>
142 142 <th scope="row">2</th>
143 143 <td><p id="pot2"></p></td>
144 144 </tr>
145 145 </tbody>
146 146 </table>
147 147 </div>
148 148 <div class="card-body">
149 149 <button type="button" class="btn btn-primary" data-toggle="modal" data-target="#Pot-1">T1</button>
150 150 <button type="button" class="btn btn-primary" data-toggle="modal" data-target="#Pot-2">T2</button>
151 151 </div>
152 152 </div>
153 153 </div>
154 154 </div>
155 155 </div>
156 156 </div>
157 157 <!--Temperature Graph-->
158 158 <div class="row ">
159 159 <div class="card border-light">
160 160 <div class="card-body">
161 161 <h3 class="card-title">Temperature graph</h3>
162 162 <div class="row justify-content-md-center">
163 163 <div class="col-md-9">
164 164 <div id="plot-temp"></div>
165 165 </div>
166 166 <div class="col-md-3 text-end">
167 167 <div class="card-body">
168 168 <table class="table table-hover" style="max-width:170px;">
169 169 <tbody>
170 170 <tr>
171 171 <th scope="col"># Tx</th>
172 172 <th scope="col">Temperature (°C)</th>
173 173 </tr>
174 174 <tr class="clickable-row" data-href="{% url 'url_tx_atrad' dev_conf.id 'tx1' %}">
175 175 <th scope="row">1</th>
176 176 <td><p id="temp1"></p></td>
177 177 </tr>
178 178 <tr class="clickable-row" data-href="{% url 'url_tx_atrad' dev_conf.id 'tx2' %}">
179 179 <th scope="row">2</th>
180 180 <td><p id="temp2"></p></td>
181 181 </tr>
182 182 </tbody>
183 183 </table>
184 184 </div>
185 185 </div>
186 186 </div>
187 187 </div>
188 188 </div>
189 189 </div>
190 190 </div>
191 191
192 192 <!--Modales-->
193 193 <div class="modal fade" id="Pot-1" role="dialog">
194 <div class="modal-dialog modal-lg" style="max-width:50%;min-width:750px">
194 <div class="modal-dialog modal-lg" style="max-width:50%;min-width:928px">
195 195 <div class="modal-content">
196 196 <div class="modal-header">
197 <h4 class="modal-title">Potencia incidente - Transmisor 1</h4>
197 <h4 class="modal-title">Incident Power - Transmitter 1 </h4>
198 198 <button type="button" class="close" data-dismiss="modal">&times;</button>
199 199 </div>
200 200 <div class="modal-body">
201 201 <div class="row">
202 202 <div class="col">
203 203 <div id="plot-pot-t1"></div>
204 204 </div>
205 205 <div class="col">
206 206 <table class="table" style="max-width: 150px;">
207 207 <tbody>
208 208 <tr>
209 209 <th scope="col"># Amp</th>
210 <th scope="col">Potencia (kW)</th>
210 <th scope="col">Power (kW)</th>
211 211 </tr>
212 212 <tr>
213 213 <th scope="row">P1</th>
214 214 <td><p id="pot1-1"></p></td>
215 215 </tr>
216 216 <tr>
217 217 <th scope="row">P2</th>
218 218 <td><p id="pot1-2"></p></td>
219 219 </tr>
220 220 <tr>
221 221 <th scope="row">P3</th>
222 222 <td><p id="pot1-3"></p></td>
223 223 </tr>
224 224 <tr>
225 225 <th scope="row">P4</th>
226 226 <td><p id="pot1-4"></p></td>
227 227 </tr>
228 228 </tbody>
229 229 </table>
230 230 </div>
231 231 </div>
232 232 </div>
233 233 </div>
234 234 </div>
235 235 </div>
236 236
237 237 <div class="modal fade" id="Pot-2" role="dialog">
238 <div class="modal-dialog modal-lg" style="max-width:50%;min-width:750px">
238 <div class="modal-dialog modal-lg" style="max-width:50%;min-width:928px">
239 239 <div class="modal-content">
240 240 <div class="modal-header">
241 <h4 class="modal-title">Potencia incidente - Transmisor 2</h4>
241 <h4 class="modal-title">Incident Power - Transmitter 2</h4>
242 242 <button type="button" class="close" data-dismiss="modal">&times;</button>
243 243 </div>
244 244 <div class="modal-body">
245 245 <div class="row">
246 246 <div class="col">
247 247 <div id="plot-pot-t2"></div>
248 248 </div>
249 249 <div class="col">
250 250 <table class="table" style="max-width: 150px;">
251 251 <tbody>
252 252 <tr>
253 253 <th scope="col"># Amp</th>
254 <th scope="col">Potencia (kW)</th>
254 <th scope="col">Power (kW)</th>
255 255 </tr>
256 256 <tr>
257 257 <th scope="row">P1</th>
258 258 <td><p id="pot2-1"></p></td>
259 259 </tr>
260 260 <tr>
261 261 <th scope="row">P2</th>
262 262 <td><p id="pot2-2"></p></td>
263 263 </tr>
264 264 <tr>
265 265 <th scope="row">P3</th>
266 266 <td><p id="pot2-3"></p></td>
267 267 </tr>
268 268 <tr>
269 269 <th scope="row">P4</th>
270 270 <td><p id="pot2-4"></p></td>
271 271 </tr>
272 272 </tbody>
273 273 </table>
274 274 </div>
275 275 </div>
276 276 </div>
277 277 </div>
278 278 </div>
279 279 </div>
280 280
281 <script src="{% static 'js/atrad-conf.js' %}"></script>
281 <script src="{% static 'js/atrad-mainpage.js' %}"></script>
282 282
283 283 {% endblock %} No newline at end of file
@@ -1,168 +1,174
1 1 {% extends "base.html" %}
2 2 {% load static %}
3 3 {% block title %}ATRAD Tx{{id_tx}} Temperatures{% endblock %}
4 4 {% block content-title %}{{title}}{% endblock %}
5 5 {% block content-suptitle %}Tx {{id_tx}}{% endblock %}
6 6
7 7 {% block extra-head %}
8 8 <style>
9 9 .panel-body {
10 10 background:#ffffff;}
11 11 .panel-footer {
12 12 background:#ffffff;}
13 13 .card-body {
14 14 padding-top: 1px;
15 15 padding-bottom: 1px;
16 16 }
17 17 </style>
18 18 {% endblock %}
19 19
20 20 {% block content-graph %}
21 21 <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.3/jquery.min.js"></script>
22 22 <script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/socket.io/4.4.1/socket.io.min.js"></script>
23 23
24 24 <div class="container-fluid">
25 25 <!-- Temperatura generales -->
26 26 <div class="row ">
27 27 <div class="panel panel-default">
28 28 <div class="panel-heading">
29 <h3 class="panel-title">Amplifiers</h3>
29 <h3 class="panel-title">Amplifiers Temperature (°C)</h3>
30 30 </div>
31 31 <div class="panel-body">
32 32 <div class="card border-0">
33 33 <div class="row">
34 34 <div class="card-body">
35 35 <h5 class="card-title">Amplifier 1</h5>
36 36 <div id="plot-temp-1"></div>
37 37 </div>
38 38 <div class="card-body">
39 39 <h5 class="card-title">Amplifier 2</h5>
40 40 <div id="plot-temp-2"></div>
41 41 </div>
42 42 <div class="card-body">
43 43 <h5 class="card-title">Amplifier 3</h5>
44 44 <div id="plot-temp-3"></div>
45 45 </div>
46 46 <div class="card-body">
47 47 <h5 class="card-title">Amplifier 4</h5>
48 48 <div id="plot-temp-4"></div>
49 49 </div>
50 50 </div>
51 51 </div>
52 52 </div>
53 53 </div>
54 54 </div>
55 55 <div class="row">
56 56 <div class="panel panel-default">
57 57 <div class="panel-heading">
58 <h3 class="panel-title">Controllers and combiners</h3>
58 <h3 class="panel-title">Combiners Temperature °C</h3>
59 59 </div>
60 60 <div class="panel-body">
61 61 <div id="plot-temp-0"></div>
62 62 </div>
63 63 </div>
64 64 </div>
65 65 </div>
66 66
67 67 <script>
68 68 $(document).ready(function() {
69 69 var socket = io.connect('http://' + document.domain + ':' + location.port);
70 70 socket.on('connect', function(data) {
71 71 console.log('Connecting... OK');
72 72 var basedata = JSON.parse('{{data|safe}}')
73 73 console.log(basedata);
74 makePlot("plot-temp-0",4,["PC1","PC2","PC3","PC4"],[10,40]);
74 makePlot("plot-temp-0",4,["PC1","PC2","PC3","PC4"],[10,40],basedata);
75 75 makePlot2("plot-temp-1",6,["PA1","PA2","PA3","PA4","PA5","PA6"],[10,40],basedata)
76 76 makePlot2("plot-temp-2",6,["PA1","PA2","PA3","PA4","PA5","PA6"],[10,40],basedata)
77 77 makePlot2("plot-temp-3",6,["PA1","PA2","PA3","PA4","PA5","PA6"],[10,40],basedata)
78 78 makePlot2("plot-temp-4",6,["PA1","PA2","PA3","PA4","PA5","PA6"],[10,40],basedata)
79 79 })
80 80 socket.on("temptx"+"{{id_tx}}", function(data) {
81 var controllers = [data.temp[0][1],data.temp[1][1],data.temp[2][1],data.temp[3][1]]
81 var combiners = [data.temp[0][8],data.temp[0][9],data.temp[2][8],data.temp[2][9]]
82 82 streamPlot2("plot-temp-0",data.time,controllers,4);
83 83 streamPlot2("plot-temp-1",data.time,data.temp[0].slice(2,8),6);
84 84 streamPlot2("plot-temp-2",data.time,data.temp[1].slice(2,8),6);
85 85 streamPlot2("plot-temp-3",data.time,data.temp[2].slice(2,8),6);
86 86 streamPlot2("plot-temp-4",data.time,data.temp[3].slice(2,8),6);
87 87 })
88 88 });
89 89
90 function makePlot(div, n=1, names=["", ""],ranges){
90 function makePlot(div, n=1, names=["", ""],ranges,data){
91 91 var plotDiv = document.getElementById(div);
92 92 var traces = [];
93 var keys = ['combiner1','combiner2','combiner3','combiner4']
93 94 for (let i = 0; i < n; i++) {
94 traces.push({x: [], y: [],mode: 'lines', name: names[i]});
95 var x = [];
96 var y = [];
97 for(let j = 0;j < data.length; j++){
98 x[j] = data[j].datetime;
99 y[j] = data[j][keys[i]];
100 }
101 traces.push({x:x, y:y,mode: 'lines', name: names[i]});
95 102 }
96 traces.push({x: [], y: [],mode: 'lines',line: {color:'rgb(219, 64, 82)',dash: 'dot',width: 2},name:"nominal",showlegend: false});
97 103 var yrange = ranges;
98 104 var layout = {
99 105 width: 505,
100 106 height: 300,
101 107 font: {size: 12},
102 108 margin: { t: 10, b:50, r:15 ,l:15},
103 109 xaxis: {
104 110 type: 'date'
105 111 },
106 112 yaxis: {
107 113 range: yrange,
108 114 },
109 115 legend: {"orientation": "h"},
110 116 };
111 117 var config = {responsive: true}
112 118 Plotly.newPlot(plotDiv, traces, layout,config);
113 119 };
114 120
115 function makePlot2(div, n=1, names=["", ""],ranges,data){
121 function makePlot2(div, n=1, names=["", ""],ranges,data,keys){
116 122 var plotDiv = document.getElementById(div);
117 123 var traces = [];
118 124 var keys = ['temp1','temp2','temp3','temp4','temp5','temp6']
119 125
120 126 for (let i = 0; i < n; i++) {
121 127 var x = [];
122 128 var y = [];
123 129 for(let j = 0;j < data.length; j++){
124 130 x[j] = data[j].datetime;
125 131 y[j] = data[j][keys[i]+'_'+div.charAt(10)];
126 132 }
127 133 traces.push({x:x, y:y,mode: 'lines', name: names[i]});
128 134 }
129 135 var yrange = ranges;
130 136 var layout = {
131 137 width: 505,
132 height: 400,
138 height: 300,
133 139 font: {size: 12},
134 140 margin: { t: 10, b:50, r:15 ,l:15},
135 141 xaxis: {
136 142 type: 'date'
137 143 },
138 144 yaxis: {
139 145 range: yrange,
140 146 },
141 147 legend: {"orientation": "h"},
142 148 };
143 149 var config = {responsive: true}
144 150 Plotly.newPlot(plotDiv, traces, layout,config);
145 151 };
146 152
147 153 function streamPlot2(div,x,y,cant){
148 154 var plotDiv = document.getElementById(div);
149 155 if (plotDiv.data[0].x.length > 8){
150 156 for(let i=0;i<cant;i++){
151 157 plotDiv.data[i].x = plotDiv.data[i].x.slice(-11)
152 158 plotDiv.data[i].y = plotDiv.data[i].y.slice(-11)
153 159 }
154 160 }
155 161 var tm = [];
156 162 var values = [];
157 163 var index = []
158 164 for(let i=0;i<cant;i++){
159 165 values[i]=[y[i]];
160 166 tm[i] = [x];
161 167 index[i] = i;
162 168 }
163 169 var data_update = {x: tm, y: values}
164 170 Plotly.extendTraces(plotDiv, data_update,index)
165 171 };
166 172
167 173 </script>
168 174 {% endblock %} No newline at end of file
@@ -1,125 +1,133
1 1 from django.shortcuts import redirect, render, get_object_or_404
2 2 from django.contrib import messages
3 3 from django.http import HttpResponse
4 4 from django.template.loader import get_template
5 5
6 6 from apps.main.models import Experiment
7 7 from .models import ATRADConfiguration, ATRADData
8 8
9 9 from .forms import ATRADConfigurationForm, UploadFileForm
10 10 from apps.main.views import sidebar
11 11
12 12 import requests
13 13 import json
14 14
15 15 import os
16 16 from django.http import JsonResponse
17 17 from .mqtt import client as mqtt_client
18 18 from radarsys.socketconfig import sio as sio
19 19 from datetime import timedelta
20 from datetime import datetime
20 21
21 22 def atrad_conf(request, id_conf):
22 23
23 24 conf = get_object_or_404(ATRADConfiguration, pk=id_conf)
24 25
25 26 ip=conf.device.ip_address
26 27 port=conf.device.port_address
27 28
28 29 kwargs = {}
29 30
30 31 kwargs['status'] = conf.device.get_status_display()
31 32
32 33 kwargs['dev_conf'] = conf
33 34 kwargs['dev_conf_keys'] = ['label',
34 35 'topic']
35 36
36 37 kwargs['title'] = 'ATRAD Configuration'
37 38 kwargs['suptitle'] = 'Details'
38 39
39 40 kwargs['button'] = 'Edit Configuration'
40 41
41 42 #kwargs['no_play'] = True
42 43 ###### SIDEBAR ######
43 44 kwargs.update(sidebar(conf=conf))
44 45
45 46 return render(request, 'atrad_conf.html', kwargs)
46 47
47 48 def atrad_tx(request, id_conf, id_tx):
48 49 kwargs = {}
49 50 kwargs['id_tx'] = id_tx[-1]
50 51 kwargs['title'] = 'Temperature Details'
51 52 kwargs['button'] = 'Edit Configuration'
52 time = ATRADData.objects.last().datetime
53 try:
54 time = ATRADData.objects.last().datetime
55 except:
56 time = datetime.now()
57
53 58 id_stx = (int(id_tx[-1])-1)*4+1
54 mydata = ATRADData.objects.filter(datetime__gte = (time-timedelta(hours=1)),nstx = id_stx).values('datetime','temp1_1','temp2_1','temp3_1','temp4_1','temp5_1','temp6_1',
55 'temp1_2','temp2_2','temp3_2','temp4_2','temp5_2','temp6_2','temp1_3','temp2_3','temp3_3','temp4_3','temp5_3','temp6_3',
56 'temp1_4','temp2_4','temp3_4','temp4_4','temp5_4','temp6_4')
59 mydata = ATRADData.objects.filter(datetime__gte = (time-timedelta(hours=1)),nstx = id_stx).values('datetime',
60 'temp1_1','temp2_1','temp3_1','temp4_1','temp5_1','temp6_1',
61 'temp1_2','temp2_2','temp3_2','temp4_2','temp5_2','temp6_2',
62 'temp1_3','temp2_3','temp3_3','temp4_3','temp5_3','temp6_3',
63 'temp1_4','temp2_4','temp3_4','temp4_4','temp5_4','temp6_4',
64 'combiner1','combiner2','combiner3','combiner4')
57 65 kwargs['data'] = json.dumps(list(mydata),default=str)
58 66 return render(request, 'atrad_tx.html', kwargs)
59 67
60 68 def QuerytoStr(data):
61 69 time = data[0]
62 70 strdata = str(time)
63 71 return strdata
64 72
65 73 def atrad_conf_edit(request, id_conf):
66 74
67 75 conf = get_object_or_404(ATRADConfiguration, pk=id_conf)
68 76
69 77 if request.method=='GET':
70 78 form = ATRADConfigurationForm(instance=conf)
71 79
72 80 if request.method=='POST':
73 81 form = ATRADConfigurationForm(request.POST, instance=conf)
74 82
75 83 if form.is_valid():
76 84 if conf.topic == None: conf.topic = 0
77 85
78 86 conf = form.save(commit=False)
79 87
80 88 if conf.verify_frequencies():
81 89 conf.save()
82 90 return redirect('url_atrad_conf', id_conf=conf.id)
83 91
84 92 kwargs = {}
85 93 kwargs['id_dev'] = conf.id
86 94 kwargs['form'] = form
87 95 kwargs['title'] = 'Device Configuration'
88 96 kwargs['suptitle'] = 'Edit'
89 97 kwargs['button'] = 'Save'
90 98
91 99 return render(request, 'atrad_conf_edit.html', kwargs)
92 100
93 101 def publish_message(request):
94 102 rc, mid = mqtt_client.publish('test/data2',1)
95 103 return JsonResponse({'code1': 'HIKA', 'code2': 'LUCAS'})
96 104
97 105 def monitor(request):
98 106 kwargs = {'no_sidebar': True}
99 107 return render(request, 'monitor.html', kwargs)
100 108
101 109 def atrad_prueba(request):
102 110 keys = ['id','temp1','temp2','temp3','temp4','temp5','temp6']
103 111 time = ATRADData.objects.last().datetime
104 112 mydata = ATRADData.objects.filter(datetime__gte = (time-timedelta(hours=1))).values('id','temp1_1','temp2_1','temp3_1','temp4_1','temp5_1','temp6_1',
105 113 'temp1_2','temp2_2','temp3_2','temp4_2','temp5_2','temp6_2','temp1_3','temp2_3','temp3_3','temp4_3','temp5_3','temp6_3',
106 114 'temp1_4','temp2_4','temp3_4','temp4_4','temp5_4','temp6_4')
107 115 template = get_template('prueba.html')
108 116 context = {
109 117 'last' : time,
110 118 'temps': mydata,
111 119 'keys' : keys,
112 120 }
113 121 return HttpResponse(template.render(context, request))
114 122
115 123 @sio.on('connection-bind')
116 124 def atrad_connection_bind(sid, data):
117 125 print("sid:",sid,"data",data)
118 126
119 127 @sio.on('disconnect')
120 128 def atrad_disconnect(sid):
121 129 print("Disconnected")
122 130
123 131 @sio.event
124 132 def atrad_control_event(sid,message):
125 mqtt_client.publish('test/data2', json.dumps(message)) No newline at end of file
133 mqtt_client.publish(os.environ.get('MQTT_TOPIC_ATRAD_CONTROL', 'atrad/test2'), json.dumps(message)) No newline at end of file
@@ -1,409 +1,409
1 1 import json
2 2 import requests
3 3
4 4 from django.db import models
5 5 from django.core.validators import MinValueValidator, MaxValueValidator
6 6 from django.urls import reverse
7 7
8 8 from apps.main.models import Configuration
9 9 from apps.main.utils import Params
10 10 from .utils import create_jarsfiles
11 11
12 12 # Create your models here.
13 13
14 14 EXPERIMENT_TYPE = (
15 15 (0, 'RAW_DATA'),
16 16 (1, 'PDATA'),
17 17 )
18 18
19 19 DATA_TYPE = (
20 20 (0, 'SHORT'),
21 21 (1, 'FLOAT'),
22 22 )
23 23
24 24 DECODE_TYPE = (
25 25 (0, 'None'),
26 26 (1, 'TimeDomain'),
27 27 (2, 'FreqDomain'),
28 28 (3, 'InvFreqDomain'),
29 29 )
30 30
31 31 FILTER = '{"id":1, "clock": 60, "multiplier": 5, "frequency": 49.92, "f_decimal": 721554506, "fir": 2, "cic_2": 12, "cic_5": 25}'
32 32
33 33 class JARSFilter(models.Model):
34 34
35 35 JARS_NBITS = 32
36 36
37 37 name = models.CharField(verbose_name='Name', max_length=60, unique=True, default='')
38 38 clock = models.FloatField(verbose_name='Clock In (MHz)', validators=[
39 39 MinValueValidator(5), MaxValueValidator(75)], null=True, default=60)
40 40 multiplier = models.PositiveIntegerField(verbose_name='Multiplier', validators=[
41 41 MinValueValidator(1), MaxValueValidator(20)], default=5)
42 42 frequency = models.FloatField(verbose_name='Frequency (MHz)', validators=[
43 43 MaxValueValidator(150)], null=True, default=49.9200)
44 44 f_decimal = models.BigIntegerField(verbose_name='Frequency (Decimal)', validators=[
45 45 MinValueValidator(-9223372036854775808), MaxValueValidator(2**JARS_NBITS-1)], null=True, default=721554505)
46 46 cic_2 = models.PositiveIntegerField(verbose_name='CIC2', validators=[
47 47 MinValueValidator(2), MaxValueValidator(100)], default=10)
48 48 scale_cic_2 = models.PositiveIntegerField(verbose_name='Scale CIC2', validators=[
49 49 MinValueValidator(0), MaxValueValidator(6)], default=1)
50 50 cic_5 = models.PositiveIntegerField(verbose_name='CIC5', validators=[
51 51 MinValueValidator(1), MaxValueValidator(100)], default=1)
52 52 scale_cic_5 = models.PositiveIntegerField(verbose_name='Scale CIC5', validators=[
53 53 MinValueValidator(0), MaxValueValidator(20)], default=5)
54 54 fir = models.PositiveIntegerField(verbose_name='FIR', validators=[
55 55 MinValueValidator(1), MaxValueValidator(100)], default=6)
56 56 scale_fir = models.PositiveIntegerField(verbose_name='Scale FIR', validators=[
57 57 MinValueValidator(0), MaxValueValidator(7)], default=3)
58 58 number_taps = models.PositiveIntegerField(verbose_name='Number of taps', validators=[
59 59 MinValueValidator(1), MaxValueValidator(256)], default=4)
60 60 taps = models.CharField(verbose_name='Taps', max_length=1600, default='0')
61 61
62 62 class Meta:
63 63 db_table = 'jars_filters'
64 64
65 65 def __unicode__(self):
66 66 return u'%s' % (self.name)
67 67
68 68 def jsonify(self):
69 69
70 70 data = {}
71 71 ignored = ()
72 72
73 73 for field in self._meta.fields:
74 74 if field.name in ignored:
75 75 continue
76 76 data[field.name] = field.value_from_object(self)
77 77
78 78 return data
79 79
80 80 def parms_to_dict(self):
81 81
82 82 parameters = {}
83 83
84 84 parameters['name'] = self.name
85 85 parameters['clock'] = float(self.clock)
86 86 parameters['multiplier'] = int(self.multiplier)
87 87 parameters['frequency'] = float(self.frequency)
88 88 parameters['f_decimal'] = int(self.frequency)
89 89 parameters['fir'] = int(self.fir)
90 90 parameters['cic_2'] = int(self.cic_2)
91 91 parameters['cic_5'] = int(self.cic_5)
92 92
93 93 return parameters
94 94
95 95 def dict_to_parms(self, parameters):
96 96
97 97 self.name = parameters['name']
98 98 self.clock = parameters['clock']
99 99 self.multiplier = parameters['multiplier']
100 100 self.frequency = parameters['frequency']
101 101 self.f_decimal = parameters['f_decimal']
102 102 self.fir = parameters['fir']
103 103 self.cic_2 = parameters['cic_2']
104 104 self.cic_5 = parameters['cic_5']
105 105
106 106 def dict_to_parms_new(self, parameters):
107 107
108 108 self.name = parameters['name']
109 109 self.clock = parameters['clock']
110 110 self.multiplier = parameters['multiplier']
111 111 self.frequency = parameters['frequency']
112 112 self.f_decimal = parameters['f_decimal']
113 113 self.fir = parameters['fir']
114 114 self.cic_2 = parameters['cic_2']
115 115 self.cic_5 = parameters['cic_5']
116 116 self.scale_fir = parameters['scale_fir']
117 117 self.scale_cic_2 = parameters['scale_cic_2']
118 118 self.scale_cic_5 = parameters['scale_cic_5']
119 119 self.number_taps = parameters['number_taps']
120 120 self.taps = parameters['taps']
121 121
122 122 class JARSConfiguration(Configuration):
123 123
124 124 ADC_RESOLUTION = 8
125 125 PCI_DIO_BUSWIDTH = 32
126 126 HEADER_VERSION = 1103
127 127 BEGIN_ON_START = True
128 128 REFRESH_RATE = 1
129 129
130 130 exp_type = models.PositiveIntegerField(
131 131 verbose_name='Experiment Type', choices=EXPERIMENT_TYPE, default=0)
132 132 cards_number = models.PositiveIntegerField(verbose_name='Number of Cards', validators=[
133 133 MinValueValidator(1), MaxValueValidator(4)], default=1)
134 134 channels_number = models.PositiveIntegerField(verbose_name='Number of Channels', validators=[
135 135 MinValueValidator(1), MaxValueValidator(8)], default=5)
136 136 channels = models.CharField(
137 137 verbose_name='Channels', max_length=15, default='1,2,3,4,5')
138 138 data_type = models.PositiveIntegerField(
139 139 verbose_name='Data Type', choices=DATA_TYPE, default=0)
140 140 raw_data_blocks = models.PositiveIntegerField(
141 141 verbose_name='Raw Data Blocks', validators=[MaxValueValidator(5000)], default=60)
142 142 profiles_block = models.PositiveIntegerField(
143 143 verbose_name='Profiles Per Block', default=400)
144 144 acq_profiles = models.PositiveIntegerField(
145 145 verbose_name='Acquired Profiles', default=400)
146 146 ftp_interval = models.PositiveIntegerField(
147 147 verbose_name='FTP Interval', default=60)
148 148 fftpoints = models.PositiveIntegerField(
149 149 verbose_name='FFT Points', default=16)
150 150 cohe_integr_str = models.PositiveIntegerField(
151 151 verbose_name='Coh. Int. Stride', validators=[MinValueValidator(1)], default=30)
152 152 cohe_integr = models.PositiveIntegerField(
153 153 verbose_name='Coherent Integrations', validators=[MinValueValidator(1)], default=30)
154 154 incohe_integr = models.PositiveIntegerField(
155 155 verbose_name='Incoherent Integrations', validators=[MinValueValidator(1)], default=30)
156 156 decode_data = models.PositiveIntegerField(
157 157 verbose_name='Decode Data', choices=DECODE_TYPE, default=0)
158 158 post_coh_int = models.BooleanField(
159 159 verbose_name='Post Coherent Integration', default=False)
160 160 spectral_number = models.PositiveIntegerField(
161 161 verbose_name='# Spectral Combinations', validators=[MinValueValidator(1)], default=1)
162 162 spectral = models.CharField(
163 163 verbose_name='Combinations', max_length=5000, default='[0, 0],')
164 164 create_directory = models.BooleanField(
165 165 verbose_name='Create Directory Per Day', default=True)
166 166 include_expname = models.BooleanField(
167 167 verbose_name='Experiment Name in Directory', default=False)
168 168 #view_raw_data = models.BooleanField(verbose_name='View Raw Data', default=True)
169 169 save_ch_dc = models.BooleanField(
170 170 verbose_name='Save Channels DC', default=True)
171 171 save_data = models.BooleanField(verbose_name='Save Data', default=True)
172 172 filter_parms = models.CharField(
173 173 max_length=10000, default=FILTER)
174 174 filter = models.ForeignKey(
175 175 'JARSFilter', verbose_name='Filter', null=True, blank=True, on_delete=models.CASCADE)
176 176
177 177 class Meta:
178 178 db_table = 'jars_configurations'
179 179
180 180 def filter_resolution(self):
181 181 filter_parms = json.loads(self.filter_parms)
182 182 clock = float(filter_parms['clock'])
183 183 cic_2 = filter_parms['cic_2']
184 184 cic_5 = filter_parms['cic_5']
185 185 fir = filter_parms['fir']
186 186 resolution = round((clock/(cic_2*cic_5*fir)), 2)
187 187 return resolution
188 188
189 189 def dict_to_parms(self, params, id=None):
190 190
191 191 if id is not None:
192 192 data = Params(params).get_conf(id_conf=id)
193 193 else:
194 194 data = Params(params).get_conf(dtype='jars')
195 195 data['filter_parms'] = params['filter_parms']
196 196
197 197 # self.name = data['name']
198 198 self.exp_type = data['exp_type']
199 199 #----PDATA----
200 200 if self.exp_type == 1:
201 201 self.incohe_integr = data['incohe_integr']
202 202 self.spectral_number = data['spectral_number']
203 203 self.spectral = data['spectral']
204 204 self.fftpoints = data['fftpoints']
205 205 self.save_ch_dc = data['save_ch_dc']
206 206 else:
207 207 self.raw_data_blocks = data['raw_data_blocks']
208 208 #----PDATA----
209 209 self.cards_number = data['cards_number']
210 210 self.channels_number = data['channels_number']
211 211 self.channels = data['channels']
212 212 self.data_type = data['data_type']
213 213 self.profiles_block = data['profiles_block']
214 214 self.acq_profiles = data['acq_profiles']
215 215 self.ftp_interval = data['ftp_interval']
216 216 self.cohe_integr_str = data['cohe_integr_str']
217 217 self.cohe_integr = data['cohe_integr']
218 218 #----DECODE----
219 219 self.decode_data = data['decode_data']
220 220 self.post_coh_int = data['post_coh_int']
221 221 #----DECODE----
222 222 self.create_directory = data['create_directory']
223 223 self.include_expname = data['include_expname']
224 224 self.save_data = data['save_data']
225 225 self.filter_parms = json.dumps(data['filter_parms'])
226 226
227 227 self.save()
228 228
229 229 def parms_to_text(self, file_format='jars'):
230 230
231 231 data = self.experiment.parms_to_dict()
232 232
233 233 for key in data['configurations']['allIds']:
234 234 if data['configurations']['byId'][key]['device_type'] in ('dds', 'cgs'):
235 235 data['configurations']['allIds'].remove(key)
236 236 data['configurations']['byId'].pop(key)
237 237 elif data['configurations']['byId'][key]['device_type'] == 'jars':
238 238 data['configurations']['byId'][key] = self.parms_to_dict(
239 239 )['configurations']['byId'][str(self.pk)]
240 240 elif data['configurations']['byId'][key]['device_type'] == 'rc':
241 241 data['configurations']['byId'][key]['pulses'] = ''
242 242 data['configurations']['byId'][key]['delays'] = ''
243 243 rc_ids = [pk for pk in data['configurations']['allIds']
244 244 if data['configurations']['byId'][pk]['device_type'] == 'rc']
245 245 mix_ids = [pk for pk in rc_ids if data['configurations']
246 246 ['byId'][pk]['mix']]
247 247
248 248 if mix_ids:
249 249 params = data['configurations']['byId'][mix_ids[0]]['parameters']
250 250 rc = data['configurations']['byId'][params.split(
251 251 '-')[0].split('|')[0]]
252 252 rc['mix'] = True
253 253 data['configurations']['byId'][rc['id']] = rc
254 254 elif len(rc_ids) == 0:
255 255 self.message = 'File needs RC configuration'
256 256 return ''
257 257
258 258 json_data = json.dumps(data)
259 259 racp_file, filter_file = create_jarsfiles(json_data)
260 260 if file_format == 'racp':
261 261 return racp_file
262 262
263 263 return filter_file
264 264
265 265 def request(self, cmd, method='get', **kwargs):
266 266
267 267 req = getattr(requests, method)(self.device.url(cmd), **kwargs)
268 268 payload = req.json()
269 269 return payload
270 270
271 271 def status_device(self):
272 272
273 273 try:
274 274 payload = self.request('status',
275 275 params={'name': self.experiment.name})
276 276 self.device.status = payload['status']
277 277 self.device.save()
278 278 self.message = payload['message']
279 279 except Exception as e:
280 280 self.device.status = 0
281 281 self.message = str(e)
282 282 self.device.save()
283 283 return False
284 284
285 285 return True
286 286
287 287 def stop_device(self):
288 288
289 289 # Se crea el modo ocupado para una vez inicia el STOP
290 290 self.device.status = 5
291 291 self.device.save()
292 292 # Por si se demora deteniendo, que su estado sea busy
293 293
294 294 try:
295 295 payload = self.request('stop', 'post')
296 296 self.device.status = payload['status']
297 297 self.device.save()
298 298 self.message = payload['message']
299 299 except Exception as e:
300 300 self.device.status = 0
301 301 self.message = str(e)
302 302 self.device.save()
303 303 return False
304 304
305 305 return True
306 306
307 307 def read_device(self):
308 308
309 309 try:
310 310 payload = self.request(
311 311 'read', params={'name': self.experiment.name})
312 312 self.message = 'Configuration loaded'
313 313 except:
314 314 self.device.status = 0
315 315 self.device.save()
316 316 self.message = 'Could not read JARS configuration.'
317 317 return False
318 318
319 319 return payload
320 320
321 321 def write_device(self):
322 322
323 323 if self.device.status == 3:
324 324 self.message = 'Could not configure device. Software Acquisition is running'
325 325 print('Could not configure device. Software Acquisition is running')
326 326 return False
327 327
328 328 data = self.experiment.parms_to_dict()
329 329 #print(data)
330 330 for key in data['configurations']['allIds']:
331 331 if data['configurations']['byId'][key]['device_type'] in ('dds', 'cgs'):
332 332 data['configurations']['allIds'].remove(key)
333 333 data['configurations']['byId'].pop(key)
334 334 elif data['configurations']['byId'][key]['device_type'] == 'rc':
335 335 data['configurations']['byId'][key]['pulses'] = ''
336 336 data['configurations']['byId'][key]['delays'] = ''
337 337 rc_ids = [pk for pk in data['configurations']['allIds']
338 338 if data['configurations']['byId'][pk]['device_type'] == 'rc']
339 339 if len(rc_ids) == 0:
340 340 self.message = 'Missing RC configuration'
341 341 return False
342 342
343 343 json_data = json.dumps(data)
344 print("STATUS:", self.device.status,flush=True)
344 # print("STATUS:", self.device.status,flush=True)
345 345
346 346 try:
347 347 payload = self.request('write', 'post', json=json_data)
348 348 self.device.status = payload['status']
349 349 self.message = payload['message']
350 350 self.device.save()
351 351 if self.device.status == 1:
352 352 return False
353 353
354 354 except Exception as e:
355 355 self.device.status = 0
356 356 self.message = str(e)
357 357 self.device.save()
358 358 return False
359 359 return True
360 360
361 361 def start_device(self):
362 362
363 363 try:
364 364 payload = self.request('start', 'post',
365 365 json={'name': self.experiment.name})
366 366 self.device.status = payload['status']
367 367 self.message = payload['message']
368 368 self.device.save()
369 369 if self.device.status == 1:
370 370 return False
371 371
372 372 except Exception as e:
373 373 self.device.status = 0
374 374 self.message = str(e)
375 375 self.device.save()
376 376 return False
377 377 return True
378 378
379 379 def get_log(self):
380 380
381 381 payload = None
382 382
383 383 try:
384 384 payload = requests.get(self.device.url('get_log'), params={
385 385 'name': self.experiment.name})
386 386 except:
387 387 self.device.status = 0
388 388 self.device.save()
389 389 self.message = 'Jars API is not running.'
390 390 return False
391 391
392 392 self.message = 'Jars API is running'
393 393
394 394 return payload
395 395
396 396 def update_from_file(self, filename):
397 397
398 398 f = JARSFile(filename)
399 399 self.dict_to_parms(f.data)
400 400 self.save()
401 401
402 402 def get_absolute_url_import(self):
403 403 return reverse('url_import_jars_conf', args=[str(self.id)])
404 404
405 405 def get_absolute_url_read(self):
406 406 return reverse('url_read_jars_conf', args=[str(self.id)])
407 407
408 408 def get_absolute_url_log(self):
409 409 return reverse('url_get_jars_log', args=[str(self.id)])
1 NO CONTENT: file renamed from apps/main/management/commands/hello.py to apps/main/management/commands/scheduler.py
@@ -1,856 +1,853
1 1
2 2 import os
3 3 import json
4 4 import requests
5 5 import time
6 6 from datetime import datetime
7 7
8 8 try:
9 9 from polymorphic.models import PolymorphicModel
10 10 except:
11 11 from polymorphic import PolymorphicModel
12 12
13 13 from django.template.base import kwarg_re
14 14 from django.db import models
15 15 from django.urls import reverse
16 16 from django.core.validators import MinValueValidator, MaxValueValidator
17 17 from django.shortcuts import get_object_or_404
18 18 from django.contrib.auth.models import User
19 19 from django.db.models.signals import post_save
20 20 from django.dispatch import receiver
21 21
22 22 from apps.main.utils import Params
23 23 from apps.rc.utils import RCFile
24 24 from apps.jars.utils import RacpFile
25 25 from devices.dds import api as dds_api
26 26 from devices.dds import data as dds_data
27 27
28 28
29 29 DEV_PORTS = {
30 30 'rc' : 2000,
31 31 'dds' : 2000,
32 32 'jars' : 2000,
33 33 'usrp' : 2000,
34 34 'cgs' : 8080,
35 35 'abs' : 8080,
36 36 'dds_rest': 80
37 37 }
38 38
39 39 RADAR_STATES = (
40 40 (0, 'No connected'),
41 41 (1, 'Connected'),
42 42 (2, 'Configured'),
43 43 (3, 'Running'),
44 44 (4, 'Scheduled'),
45 45 )
46 46
47 47 EXPERIMENT_TYPE = (
48 48 (0, 'RAW_DATA'),
49 49 (1, 'PDATA'),
50 50 )
51 51
52 52 DECODE_TYPE = (
53 53 (0, 'None'),
54 54 (1, 'TimeDomain'),
55 55 (2, 'FreqDomain'),
56 56 (3, 'InvFreqDomain'),
57 57 )
58 58
59 59 DEV_STATES = (
60 60 (0, 'No connected'),
61 61 (1, 'Connected'),
62 62 (2, 'Configured'),
63 63 (3, 'Running'),
64 64 (4, 'Unknown'),
65 65 (5, 'Busy')
66 66 )
67 67
68 68 DEV_TYPES = (
69 69 ('', 'Select a device type'),
70 70 ('rc', 'Radar Controller'),
71 71 ('dds', 'Direct Digital Synthesizer'),
72 72 ('jars', 'Jicamarca Radar Acquisition System'),
73 73 ('usrp', 'Universal Software Radio Peripheral'),
74 74 ('cgs', 'Clock Generator System'),
75 75 ('abs', 'Automatic Beam Switching'),
76 76 ('dds_rest', 'Direct Digital Synthesizer_REST'),
77 77 ('atrad', 'Transmitter ATRAD'),
78 78 )
79 79
80 80 EXP_STATES = (
81 81 (0,'Error'), #RED
82 82 (1,'Cancelled'), #YELLOW
83 83 (2,'Running'), #GREEN
84 84 (3,'Scheduled'), #BLUE
85 85 (4,'Unknown'), #WHITE
86 86 (5,'Busy'),
87 87 )
88 88
89 89 CONF_TYPES = (
90 90 (0, 'Active'),
91 91 (1, 'Historical'),
92 92 )
93 93
94 94 class Profile(models.Model):
95 95 user = models.OneToOneField(User, on_delete=models.CASCADE)
96 96 theme = models.CharField(max_length=30, default='spacelab')
97 97
98 98
99 99 @receiver(post_save, sender=User)
100 100 def create_user_profile(sender, instance, created, **kwargs):
101 101 if created:
102 102 Profile.objects.create(user=instance)
103 103
104 104 @receiver(post_save, sender=User)
105 105 def save_user_profile(sender, instance, **kwargs):
106 106 instance.profile.save()
107 107
108 108
109 109 class Location(models.Model):
110 110
111 111 name = models.CharField(max_length = 30)
112 112 description = models.TextField(blank=True, null=True)
113 113
114 114 class Meta:
115 115 db_table = 'db_location'
116 116
117 117 def __str__(self):
118 118 return u'%s' % self.name
119 119
120 120 def get_absolute_url(self):
121 121 return reverse('url_location', args=[str(self.id)])
122 122
123 123
124 124 class DeviceType(models.Model):
125 125
126 126 name = models.CharField(max_length = 10, choices = DEV_TYPES, default = 'dds_rest')
127 127 sequence = models.PositiveSmallIntegerField(default=55)
128 128 description = models.TextField(blank=True, null=True)
129 129
130 130 class Meta:
131 131 db_table = 'db_device_types'
132 132
133 133 def __str__(self):
134 134 return u'%s' % self.get_name_display()
135 135
136 136 class Device(models.Model):
137 137
138 138 device_type = models.ForeignKey('DeviceType', on_delete=models.CASCADE)
139 139 location = models.ForeignKey('Location', on_delete=models.CASCADE)
140 140 ip_address = models.GenericIPAddressField(protocol='IPv4', default='0.0.0.0')
141 141 port_address = models.PositiveSmallIntegerField(default=2000)
142 142 description = models.TextField(blank=True, null=True)
143 143 status = models.PositiveSmallIntegerField(default=4, choices=DEV_STATES)
144 144 conf_active = models.PositiveIntegerField(default=0, verbose_name='Current configuration')
145 145
146 146 class Meta:
147 147 db_table = 'db_devices'
148 148
149 149 def __str__(self):
150 150 ret = u'{} [{}]'.format(self.device_type.name.upper(), self.location.name)
151 151
152 152 return ret
153 153
154 154 @property
155 155 def name(self):
156 156 return str(self)
157 157
158 158 def get_status(self):
159 159 return self.status
160 160
161 161 @property
162 162 def status_color(self):
163 163 color = 'muted'
164 164 if self.status == 0:
165 165 color = "danger"
166 166 elif self.status == 1:
167 167 color = "warning"
168 168 elif self.status == 2:
169 169 color = "info"
170 170 elif self.status == 3:
171 171 color = "success"
172 172
173 173 return color
174 174
175 175 def url(self, path=None):
176 176
177 177 if path:
178 178 return 'http://{}:{}/{}/'.format(self.ip_address, self.port_address, path)
179 179 else:
180 180 return 'http://{}:{}/'.format(self.ip_address, self.port_address)
181 181
182 182 def get_absolute_url(self):
183 183 return reverse('url_device', args=[str(self.id)])
184 184
185 185 def get_absolute_url_edit(self):
186 186 return reverse('url_edit_device', args=[str(self.id)])
187 187
188 188 def get_absolute_url_delete(self):
189 189 return reverse('url_delete_device', args=[str(self.id)])
190 190
191 191 def change_ip(self, ip_address, mask, gateway, dns, **kwargs):
192 192
193 193 if self.device_type.name=='dds':
194 194 try:
195 195 answer = dds_api.change_ip(ip = self.ip_address,
196 196 port = self.port_address,
197 197 new_ip = ip_address,
198 198 mask = mask,
199 199 gateway = gateway)
200 200 if answer[0]=='1':
201 201 self.message = '25|DDS - {}'.format(answer)
202 202 self.ip_address = ip_address
203 203 self.save()
204 204 else:
205 205 self.message = '30|DDS - {}'.format(answer)
206 206 return False
207 207 except Exception as e:
208 208 self.message = '40|{}'.format(str(e))
209 209 return False
210 210
211 211 elif self.device_type.name=='rc':
212 212 headers = {'content-type': "application/json",
213 213 'cache-control': "no-cache"}
214 214
215 215 ip = [int(x) for x in ip_address.split('.')]
216 216 dns = [int(x) for x in dns.split('.')]
217 217 gateway = [int(x) for x in gateway.split('.')]
218 218 subnet = [int(x) for x in mask.split('.')]
219 219
220 220 payload = {
221 221 "ip": ip,
222 222 "dns": dns,
223 223 "gateway": gateway,
224 224 "subnet": subnet
225 225 }
226 226
227 227 req = requests.post(self.url('changeip'), data=json.dumps(payload), headers=headers)
228 228 try:
229 229 answer = req.json()
230 230 if answer['changeip']=='ok':
231 231 self.message = '25|IP succesfully changed'
232 232 self.ip_address = ip_address
233 233 self.save()
234 234 else:
235 235 self.message = '30|An error ocuur when changing IP'
236 236 except Exception as e:
237 237 self.message = '40|{}'.format(str(e))
238 238 else:
239 239 self.message = 'Not implemented'
240 240 return False
241 241
242 242 return True
243 243
244 244
245 245 class Campaign(models.Model):
246 246
247 247 template = models.BooleanField(default=False)
248 248 name = models.CharField(max_length=60, unique=True)
249 249 start_date = models.DateTimeField(blank=True, null=True)
250 250 end_date = models.DateTimeField(blank=True, null=True)
251 251 tags = models.CharField(max_length=40, blank=True, null=True)
252 252 description = models.TextField(blank=True, null=True)
253 253 experiments = models.ManyToManyField('Experiment', blank=True)
254 254 author = models.ForeignKey(User, null=True, blank=True,on_delete=models.CASCADE)
255 255
256 256 class Meta:
257 257 db_table = 'db_campaigns'
258 258 ordering = ('name',)
259 259
260 260 def __str__(self):
261 261 if self.template:
262 262 return u'{} (template)'.format(self.name)
263 263 else:
264 264 return u'{}'.format(self.name)
265 265
266 266 def jsonify(self):
267 267
268 268 data = {}
269 269
270 270 ignored = ('template')
271 271
272 272 for field in self._meta.fields:
273 273 if field.name in ignored:
274 274 continue
275 275 data[field.name] = field.value_from_object(self)
276 276
277 277 data['start_date'] = data['start_date'].strftime('%Y-%m-%d')
278 278 data['end_date'] = data['end_date'].strftime('%Y-%m-%d')
279 279
280 280 return data
281 281
282 282 def parms_to_dict(self):
283 283
284 284 params = Params({})
285 285 params.add(self.jsonify(), 'campaigns')
286 286
287 287 for exp in Experiment.objects.filter(campaign = self):
288 288 params.add(exp.jsonify(), 'experiments')
289 289 configurations = Configuration.objects.filter(experiment=exp, type=0)
290 290
291 291 for conf in configurations:
292 292 params.add(conf.jsonify(), 'configurations')
293 293 if conf.device.device_type.name=='rc':
294 294 for line in conf.get_lines():
295 295 params.add(line.jsonify(), 'lines')
296 296
297 297 return params.data
298 298
299 299 def dict_to_parms(self, parms, CONF_MODELS):
300 300
301 301 experiments = Experiment.objects.filter(campaign = self)
302 302
303 303 if experiments:
304 304 for experiment in experiments:
305 305 experiment.delete()
306 306
307 307 for id_exp in parms['experiments']['allIds']:
308 308 exp_parms = parms['experiments']['byId'][id_exp]
309 309 dum = (datetime.now() - datetime(1970, 1, 1)).total_seconds()
310 310 exp = Experiment(name='{}'.format(dum))
311 311 exp.save()
312 312 exp.dict_to_parms(parms, CONF_MODELS, id_exp=id_exp)
313 313 self.experiments.add(exp)
314 314
315 315 camp_parms = parms['campaigns']['byId'][parms['campaigns']['allIds'][0]]
316 316
317 317 self.name = '{}-{}'.format(camp_parms['name'], datetime.now().strftime('%y%m%d'))
318 318 self.start_date = camp_parms['start_date']
319 319 self.end_date = camp_parms['end_date']
320 320 self.tags = camp_parms['tags']
321 321 self.save()
322 322
323 323 return self
324 324
325 325 def get_experiments_by_radar(self, radar=None):
326 326
327 327 ret = []
328 328 if radar:
329 329 locations = Location.objects.filter(pk=radar)
330 330 else:
331 331 locations = set([e.location for e in self.experiments.all()])
332 332
333 333 for loc in locations:
334 334 dum = {}
335 335 dum['name'] = loc.name
336 336 dum['id'] = loc.pk
337 337 dum['experiments'] = [e for e in self.experiments.all() if e.location==loc]
338 338 ret.append(dum)
339 339 return ret
340 340
341 341 def get_absolute_url(self):
342 342 return reverse('url_campaign', args=[str(self.id)])
343 343
344 344 def get_absolute_url_edit(self):
345 345 return reverse('url_edit_campaign', args=[str(self.id)])
346 346
347 347 def get_absolute_url_delete(self):
348 348 return reverse('url_delete_campaign', args=[str(self.id)])
349 349
350 350 def get_absolute_url_export(self):
351 351 return reverse('url_export_campaign', args=[str(self.id)])
352 352
353 353 def get_absolute_url_import(self):
354 354 return reverse('url_import_campaign', args=[str(self.id)])
355 355
356 356
357 357 class RunningExperiment(models.Model):
358 358 radar = models.OneToOneField('Location', on_delete=models.CASCADE)
359 359 running_experiment = models.ManyToManyField('Experiment', blank = True)
360 360 status = models.PositiveSmallIntegerField(default=0, choices=RADAR_STATES)
361 361
362 362
363 363 class Experiment(models.Model):
364 364
365 365 template = models.BooleanField(default=False)
366 366 name = models.CharField(max_length=40, default='', unique=True)
367 367 location = models.ForeignKey('Location', null=True, blank=True, on_delete=models.CASCADE)
368 368 freq = models.FloatField(verbose_name='Operating Freq. (MHz)', validators=[MinValueValidator(1), MaxValueValidator(10000)], default=49.9200)
369 369 start_time = models.TimeField(default='00:00:00')
370 370 end_time = models.TimeField(default='23:59:59')
371 371 task = models.CharField(max_length=36, default='', blank=True, null=True)
372 372 status = models.PositiveSmallIntegerField(default=4, choices=EXP_STATES)
373 373 author = models.ForeignKey(User, null=True, blank=True,on_delete=models.CASCADE)
374 374 hash = models.CharField(default='', max_length=64, null=True, blank=True)
375 375
376 376 class Meta:
377 377 db_table = 'db_experiments'
378 378 ordering = ('template', 'name')
379 379
380 380 def __str__(self):
381 381 if self.template:
382 382 return u'%s (template)' % (self.name)
383 383 else:
384 384 return u'%s' % (self.name)
385 385
386 386 def jsonify(self):
387 387
388 388 data = {}
389 389
390 390 ignored = ('template')
391 391
392 392 for field in self._meta.fields:
393 393 if field.name in ignored:
394 394 continue
395 395 data[field.name] = field.value_from_object(self)
396 396
397 397 data['start_time'] = data['start_time'].strftime('%H:%M:%S')
398 398 data['end_time'] = data['end_time'].strftime('%H:%M:%S')
399 399 data['location'] = self.location.name
400 400 data['configurations'] = ['{}'.format(conf.pk) for
401 401 conf in Configuration.objects.filter(experiment=self, type=0)]
402 402
403 403 return data
404 404
405 405 @property
406 406 def radar_system(self):
407 407 return self.location
408 408
409 409 def clone(self, **kwargs):
410 410
411 411 confs = Configuration.objects.filter(experiment=self, type=0)
412 412 self.pk = None
413 413 self.name = '{}_{:%y%m%d%H%M%S}'.format(self.name, datetime.now())
414 414 for attr, value in kwargs.items():
415 415 setattr(self, attr, value)
416 416
417 417 self.save()
418 418
419 419 for conf in confs:
420 420 conf.clone(experiment=self, template=False)
421 421
422 422 return self
423 423
424 424 def start(self):
425 425 '''
426 426 Configure and start experiments's devices
427 427 ABS-CGS-DDS-RC-JARS
428 428 '''
429 429 self.status=5 #Busy
430 430 self.save()
431 431 print("Realizando operación. \nEXPERIMENT STATUS : {}".format(self.status))
432 432
433 433 confs = []
434 434 allconfs = Configuration.objects.filter(experiment=self, type = 0).order_by('-device__device_type__sequence')
435 435 rc_mix = [conf for conf in allconfs if conf.device.device_type.name=='rc' and conf.mix]
436 436 if rc_mix:
437 437 for conf in allconfs:
438 438 if conf.device.device_type.name == 'rc' and not conf.mix:
439 439 continue
440 440 confs.append(conf)
441 441 else:
442 442 confs = allconfs
443 443
444 444
445 445 for conf in confs:
446 446 print("--------------",flush=True)
447 447 print("STATUS: {}".format(conf.device.status))
448 448 print("Stop ",conf.name,flush=True)
449 449 if conf.stop_device() ==False:
450 450 print("Falló Stop ",conf.name)
451 451 print("Cancelando Campaña...",flush=True)
452 452 return 0
453 453 print("Write ",conf.name,flush=True)
454 454 if conf.write_device() ==False:
455 455 print("Falló Write ",conf.name)
456 456 print("Cancelando Campaña...",flush=True)
457 457 return 0
458 458 print("Save",conf.name,flush=True)
459 459 conf.device.conf_active = conf.pk
460 460 conf.device.save()
461 461 print("Start",conf.name,flush=True)
462 462 if conf.start_device()==False:
463 463 print("Falló Start ",conf.name)
464 464 print("Cancelando Campaña...",flush=True)
465 465 return 0
466 466 print("--- CONFIGURACIÓN EXITOSA ---",flush=True)
467 467 time.sleep(1)
468 468
469 469 return 2
470 470
471 471
472 472 def stop(self):
473 473 '''
474 474 Stop experiments's devices
475 475 DDS-JARS-RC-CGS-ABS
476 476 '''
477 477
478 478 confs = Configuration.objects.filter(experiment=self, type = 0).order_by('device__device_type__sequence')
479 479 confs = confs.exclude(device__device_type__name='cgs')
480 480 try:
481 481 for conf in confs:
482 482 conf.stop_device()
483 483 except:
484 484 return 0
485 485 return 1
486 486
487 487 def get_status(self):
488 488
489 489 if self.status == 3:
490 490 return
491 491
492 492 confs = Configuration.objects.filter(experiment=self, type=0)
493 493
494 494 for conf in confs:
495 495 conf.status_device()
496 496
497 497 total = confs.aggregate(models.Sum('device__status'))['device__status__sum']
498 498
499 499 if total==2*confs.count():
500 500 status = 1
501 501 elif total == 3*confs.count():
502 502 status = 2
503 503 else:
504 504 status = 0
505 505
506 506 self.status = status
507 507 self.save()
508 508
509 509 def status_color(self):
510 510 color = 'muted'
511 511 if self.status == 0:
512 512 color = "danger"
513 513 elif self.status == 1:
514 514 color = "warning"
515 515 elif self.status == 2:
516 516 color = "success"
517 517 elif self.status == 3:
518 518 color = "info"
519 519
520 520 return color
521 521
522 522 def parms_to_dict(self):
523 523
524 524 params = Params({})
525 525 params.add(self.jsonify(), 'experiments')
526 526
527 527 configurations = Configuration.objects.filter(experiment=self, type=0)
528 528
529 529 for conf in configurations:
530 530 params.add(conf.jsonify(), 'configurations')
531 531 if conf.device.device_type.name=='rc':
532 532 for line in conf.get_lines():
533 533 params.add(line.jsonify(), 'lines')
534 534
535 535 return params.data
536 536
537 537 def dict_to_parms(self, parms, CONF_MODELS, id_exp=None):
538 538
539 539 configurations = Configuration.objects.filter(experiment=self)
540 540
541 541 if id_exp is not None:
542 542 exp_parms = parms['experiments']['byId'][id_exp]
543 543 else:
544 544 exp_parms = parms['experiments']['byId'][parms['experiments']['allIds'][0]]
545 545
546 546 if configurations:
547 547 for configuration in configurations:
548 548 configuration.delete()
549 549
550 550 for id_conf in exp_parms['configurations']:
551 551 conf_parms = parms['configurations']['byId'][id_conf]
552 552 device = Device.objects.filter(device_type__name=conf_parms['device_type'])[0]
553 553 model = CONF_MODELS[conf_parms['device_type']]
554 554 conf = model(
555 555 experiment = self,
556 556 device = device,
557 557 )
558 558 conf.dict_to_parms(parms, id=id_conf)
559 559
560 560
561 561 location, created = Location.objects.get_or_create(name=exp_parms['location'])
562 562 self.name = '{}-{}'.format(exp_parms['name'], datetime.now().strftime('%y%m%d'))
563 563 self.location = location
564 564 self.start_time = exp_parms['start_time']
565 565 self.end_time = exp_parms['end_time']
566 566 self.save()
567 567
568 568 return self
569 569
570 570 def get_absolute_url(self):
571 571 return reverse('url_experiment', args=[str(self.id)])
572 572
573 573 def get_absolute_url_edit(self):
574 574 return reverse('url_edit_experiment', args=[str(self.id)])
575 575
576 576 def get_absolute_url_delete(self):
577 577 return reverse('url_delete_experiment', args=[str(self.id)])
578 578
579 579 def get_absolute_url_import(self):
580 580 return reverse('url_import_experiment', args=[str(self.id)])
581 581
582 582 def get_absolute_url_export(self):
583 583 return reverse('url_export_experiment', args=[str(self.id)])
584 584
585 585 def get_absolute_url_start(self):
586 586 return reverse('url_start_experiment', args=[str(self.id)])
587 587
588 588 def get_absolute_url_stop(self):
589 589 return reverse('url_stop_experiment', args=[str(self.id)])
590 590
591 591
592 592 class Configuration(PolymorphicModel):
593 593
594 594 template = models.BooleanField(default=False)
595 595 # name = models.CharField(verbose_name="Configuration Name", max_length=40, default='')
596 596 device = models.ForeignKey('Device', verbose_name='Device', null=True, on_delete=models.CASCADE)
597 597 label = models.CharField(verbose_name="Label", max_length=40, default='', blank=True, null=True)
598 598 experiment = models.ForeignKey('Experiment', verbose_name='Experiment', null=True, blank=True, on_delete=models.CASCADE)
599 599 type = models.PositiveSmallIntegerField(default=0, choices=CONF_TYPES)
600 600 created_date = models.DateTimeField(auto_now_add=True)
601 601 programmed_date = models.DateTimeField(auto_now=True)
602 602 parameters = models.TextField(default='{}')
603 603 author = models.ForeignKey(User, null=True, blank=True,on_delete=models.CASCADE)
604 604 hash = models.CharField(default='', max_length=64, null=True, blank=True)
605 605 message = ""
606 606
607 607 class Meta:
608 608 db_table = 'db_configurations'
609 609 ordering = ('device__device_type__name',)
610 610
611 611 def __str__(self):
612 612
613 613 ret = u'{} '.format(self.device.device_type.name.upper())
614 614
615 615 if 'mix' in [f.name for f in self._meta.get_fields()]:
616 616 if self.mix:
617 617 ret = '{} MIX '.format(self.device.device_type.name.upper())
618 618
619 619 if 'label' in [f.name for f in self._meta.get_fields()]:
620 620 ret += '{}'.format(self.label)
621 621
622 622 if self.template:
623 623 ret += ' (template)'
624 624
625 625 return ret
626 626
627 627 @property
628 628 def name(self):
629 629
630 630 return str(self)
631 631
632 632 def jsonify(self):
633 633
634 634 data = {}
635 635
636 636 ignored = ('type', 'polymorphic_ctype', 'configuration_ptr',
637 637 'created_date', 'programmed_date', 'template', 'device',
638 638 'experiment')
639 639
640 640 for field in self._meta.fields:
641 641 if field.name in ignored:
642 642 continue
643 643 data[field.name] = field.value_from_object(self)
644 644
645 645 data['device_type'] = self.device.device_type.name
646 646
647 647 if self.device.device_type.name == 'rc':
648 648 data['lines'] = ['{}'.format(line.pk) for line in self.get_lines()]
649 649 data['delays'] = self.get_delays()
650 650 data['pulses'] = self.get_pulses()
651 651
652 652 elif self.device.device_type.name == 'jars':
653 653 data['decode_type'] = DECODE_TYPE[self.decode_data][1]
654 654
655 655 elif self.device.device_type.name == 'dds':
656 656 data['frequencyA_Mhz'] = float(data['frequencyA_Mhz'])
657 657 data['frequencyB_Mhz'] = float(data['frequencyB_Mhz'])
658 658 data['phaseA'] = dds_data.phase_to_binary(data['phaseA_degrees'])
659 659 data['phaseB'] = dds_data.phase_to_binary(data['phaseB_degrees'])
660 660
661 661 elif self.device.device_type.name == 'dds_rest':
662 662 data['frequencyA_Mhz'] = float(data['frequencyA_Mhz'])
663 663 data['frequencyB_Mhz'] = float(data['frequencyB_Mhz'])
664 664 data['phaseA'] = dds_data.phase_to_binary(data['phaseA_degrees'])
665 665 data['phaseB'] = dds_data.phase_to_binary(data['phaseB_degrees'])
666 666 data['delta_frequency_Mhz'] = float(data['delta_frequency_Mhz'] or 0.00)
667 667 data['update_clock_Mhz'] = float(data['update_clock_Mhz'] or 0.00)
668 668 data['ramp_rate_clock_Mhz'] = float(data['ramp_rate_clock_Mhz'] or 0.0)
669 669 return data
670 670
671 671 def clone(self, **kwargs):
672 672
673 673 self.pk = None
674 674 self.id = None
675 675 for attr, value in kwargs.items():
676 676 setattr(self, attr, value)
677 677
678 678 self.save()
679 679
680 680 return self
681 681
682 682 def parms_to_dict(self):
683 683
684 684 params = Params({})
685 685 params.add(self.jsonify(), 'configurations')
686 686
687 687 if self.device.device_type.name=='rc':
688 688 for line in self.get_lines():
689 689 params.add(line.jsonify(), 'lines')
690 690
691 691 return params.data
692 692
693 693 def parms_to_text(self):
694 694
695 695 raise NotImplementedError("This method should be implemented in %s Configuration model" %str(self.device.device_type.name).upper())
696 696
697 697
698 698 def parms_to_binary(self):
699 699
700 700 raise NotImplementedError("This method should be implemented in %s Configuration model" %str(self.device.device_type.name).upper())
701 701
702 702
703 703 def dict_to_parms(self, parameters, id=None):
704 704
705 705 params = Params(parameters)
706 706
707 707 if id:
708 708 data = params.get_conf(id_conf=id)
709 709 else:
710 710 data = params.get_conf(dtype=self.device.device_type.name)
711 711
712 712 if data['device_type']=='rc':
713 713 self.clean_lines()
714 714 lines = data.pop('lines', None)
715 715 for line_id in lines:
716 716 pass
717 717
718 718 for key, value in data.items():
719 719 if key not in ('id', 'device_type'):
720 720 setattr(self, key, value)
721 721
722 722 self.save()
723 723
724 724
725 725 def export_to_file(self, format="json"):
726 726
727 727 content_type = ''
728 728
729 729 if format == 'racp':
730 730 content_type = 'text/plain'
731 731 filename = '%s_%s.%s' %(self.device.device_type.name, self.name, 'racp')
732 732 content = self.parms_to_text(file_format = 'racp')
733 733
734 734 if format == 'text':
735 735 content_type = 'text/plain'
736 736 filename = '%s_%s.%s' %(self.device.device_type.name, self.name, self.device.device_type.name)
737 737 content = self.parms_to_text()
738 738
739 739 if format == 'binary':
740 740 content_type = 'application/octet-stream'
741 741 filename = '%s_%s.bin' %(self.device.device_type.name, self.name)
742 742 content = self.parms_to_binary()
743 743
744 744 if not content_type:
745 745 content_type = 'application/json'
746 746 filename = '%s_%s.json' %(self.device.device_type.name, self.name)
747 747 content = json.dumps(self.parms_to_dict(), indent=2)
748 748
749 749 fields = {'content_type':content_type,
750 750 'filename':filename,
751 751 'content':content
752 752 }
753 753
754 754 return fields
755 755
756 756 def import_from_file(self, fp):
757 757
758 758 parms = {}
759 759
760 760 path, ext = os.path.splitext(fp.name)
761 761
762 762 if ext == '.json':
763 763 parms = json.load(fp)
764 764
765 765 if ext == '.dds':
766 766 lines = fp.readlines()
767 767 parms = dds_data.text_to_dict(lines)
768 768
769 769 if ext == '.racp':
770 770 if self.device.device_type.name == 'jars':
771 771 parms = RacpFile(fp).to_dict()
772 772 parms['filter_parms'] = json.loads(self.filter_parms)
773 773 return parms
774 774 parms = RCFile(fp).to_dict()
775 775
776 776 return parms
777 777
778 778 def status_device(self):
779 779
780 780 self.message = 'Function not implemented'
781 781 return False
782 782
783 783
784 784 def stop_device(self):
785 785
786 786 self.message = 'Function not implemented'
787 print("BUENAS SEÑALES??? NO LO CREO2",flush=True)
788 787 return False
789 788
790 789
791 790 def start_device(self):
792 791
793 792 self.message = 'Function not implemented'
794 print("BUENAS SEÑALES??? NO LO CREO",flush=True)
795 793 return False
796 794
797 795
798 796 def write_device(self, parms):
799 797
800 798 self.message = 'Function not implemented'
801 print("BUENAS SEÑALES??? NO LO CREO3",flush=True)
802 799 return False
803 800
804 801 def write_device_mqtt(self, parms):
805 802
806 803 self.message = 'Function not implemented'
807 804 return False
808 805
809 806 def read_device(self):
810 807
811 808 self.message = 'Function not implemented'
812 809 return False
813 810
814 811
815 812 def get_absolute_url(self):
816 813 return reverse('url_%s_conf' % self.device.device_type.name, args=[str(self.id)])
817 814
818 815 def get_absolute_mqtt_url(self):
819 816 print("----------------- {} ----------------------".format(self.device.device_type.name),flush=True)
820 817 if self.device.device_type.name=='abs':
821 818 return reverse('url_%s_conf_mqtt' % self.device.device_type.name, args=[str(self.id)])
822 819 else:
823 820 return reverse('url_%s_conf' % self.device.device_type.name, args=[str(self.id)])
824 821
825 822 def get_absolute_url_edit(self):
826 823 return reverse('url_edit_%s_conf' % self.device.device_type.name, args=[str(self.id)])
827 824
828 825 def get_absolute_url_delete(self):
829 826 return reverse('url_delete_dev_conf', args=[str(self.id)])
830 827
831 828 def get_absolute_url_import(self):
832 829 return reverse('url_import_dev_conf', args=[str(self.id)])
833 830
834 831 def get_absolute_url_export(self):
835 832 return reverse('url_export_dev_conf', args=[str(self.id)])
836 833
837 834 def get_absolute_url_write(self):
838 835 return reverse('url_write_dev_conf', args=[str(self.id)])
839 836
840 837 def get_absolute_url_write_mqtt(self):
841 838 return reverse('url_write_mqtt_dev_conf', args=[str(self.id)])
842 839
843 840 def get_absolute_url_read(self):
844 841 return reverse('url_read_dev_conf', args=[str(self.id)])
845 842
846 843 def get_absolute_url_start(self):
847 844 return reverse('url_start_dev_conf', args=[str(self.id)])
848 845
849 846 def get_absolute_url_stop(self):
850 847 return reverse('url_stop_dev_conf', args=[str(self.id)])
851 848
852 849 def get_absolute_url_stop_mqtt(self):
853 850 return reverse('url_stop_mqtt_dev_conf', args=[str(self.id)])
854 851
855 852 def get_absolute_url_status(self):
856 853 return reverse('url_status_dev_conf', args=[str(self.id)])
@@ -1,444 +1,436
1 1
2 2 import json
3 3
4 4 from django.contrib import messages
5 5 from django.utils.safestring import mark_safe
6 6 from django.shortcuts import render, redirect, get_object_or_404, HttpResponse
7 7 from django.contrib.auth.decorators import login_required
8 8
9 9 from apps.main.models import Experiment, Device
10 10 from apps.main.views import sidebar
11 11
12 12 from .models import RCConfiguration, RCLine, RCLineType, RCLineCode, RCClock
13 13 from .forms import RCConfigurationForm, RCLineForm, RCLineViewForm, RCLineEditForm, RCImportForm, RCLineCodesForm, RCClockForm
14 14
15 15
16 16 def conf(request, conf_id):
17 17
18 18 conf = get_object_or_404(RCConfiguration, pk=conf_id)
19 19
20 20 lines = RCLine.objects.filter(rc_configuration=conf).order_by('channel')
21 21 clk = RCClock.objects.filter(rc_configuration=conf).first()
22 22 if clk is None:
23 23 clk = RCClock(rc_configuration=conf)
24 24 clk.save()
25 25
26 26 for line in lines:
27 27 params = json.loads(line.params)
28 28 line.form = RCLineViewForm(extra_fields=params, line=line)
29 29 if 'params' in params:
30 30 line.subforms = [RCLineViewForm(extra_fields=fields, line=line, subform=True) for fields in params['params']]
31 31
32 32 kwargs = {}
33 33 kwargs['clock'] = clk
34 34 kwargs['dev_conf'] = conf
35 35 kwargs['rc_lines'] = lines
36 36 kwargs['dev_conf_keys'] = ['ipp_unit', 'ntx', 'clock_divider', 'clock',
37 37 'time_before', 'time_after', 'sync', 'sampling_reference',
38 38 'control_tx', 'control_sw']
39 39
40 40 kwargs['title'] = 'Configuration'
41 41 kwargs['suptitle'] = 'Detail'
42 42
43 43 kwargs['button'] = 'Edit Configuration'
44 44 ###### SIDEBAR ######
45 45 kwargs.update(sidebar(conf=conf))
46 46
47 47 return render(request, 'rc_conf.html', kwargs)
48 48
49 49 @login_required
50 50 def conf_edit(request, conf_id):
51 51
52 52 conf = get_object_or_404(RCConfiguration, pk=conf_id)
53 53 clock = RCClock.objects.get(rc_configuration=conf)
54 54 lines = RCLine.objects.filter(rc_configuration=conf).order_by('channel')
55 55
56 56 for line in lines:
57 57 params = json.loads(line.params)
58 58 #print(params)
59 59 line.form = RCLineEditForm(conf=conf, line=line, extra_fields=params)
60 60 line.subform = False
61 61
62 62 if 'params' in params:
63 63 line.subforms = [RCLineEditForm(extra_fields=fields, line=line, subform=i) for i, fields in enumerate(params['params'])]
64 64 line.subform = True
65 65 print(params)
66 66 print("fin de sub carga de params")
67 67 #print("fin de carga de params")
68 68 if request.method=='GET':
69 69 print("GET case")
70 70 form = RCConfigurationForm(instance=conf)
71 71 form_clock = RCClockForm(instance=clock)
72 72
73 73 elif request.method=='POST':
74 74 #print("ingreso a post conf edit")
75 75 line_data = {}
76 76 conf_data = {}
77 77 clock_data = {}
78 78 extras = []
79 79 print("Inicio impresion POST#####")
80 80 print(request.POST.items)
81 81 print("Fin impresion de POST items#####")
82 82 #classified post fields
83 83 for label,value in request.POST.items():
84 84 if label=='csrfmiddlewaretoken':
85 85 continue
86 86
87 87 if label.count('|')==0:
88 88 if label in ('mode', 'multiplier', 'divisor', 'reference', 'frequency'):
89 89 clock_data[label] = value
90 90 else:
91 91 conf_data[label] = value
92 92 continue
93 93
94 94 elif label.split('|')[0]!='-1':
95 95 extras.append(label)
96 96 continue
97 97
98 98 #print(label)
99 99 x, pk, name = label.split('|')
100 100
101 101 if name=='codes':
102 102 value = [s for s in value.split('\r\n') if s]
103 103
104 104 if pk in line_data:
105 105 line_data[pk][name] = value
106 106 else:
107 107 line_data[pk] = {name:value}
108 108 #print(line_data[pk])
109 109 #update conf
110 110
111 111 form_clock = RCClockForm(clock_data, instance=clock)
112 112 form = RCConfigurationForm(conf_data, instance=conf)
113 113
114 114 #print(request.POST.items())
115 115
116 116 if form_clock.is_valid() and form.is_valid():
117 117 form_clock.save()
118 118 form.save()
119 119
120 120 #update lines fields
121 121 extras.sort()
122 122 #print("Inicio extras")
123 123 #print(extras)
124 124 #print("Fin extras")
125 125 for label in extras:
126 126 x, pk, name = label.split('|')
127 127 if pk not in line_data:
128 128 line_data[pk] = {}
129 129 if 'params' not in line_data[pk]:
130 130 line_data[pk]['params'] = []
131 131 if len(line_data[pk]['params'])<int(x)+1:
132 132 line_data[pk]['params'].append({})
133 133 line_data[pk]['params'][int(x)][name] = float(request.POST[label])
134 134
135 135 for pk, params in line_data.items():
136 136 line = RCLine.objects.get(pk=pk)
137 137 if line.line_type.name in ('windows', 'prog_pulses'):
138 138 if 'params' not in params:
139 139 params['params'] = []
140 140 line.params = json.dumps(params)
141 141 #print(line.params)
142 142 line.save()
143 143
144 144
145 145 #update pulses field
146 146 conf.update_pulses()
147 147
148 148 messages.success(request, 'RC Configuration successfully updated')
149 149
150 150 return redirect(conf.get_absolute_url())
151 151
152 152 kwargs = {}
153 153 kwargs['dev_conf'] = conf
154 154 kwargs['form'] = form
155 155 kwargs['form_clock'] = form_clock
156 156 kwargs['rc_lines'] = lines
157 157 kwargs['edit'] = True
158 158
159 159 kwargs['title'] = 'RC Configuration'
160 160 kwargs['suptitle'] = 'Edit'
161 161 kwargs['button'] = 'Update'
162 162
163 163 return render(request, 'rc_conf_edit.html', kwargs)
164 164
165 165
166 166 def add_line(request, conf_id, line_type_id=None, code_id=None):
167 167
168 168 conf = get_object_or_404(RCConfiguration, pk=conf_id)
169 169
170 170 if request.method=='GET':
171 171 if line_type_id:
172 172 line_type = get_object_or_404(RCLineType, pk=line_type_id)
173 173
174 174 if code_id:
175 175 form = RCLineForm(initial={'rc_configuration':conf_id, 'line_type': line_type_id, 'code_id': code_id},
176 176 extra_fields=json.loads(line_type.params))
177 177 else:
178 178 form = RCLineForm(initial={'rc_configuration':conf_id, 'line_type': line_type_id},
179 179 extra_fields=json.loads(line_type.params))
180 180 else:
181 181 line_type = {'id':0}
182 182 form = RCLineForm(initial={'rc_configuration':conf_id})
183 183
184 184 if request.method=='POST':
185 185
186 186 line_type = get_object_or_404(RCLineType, pk=line_type_id)
187 187 form = RCLineForm(request.POST,
188 188 extra_fields=json.loads(line_type.params))
189 189
190 190 if form.is_valid():
191 191 form.save()
192 192 form.instance.update_pulses()
193 193 return redirect('url_edit_rc_conf', conf.id)
194 194
195 195 kwargs = {}
196 196 kwargs['form'] = form
197 197 kwargs['title'] = 'RC Configuration'
198 198 kwargs['suptitle'] = 'Add Line'
199 199 kwargs['button'] = 'Add'
200 200 kwargs['previous'] = conf.get_absolute_url_edit()
201 201 kwargs['dev_conf'] = conf
202 202 kwargs['line_type'] = line_type
203 203
204 204 return render(request, 'rc_add_line.html', kwargs)
205 205
206 206 def edit_codes(request, conf_id, line_id, code_id=None):
207 207
208 208 conf = get_object_or_404(RCConfiguration, pk=conf_id)
209 209 line = get_object_or_404(RCLine, pk=line_id)
210 210 params = json.loads(line.params)
211 211
212 212 if request.method=='GET':
213 213 if code_id:
214 214 code = get_object_or_404(RCLineCode, pk=code_id)
215 215 form = RCLineCodesForm(instance=code)
216 216 else:
217 217 initial = {'code': params['code'],
218 218 'codes': params['codes'] if 'codes' in params else [],
219 219 'number_of_codes': len(params['codes']) if 'codes' in params else 0,
220 220 'bits_per_code': len(params['codes'][0]) if 'codes' in params else 0,
221 221 }
222 222 form = RCLineCodesForm(initial=initial)
223 223
224 224 if request.method=='POST':
225 225 form = RCLineCodesForm(request.POST)
226 226 if form.is_valid():
227 227 params['code'] = request.POST['code']
228 228 params['codes'] = [s for s in request.POST['codes'].split('\r\n') if s]
229 229 line.params = json.dumps(params)
230 230 line.save()
231 231 messages.success(request, 'Line: "%s" has been updated.' % line)
232 232 return redirect('url_edit_rc_conf', conf.id)
233 233
234 234 kwargs = {}
235 235 kwargs['form'] = form
236 236 kwargs['title'] = line
237 237 kwargs['suptitle'] = 'Edit'
238 238 kwargs['button'] = 'Update'
239 239 kwargs['dev_conf'] = conf
240 240 kwargs['previous'] = conf.get_absolute_url_edit()
241 241 kwargs['line'] = line
242 242
243 243 return render(request, 'rc_edit_codes.html', kwargs)
244 244
245 245 def add_subline(request, conf_id, line_id):
246 246
247 247 conf = get_object_or_404(RCConfiguration, pk=conf_id)
248 248 line = get_object_or_404(RCLine, pk=line_id)
249 249
250 250 if request.method == 'POST':
251 251 if line:
252 252 params = json.loads(line.params)
253 253 subparams = json.loads(line.line_type.params)
254 254 if 'params' in subparams:
255 255 dum = {}
256 256 for key, value in subparams['params'].items():
257 257 dum[key] = value['value']
258 258 params['params'].append(dum)
259 259 line.params = json.dumps(params)
260 260 line.save()
261 261 return redirect('url_edit_rc_conf', conf.id)
262 262
263 263 kwargs = {}
264 264
265 265 kwargs['title'] = 'Add new'
266 266 kwargs['suptitle'] = '%s to %s' % (line.line_type.name, line)
267 267
268 268 return render(request, 'confirm.html', kwargs)
269 269
270 270 def remove_line(request, conf_id, line_id):
271 271
272 272 conf = get_object_or_404(RCConfiguration, pk=conf_id)
273 273 line = get_object_or_404(RCLine, pk=line_id)
274 274
275 275 if request.method == 'POST':
276 276 if line:
277 277 try:
278 278 channel = line.channel
279 279 line.delete()
280 280 for ch in range(channel+1, RCLine.objects.filter(rc_configuration=conf).count()+1):
281 281 l = RCLine.objects.get(rc_configuration=conf, channel=ch)
282 282 l.channel = l.channel-1
283 283 l.save()
284 284 messages.success(request, 'Line: "%s" has been deleted.' % line)
285 285 except:
286 286 messages.error(request, 'Unable to delete line: "%s".' % line)
287 287
288 288 return redirect('url_edit_rc_conf', conf.id)
289 289
290 290 kwargs = {}
291 291
292 292 kwargs['object'] = line
293 293 kwargs['delete'] = True
294 294 kwargs['title'] = 'Delete'
295 295 kwargs['suptitle'] = 'Line'
296 296 kwargs['previous'] = conf.get_absolute_url_edit()
297 297 return render(request, 'confirm.html', kwargs)
298 298
299 299
300 300 def remove_subline(request, conf_id, line_id, subline_id):
301 301
302 302 conf = get_object_or_404(RCConfiguration, pk=conf_id)
303 303 line = get_object_or_404(RCLine, pk=line_id)
304 304
305 305 if request.method == 'POST':
306 306 if line:
307 307 params = json.loads(line.params)
308 308 params['params'].remove(params['params'][int(subline_id)-1])
309 309 line.params = json.dumps(params)
310 310 line.save()
311 311
312 312 return redirect('url_edit_rc_conf', conf.id)
313 313
314 314 kwargs = {}
315 315
316 316 kwargs['object'] = line
317 317 kwargs['object_name'] = line.line_type.name
318 318 kwargs['delete_view'] = True
319 319 kwargs['title'] = 'Confirm delete'
320 320
321 321 return render(request, 'confirm.html', kwargs)
322 322
323 323
324 324 def update_lines_position(request, conf_id):
325 325
326 326 conf = get_object_or_404(RCConfiguration, pk=conf_id)
327 327 print("ingreso a update_lines_position")
328 328 if request.method=='POST':
329 329 ch = 0
330 330 for item in request.POST['items'].split('&'):
331 331 line = RCLine.objects.get(pk=item.split('=')[-1])
332 332 line.channel = ch
333 333 line.save()
334 334 ch += 1
335 335
336 336 lines = RCLine.objects.filter(rc_configuration=conf).order_by('channel')
337 337
338 338 for line in lines:
339 339
340 340 params = json.loads(line.params)
341 341 print(params)
342 342 print("Fin de impresion_lines_position")
343 343 line.form = RCLineEditForm(conf=conf, line=line, extra_fields=params)
344 344
345 345 if 'params' in params:
346 346 line.subform = True
347 347 line.subforms = [RCLineEditForm(extra_fields=fields, line=line, subform=i) for i, fields in enumerate(params['params'])]
348 348
349 349 html = render(request, 'rc_lines.html', {'dev_conf':conf, 'rc_lines':lines, 'edit':True})
350 350 #html = render('rc_lines.html', {'dev_conf':conf, 'rc_lines':lines, 'edit':True},request)
351 351 data = {'html': html.content.decode('utf8')}
352 352
353 353 return HttpResponse(json.dumps(data), content_type="application/json")
354 354 return redirect('url_edit_rc_conf', conf.id)
355 355
356 356
357 357 def import_file(request, conf_id):
358 # print("HOLA",flush=True)
359 358 conf = get_object_or_404(RCConfiguration, pk=conf_id)
360 # print("HOLA2",flush=True)
361 359 if request.method=='POST':
362 360 form = RCImportForm(request.POST, request.FILES)
363 # print("HOLA3",flush=True)
364 361 if form.is_valid():
365 #print("HOLA4",flush=True)
366 362 # try:
367 #print("HOLA5",flush=True)
368 data = conf.import_from_file(request.FILES['file_name'])
369 #print("HOLA6",flush=True)
363 data = conf.import_from_file(request.FILES['file_name'])
370 364 conf.dict_to_parms(data)
371 #print("1",flush=True)
372 365 conf.update_pulses()
373 #print("2",flush=True)
374 366 messages.success(request, 'Configuration "%s" loaded succesfully' % request.FILES['file_name'])
375 367 return redirect(conf.get_absolute_url_edit())
376 368
377 369 # except Exception as e:
378 370 # messages.error(request, 'Error parsing file: "%s" - %s' % (request.FILES['file_name'], repr(e)))
379 371 else:
380 372 messages.warning(request, 'Your current configuration will be replaced')
381 373 form = RCImportForm()
382 374
383 375 kwargs = {}
384 376 kwargs['form'] = form
385 377 kwargs['title'] = 'RC Configuration'
386 378 kwargs['suptitle'] = 'Import file'
387 379 kwargs['button'] = 'Upload'
388 380 kwargs['previous'] = conf.get_absolute_url()
389 381
390 382 return render(request, 'rc_import.html', kwargs)
391 383
392 384
393 385 def plot_pulses(request, conf_id):
394 386
395 387 conf = get_object_or_404(RCConfiguration, pk=conf_id)
396 388 km = True if 'km' in request.GET else False
397 389
398 390 script, div = conf.plot_pulses(km=km)
399 391
400 392 kwargs = {}
401 393 kwargs['no_sidebar'] = True
402 394 kwargs['title'] = 'RC Pulses'
403 395 kwargs['suptitle'] = conf.name
404 396 kwargs['div'] = mark_safe(div)
405 397 kwargs['script'] = mark_safe(script)
406 398 kwargs['units'] = conf.km2unit
407 399 kwargs['kms'] = 1/conf.km2unit
408 400
409 401 if km:
410 402 kwargs['km_selected'] = True
411 403
412 404 if 'json' in request.GET:
413 405 return HttpResponse(json.dumps({'div':mark_safe(div), 'script':mark_safe(script)}), content_type="application/json")
414 406 else:
415 407 return render(request, 'rc_pulses.html', kwargs)
416 408
417 409 def plot_pulses2(request, conf_id):
418 410
419 411 conf = get_object_or_404(RCConfiguration, pk=conf_id)
420 412 km = True if 'km' in request.GET else False
421 413
422 414 script, div = conf.plot_pulses2(km=km)
423 415
424 416 kwargs = {}
425 417 kwargs['no_sidebar'] = True
426 418 kwargs['title'] = 'RC Pulses'
427 419 kwargs['suptitle'] = conf.name
428 420 kwargs['div'] = mark_safe(div)
429 421 kwargs['script'] = mark_safe(script)
430 422 kwargs['units'] = conf.km2unit
431 423 kwargs['kms'] = 1/conf.km2unit
432 424
433 425 if km:
434 426 kwargs['km_selected'] = True
435 427
436 428 if 'json' in request.GET:
437 429 return HttpResponse(json.dumps({'div':mark_safe(div), 'script':mark_safe(script)}), content_type="application/json")
438 430 else:
439 431 return render(request, 'rc_pulses.html', kwargs)
440 432
441 433 def conf_raw(request, conf_id):
442 434 conf = get_object_or_404(RCConfiguration, pk=conf_id)
443 435 raw = conf.write_device(raw=True)
444 436 return HttpResponse(raw, content_type='application/json') No newline at end of file
@@ -1,74 +1,74
1 1 version: '3'
2 2 services:
3 3 # Django app
4 4 radarsys:
5 5 container_name: 'radarsys'
6 6 build: .
7 7 restart: always
8 8 image: radarsys
9 9 ports:
10 10 - 8000:8000
11 11 env_file: .env
12 12 links:
13 13 - radarsys-postgres
14 14 volumes:
15 15 - './:/radarsys'
16 16 - '${DOCKER_DATA}/static:/radarsys/static'
17 17 labels:
18 18 ofelia.enabled: "true"
19 19 # ofelia.job-exec.restart-reception.schedule: "0 1/5 * * * *"
20 20 ofelia.job-exec.test.schedule: "@every 5s"
21 ofelia.job-exec.test.command: "python manage.py hello"
21 ofelia.job-exec.test.command: "python manage.py scheduler"
22 22 # ofelia.job-exec.restart-pedestal.schedule: "0 2/10 * * * *"
23 23 # ofelia.job-exec.restart-pedestal.command: "python manage.py restart_pedestal"
24 24 # ofelia.job-exec.restart-experiment.schedule: "@midnight"
25 25 # ofelia.job-exec.restart-experiment.command: "python manage.py restart_experiment"
26 26 depends_on:
27 27 - radarsys-postgres
28 28
29 29 # PostgreSQL
30 30 radarsys-postgres:
31 31 container_name: 'radarsys-postgres'
32 32 build: ./postgres/
33 33 volumes:
34 34 - ./postgres/docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d
35 35 - pgdata:/var/lib/postgresql/data
36 36 ports:
37 37 - 5432:5432
38 38 expose:
39 39 - 5432
40 40 env_file: .env
41 41
42 42 #Web Server
43 43 radarsys-nginx:
44 44 container_name: 'radarsys-nginx'
45 45 restart: always
46 46 build: ./nginx/
47 47 ports:
48 - '0.0.0.0:8086:80'
48 - '0.0.0.0:80:80'
49 49 volumes_from:
50 50 - radarsys
51 51 links:
52 52 - radarsys:radarsys
53 53 depends_on:
54 54 - radarsys
55 55
56 56 #Ofelia Scheduler
57 57 radarsys-job:
58 58 container_name: 'radarsys-job'
59 59 image: mcuadros/ofelia:v0.3.6
60 60 depends_on:
61 61 - radarsys
62 62 # networks:
63 63 # - backend_sirm
64 64 command: daemon --docker
65 65 volumes:
66 66 - /var/run/docker.sock:/var/run/docker.sock:ro
67 67 logging:
68 68 driver: "json-file"
69 69 options:
70 70 max-size: "12m"
71 71
72 72 volumes:
73 73 pgdata:
74 74 driver: local
@@ -1,157 +1,158
1 1 """
2 2 Django settings for radarsys project.
3 3
4 4 Generated by 'django-admin startproject' using Django 1.8.6.
5 5
6 6 For more information on this file, see
7 7 https://docs.djangoproject.com/en/1.8/topics/settings/
8 8
9 9 For the full list of settings and their values, see
10 10 https://docs.djangoproject.com/en/1.8/ref/settings/
11 11 """
12 12
13 13 # Build paths inside the project like this: os.path.join(BASE_DIR, ...)
14 14 import os
15 15
16 16 BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
17 17
18 18 # Quick-start development settings - unsuitable for production
19 19 # See https://docs.djangoproject.com/en/1.8/howto/deployment/checklist/
20 20
21 21 # SECURITY WARNING: keep the secret key used in production secret!
22 22 SECRET_KEY = 'xshb$k5fc-+j16)cvyffj&9u__0q3$l!hieh#+tbzqg)*f^km0'
23 23
24 24 # SECURITY WARNING: don't run with debug turned on in production!
25 25 DEBUG = True
26 26
27 27 ALLOWED_HOSTS = ['*']
28 28
29 29 CSRF_TRUSTED_ORIGINS=[
30 30 "http://*.localhost:8030",
31 31 "http://localhost:8030",
32 32 "http://127.0.0.1:8030",
33 33 "http://*.localhost:8086",
34 "http://0.0.0.0:8086",
34 35 "http://localhost:8086",
35 36 "http://127.0.0.1:8086"
36 37 ]
37 38 #Si se requiere que la aplicación salga de este entorno, para otros usuarios es necesario hacer una API request https://fractalideas.com/blog/making-react-and-django-play-well-together-single-page-app-model/
38 39
39 40 # Application definition
40 41
41 42 INSTALLED_APPS = [
42 43 'django.contrib.admin',
43 44 'django.contrib.auth',
44 45 'django.contrib.contenttypes',
45 46 'django.contrib.sessions',
46 47 'django.contrib.messages',
47 48 'django.contrib.staticfiles',
48 49 'apps.accounts',
49 50 'apps.main',
50 51 'apps.misc',
51 52 'apps.rc',
52 53 'apps.dds',
53 54 'apps.jars',
54 55 'apps.usrp',
55 56 'apps.abs',
56 57 'apps.cgs',
57 58 'apps.dds_rest',
58 59 'apps.atrad',
59 60 "django_bootstrap5",
60 61 'polymorphic',
61 62 'radarsys',
62 63 ]
63 64
64 65 MIDDLEWARE = [
65 66 'django.middleware.security.SecurityMiddleware',
66 67 'django.contrib.sessions.middleware.SessionMiddleware',
67 68 'django.middleware.common.CommonMiddleware',
68 69 'django.middleware.csrf.CsrfViewMiddleware',
69 70 'django.contrib.auth.middleware.AuthenticationMiddleware',
70 71 'django.contrib.messages.middleware.MessageMiddleware',
71 72 'django.middleware.clickjacking.XFrameOptionsMiddleware',
72 73
73 74 ]
74 75
75 76 ROOT_URLCONF = 'radarsys.urls'
76 77
77 78 TEMPLATES = [
78 79 {
79 80 'BACKEND': 'django.template.backends.django.DjangoTemplates',
80 81 'DIRS': [os.path.join(BASE_DIR, "templates")],
81 82 'APP_DIRS': True,
82 83 'OPTIONS': {
83 84 'context_processors': [
84 85 'django.template.context_processors.debug',
85 86 'django.template.context_processors.request',
86 87 'django.contrib.auth.context_processors.auth',
87 88 'django.contrib.messages.context_processors.messages',
88 89 'apps.main.processors.radarsys_globals',
89 90 ],
90 91 },
91 92 },
92 93 ]
93 94
94 95 WSGI_APPLICATION = 'radarsys.wsgi.application'
95 96 ASGI_APPLICATION = 'radarsys.asgi.application'
96 97
97 98 # Database
98 99 # https://docs.djangoproject.com/en/1.8/ref/settings/#databases
99 100
100 101 DATABASES = {
101 102 # 'default': {
102 103 # 'ENGINE': 'django.db.backends.sqlite3',
103 104 # 'NAME': 'radarsys.sqlite',
104 105 # }
105 106 'default': {
106 107 'ENGINE': 'django.db.backends.postgresql_psycopg2',
107 108 'NAME': os.environ.get('DB_NAME', 'radarsys'),
108 109 'USER': os.environ.get('DB_USER', 'docker'),
109 110 'PASSWORD': os.environ.get('DB_PASSWORD', 'docker'),
110 111 'HOST': os.environ.get('POSTGRES_PORT_5432_TCP_ADDR', 'localhost'),
111 112 'PORT': os.environ.get('POSTGRES_PORT_5432_TCP_PORT', '5432'),
112 113 }
113 114 }
114 115
115 116 # Internationalization
116 117 # https://docs.djangoproject.com/en/1.8/topics/i18n/
117 118
118 119 LANGUAGE_CODE = 'en-us'
119 120
120 121 USE_TZ = False #True
121 122
122 123 TIME_ZONE = os.environ.get('TZ', 'America/Lima')
123 124
124 125 USE_I18N = True
125 126
126 127 USE_L10N = True
127 128
128 129 # Static files (CSS, JavaScript, Images)
129 130 # https://docs.djangoproject.com/en/1.8/howto/static-files/
130 131
131 132 MEDIA_URL = '/media/'
132 133 MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
133 134
134 135 STATICFILES_DIRS = [
135 136 os.path.join(BASE_DIR, 'radarsys/static/')
136 137 ]
137 138
138 139 STATIC_URL = '/static/'
139 140 STATIC_ROOT = os.path.join(BASE_DIR, 'static')
140 141
141 142 LOGIN_URL = '/accounts/login'
142 143 LOGOUT_URL = 'logout'
143 144 LOGIN_REDIRECT_URL = '/admin'
144 145 LOGOUT_REDIRECT_URL = '/'
145 146
146 147 STATICFILES_FINDERS = (
147 148 'django.contrib.staticfiles.finders.FileSystemFinder',
148 149 'django.contrib.staticfiles.finders.AppDirectoriesFinder',
149 150 )
150 151
151 152
152 153 import django
153 154 from django.utils.encoding import force_str
154 155 django.utils.encoding.force_text = force_str
155 156
156 157 # choose of auto-created primary keys
157 158 DEFAULT_AUTO_FIELD='django.db.models.AutoField'
1 NO CONTENT: file renamed from radarsys/static/js/atrad-conf.js to radarsys/static/js/atrad-mainpage.js
1 NO CONTENT: modified file chmod 100644 => 100755
1 NO CONTENT: modified file chmod 100644 => 100755
1 NO CONTENT: modified file chmod 100644 => 100755
1 NO CONTENT: modified file chmod 100644 => 100755
1 NO CONTENT: modified file chmod 100644 => 100755
1 NO CONTENT: modified file chmod 100644 => 100755
1 NO CONTENT: modified file chmod 100644 => 100755
1 NO CONTENT: modified file chmod 100644 => 100755
1 NO CONTENT: modified file chmod 100644 => 100755
1 NO CONTENT: modified file chmod 100644 => 100755
1 NO CONTENT: modified file chmod 100644 => 100755
1 NO CONTENT: modified file chmod 100644 => 100755
1 NO CONTENT: modified file chmod 100644 => 100755
1 NO CONTENT: modified file chmod 100644 => 100755
1 NO CONTENT: modified file chmod 100644 => 100755
1 NO CONTENT: modified file chmod 100644 => 100755
1 NO CONTENT: modified file chmod 100644 => 100755
1 NO CONTENT: modified file chmod 100644 => 100755
1 NO CONTENT: modified file chmod 100644 => 100755
General Comments 0
You need to be logged in to leave comments. Login now