##// END OF EJS Templates
Add support to read abs module status
Juan C. Espinoza -
r326:f70d4e6cdcb2
parent child
Show More
@@ -1,876 +1,879
1 1 from django.db import models
2 from apps.main.models import Configuration
2 from apps.main.models import Configuration, User
3 3 from django.core.urlresolvers import reverse
4 # Create your models here.
5 4 from celery.execute import send_task
6 5 from datetime import datetime
7 6 import ast
8 7 import socket
9 8 import json
10 9 import requests
11 10 import struct
12 11 import os, sys, time
13 12
14 import multiprocessing
15
16
17 13 antenna_default = json.dumps({
18 14 "antenna_up": [[0.0,0.0,0.0,0.0,0.5,0.5,0.5,0.5],
19 15 [0.0,0.0,0.0,0.0,0.5,0.5,0.5,0.5],
20 16 [0.0,0.0,0.0,0.0,0.5,0.5,0.5,0.5],
21 17 [0.0,0.0,0.0,0.0,0.5,0.5,0.5,0.5],
22 18 [0.5,0.5,0.5,0.5,1.0,1.0,1.0,1.0],
23 19 [0.5,0.5,0.5,0.5,1.0,1.0,1.0,1.0],
24 20 [0.5,0.5,0.5,0.5,1.0,1.0,1.0,1.0],
25 21 [0.5,0.5,0.5,0.5,1.0,1.0,1.0,1.0]
26 22 ]
27 23 ,
28 24 "antenna_down": [[0.0,0.0,0.0,0.0,0.5,0.5,0.5,0.5],
29 25 [0.0,0.0,0.0,0.0,0.5,0.5,0.5,0.5],
30 26 [0.0,0.0,0.0,0.0,0.5,0.5,0.5,0.5],
31 27 [0.0,0.0,0.0,0.0,0.5,0.5,0.5,0.5],
32 28 [0.5,0.5,0.5,0.5,3.0,3.0,3.0,3.0],
33 29 [0.5,0.5,0.5,0.5,3.0,3.0,3.0,3.0],
34 30 [0.5,0.5,0.5,0.5,3.0,3.0,3.0,3.0],
35 31 [0.5,0.5,0.5,0.5,3.0,3.0,3.0,3.0]],
36 32 })
37 33
38 34
39 35 tx_default = json.dumps({
40 36 "up": [[1,1,1,1,0,0,0,0],
41 37 [1,1,1,1,0,0,0,0],
42 38 [1,1,1,1,0,0,0,0],
43 39 [1,1,1,1,0,0,0,0],
44 40 [0,0,0,0,1,1,1,1],
45 41 [0,0,0,0,1,1,1,1],
46 42 [0,0,0,0,1,1,1,1],
47 43 [0,0,0,0,1,1,1,1]],
48 44
49 45 "down": [[1,1,1,1,0,0,0,0],
50 46 [1,1,1,1,0,0,0,0],
51 47 [1,1,1,1,0,0,0,0],
52 48 [1,1,1,1,0,0,0,0],
53 49 [0,0,0,0,1,1,1,1],
54 50 [0,0,0,0,1,1,1,1],
55 51 [0,0,0,0,1,1,1,1],
56 52 [0,0,0,0,1,1,1,1]],
57 53 })
58 54
59 55 rx_default = json.dumps({
60 56 "up": [[1,1,1,1,0,0,0,0],
61 57 [1,1,1,1,0,0,0,0],
62 58 [1,1,1,1,0,0,0,0],
63 59 [1,1,1,1,0,0,0,0],
64 60 [0,0,0,0,1,1,1,1],
65 61 [0,0,0,0,1,1,1,1],
66 62 [0,0,0,0,1,1,1,1],
67 63 [0,0,0,0,1,1,1,1]],
68 64
69 65 "down": [[1,1,1,1,0,0,0,0],
70 66 [1,1,1,1,0,0,0,0],
71 67 [1,1,1,1,0,0,0,0],
72 68 [1,1,1,1,0,0,0,0],
73 69 [0,0,0,0,1,1,1,1],
74 70 [0,0,0,0,1,1,1,1],
75 71 [0,0,0,0,1,1,1,1],
76 72 [0,0,0,0,1,1,1,1]],
77 73 })
78 74
79 75 status_default = '0000000000000000000000000000000000000000000000000000000000000000'
80 76 default_messages = {}
81 77
82 78 for i in range(1,65):
83 79 default_messages[str(i)] = "Module "+str(i)
84 80
85 81
86 82 ues_default = json.dumps({
87 83 "up": [0.533333,0.00000,1.06667,0.00000],
88 84 "down": [0.533333,0.00000,1.06667,0.00000]
89 85 })
90 86
91 87 onlyrx_default = json.dumps({
92 88 "up": False,
93 89 "down": False
94 90 })
95 91
96 92 def up_convertion(cadena):
97 93 valores = []
98 94 for c in cadena:
99 95 if c == 1.0: valores=valores+['000']
100 96 if c == 2.0: valores=valores+['001']
101 97 if c == 3.0: valores=valores+['010']
102 98 if c == 0.0: valores=valores+['011']
103 99 if c == 0.5: valores=valores+['100']
104 100 if c == 1.5: valores=valores+['101']
105 101 if c == 2.5: valores=valores+['110']
106 102 if c == 3.5: valores=valores+['111']
107 103
108 104 return valores
109 105
110 106 def up_conv_bits(value):
111 107
112 108 if value == 1.0: bits="000"
113 109 if value == 2.0: bits="001"
114 110 if value == 3.0: bits="010"
115 111 if value == 0.0: bits="011"
116 112 if value == 0.5: bits="100"
117 113 if value == 1.5: bits="101"
118 114 if value == 2.5: bits="110"
119 115 if value == 3.5: bits="111"
120 116
121 117 return bits
122 118
123 119 def down_convertion(cadena):
124 120 valores = []
125 121 for c in cadena:
126 122 if c == 1.0: valores=valores+['000']
127 123 if c == 2.0: valores=valores+['001']
128 124 if c == 3.0: valores=valores+['010']
129 125 if c == 0.0: valores=valores+['011']
130 126 if c == 0.5: valores=valores+['100']
131 127 if c == 1.5: valores=valores+['101']
132 128 if c == 2.5: valores=valores+['110']
133 129 if c == 3.5: valores=valores+['111']
134 130
135 131 return valores
136 132
137 133 def down_conv_bits(value):
138 134
139 135 if value == 1.0: bits="000"
140 136 if value == 2.0: bits="001"
141 137 if value == 3.0: bits="010"
142 138 if value == 0.0: bits="011"
143 139 if value == 0.5: bits="100"
144 140 if value == 1.5: bits="101"
145 141 if value == 2.5: bits="110"
146 142 if value == 3.5: bits="111"
147 143
148 144 return bits
149 145
150 146 def up_conv_value(bits):
151 147
152 148 if bits == "000": value=1.0
153 149 if bits == "001": value=2.0
154 150 if bits == "010": value=3.0
155 151 if bits == "011": value=0.0
156 152 if bits == "100": value=0.5
157 153 if bits == "101": value=1.5
158 154 if bits == "110": value=2.5
159 155 if bits == "111": value=3.5
160 156
161 157 return value
162 158
163 159 def down_conv_value(bits):
164 160
165 161 if bits == "000": value=1.0
166 162 if bits == "001": value=2.0
167 163 if bits == "010": value=3.0
168 164 if bits == "011": value=0.0
169 165 if bits == "100": value=0.5
170 166 if bits == "101": value=1.5
171 167 if bits == "110": value=2.5
172 168 if bits == "111": value=3.5
173 169
174 170 return value
175 171
176 172 def ip2position(module_number):
177 173 j=0
178 174 i=0
179 175 for x in range(0,module_number-1):
180 176 j=j+1
181 177 if j==8:
182 178 i=i+1
183 179 j=0
184 180
185 181 pos = [i,j]
186 182 return pos
187 183
188 184
189 185 def fromBinary2Char(binary_string):
190 186 number = int(binary_string, 2)
191 187 #Plus 33 to avoid more than 1 characters values such as: '\x01'-'\x1f'
192 188 number = number + 33
193 189 char = chr(number)
194 190 return char
195 191
196 192 def fromChar2Binary(char):
197 193 number = ord(char) - 33
198 194 #Minus 33 to get the real value
199 195 bits = bin(number)[2:]
200 196 #To ensure we have a string with 6bits
201 197 if len(bits) < 6:
202 198 bits = bits.zfill(6)
203 199 return bits
204 200
205 201 OPERATION_MODES = (
206 202 (0, 'Manual'),
207 203 (1, 'Automatic'),
208 204 )
209 205
210 206
211 207 class ABSConfiguration(Configuration):
212 208 active_beam = models.PositiveSmallIntegerField(verbose_name='Active Beam', default=0)
213 module_status = models.CharField(verbose_name='Module Status', max_length=10000, default=json.dumps(status_default))
209 module_status = models.CharField(verbose_name='Module Status', max_length=10000, default=status_default)
214 210 operation_mode = models.PositiveSmallIntegerField(verbose_name='Operation Mode', choices=OPERATION_MODES, default = 0)
215 211 operation_value = models.FloatField(verbose_name='Periodic (seconds)', default="10", null=True, blank=True)
216 212 module_messages = models.CharField(verbose_name='Modules Messages', max_length=10000, default=json.dumps(default_messages))
217 213
218 214 class Meta:
219 215 db_table = 'abs_configurations'
220 216
221 217 def get_absolute_url_plot(self):
222 218 return reverse('url_plot_abs_patterns', args=[str(self.id)])
223 219
224 220
225 221 def parms_to_dict(self):
226 222
227 223 parameters = {}
228 224
229 225 parameters['device_id'] = self.device.id
230 226 parameters['label'] = self.label
231 227 parameters['device_type'] = self.device.device_type.name
232 228 parameters['beams'] = {}
233 229
234 230 beams = ABSBeam.objects.filter(abs_conf=self)
235 231 b=1
236 232 for beam in beams:
237 233 #absbeam = ABSBeam.objects.get(pk=beams[beam])
238 234 parameters['beams']['beam'+str(b)] = beam.parms_to_dict()#absbeam.parms_to_dict()
239 235 b+=1
240 236
241 237 return parameters
242 238
243 239
244 240 def dict_to_parms(self, parameters):
245 241
246 242 self.label = parameters['label']
247 243
248 244 absbeams = ABSBeam.objects.filter(abs_conf=self)
249 245 beams = parameters['beams']
250 246
251 247 if absbeams:
252 248 beams_number = len(beams)
253 249 absbeams_number = len(absbeams)
254 250 if beams_number==absbeams_number:
255 251 i = 1
256 252 for absbeam in absbeams:
257 253 absbeam.dict_to_parms(beams['beam'+str(i)])
258 254 i = i+1
259 255 elif beams_number > absbeams_number:
260 256 i = 1
261 257 for absbeam in absbeams:
262 258 absbeam.dict_to_parms(beams['beam'+str(i)])
263 259 i=i+1
264 260 for x in range(i,beams_number+1):
265 261 new_beam = ABSBeam(
266 262 name =beams['beam'+str(i)]['name'],
267 263 antenna =json.dumps(beams['beam'+str(i)]['antenna']),
268 264 abs_conf = self,
269 265 tx =json.dumps(beams['beam'+str(i)]['tx']),
270 266 rx =json.dumps(beams['beam'+str(i)]['rx']),
271 267 ues =json.dumps(beams['beam'+str(i)]['ues']),
272 268 only_rx =json.dumps(beams['beam'+str(i)]['only_rx'])
273 269 )
274 270 new_beam.save()
275 271 i=i+1
276 272 else: #beams_number < absbeams_number:
277 273 i = 1
278 274 for absbeam in absbeams:
279 275 if i <= beams_number:
280 276 absbeam.dict_to_parms(beams['beam'+str(i)])
281 277 i=i+1
282 278 else:
283 279 absbeam.delete()
284 280 else:
285 281 for beam in beams:
286 282 new_beam = ABSBeam(
287 283 name =beams[beam]['name'],
288 284 antenna =json.dumps(beams[beam]['antenna']),
289 285 abs_conf = self,
290 286 tx =json.dumps(beams[beam]['tx']),
291 287 rx =json.dumps(beams[beam]['rx']),
292 288 ues =json.dumps(beams[beam]['ues']),
293 289 only_rx =json.dumps(beams[beam]['only_rx'])
294 290 )
295 291 new_beam.save()
296 292
297 293
298 294
299 295 def update_from_file(self, parameters):
300 296
301 297 self.dict_to_parms(parameters)
302 298 self.save()
303 299
304 300
305 301 def get_beams(self, **kwargs):
306 302 '''
307 303 This function returns ABS Configuration beams
308 304 '''
309 305 return ABSBeam.objects.filter(abs_conf=self.pk, **kwargs)
310 306
311 307 def clone(self, **kwargs):
312 308
313 309 beams = self.get_beams()
314 310 self.pk = None
315 311 self.id = None
316 312 for attr, value in kwargs.items():
317 313 setattr(self, attr, value)
318 314 self.save()
319 315
320 316 for beam in beams:
321 317 beam.clone(abs_conf=self)
322 318
323 319 #-----For Active Beam-----
324 320 new_beams = ABSBeam.objects.filter(abs_conf=self)
325 321 self.active_beam = new_beams[0].id
326 322 self.save()
327 323 #-----For Active Beam-----
328 324 #-----For Device Status---
329 325 self.device.status = 3
330 326 self.device.save()
331 327 #-----For Device Status---
332 328
333 329 return self
334 330
335 331
336 332 def start_device(self):
337 333
338 334 if self.device.status == 3:
339 335
340 336 try:
341 337 #self.write_device()
342 338 send_task('task_change_beam', [self.id],)
343 339 self.message = 'ABS running'
344 340
345 341 except Exception as e:
346 342 self.message = str(e)
347 343 return False
348 344
349 345 return True
350 346
351 347 else:
352 348 self.message = 'Please, select Write ABS Device first.'
353 349 return False
354 350
355 351
356 352 def stop_device(self):
357 353
358 354 self.device.status = 2
359 355 self.device.save()
360 356 self.message = 'ABS has been stopped.'
361 357 self.save()
362 358
363 359 return True
364 360
365 361
366 362 def write_device(self):
367 363
368 364 """
369 365 This function sends the beams list to every abs module.
370 366 It needs 'module_conf' function
371 367 """
372 368
373 369 beams = ABSBeam.objects.filter(abs_conf=self)
374 370 nbeams = len(beams)
375 371 if self.connected_modules() == 0 :
376 372 self.message = "No ABS Module detected."
377 373 return False
378 374
379 375 #-------------Write each abs module-----------
380 376
381 377 if beams:
382 378 block_id = 0
383 379 message = 'SNDF{:03d}{:02d}{:02d}'.format(nbeams, nbeams, block_id)
384 380 for i, status in enumerate(self.module_status):
385 381 message += ''.join([fromBinary2Char(beam.module_6bits(i)) for beam in beams])
386 382 status = ['0'] * 64
387 383 n = 0
388 384
389 385 sock = self.send_multicast(message)
390 386
391 387 for i in range(32):
392 388 try:
393 389 data, address = sock.recvfrom(1024)
394 390 print address, data
395 391 if data == '1':
396 392 status[int(address[0][10:])-1] = '3'
397 393 elif data == '0':
398 394 status[int(address[0][10:])-1] = '1'
399 395 except Exception as e:
400 396 print 'Error {}'.format(e)
401 397 n += 1
402 398 sock.close()
403 399 else:
404 400 self.message = "ABS Configuration does not have beams"
405 401 return False
406 402
407 403 if n == 64:
408 404 self.message = "Could not write ABS Modules"
409 405 self.device.status = 0
410 406 self.module_status = ''.join(status)
411 407 self.save()
412 408 return False
413 409 else:
414 410 self.message = "ABS Beams List have been sent to ABS Modules"
415 411 self.active_beam = beams[0].pk
416 412
417 413 self.device.status = 3
418 414 self.module_status = ''.join(status)
419 415 self.save()
416 for u in User.objects.all():
417 u.profile.abs_active = self
418 u.save()
420 419 return True
421 420
422 421
423 422 def read_module(self, module):
424 423
425 424 """
426 425 Read out-bits (up-down) of 1 abs module NOT for Configuration
427 426 """
428 427
429 428 ip_address = self.device.ip_address
430 429 ip_address = ip_address.split('.')
431 430 module_seq = (ip_address[0],ip_address[1],ip_address[2])
432 431 dot = '.'
433 432 module_ip = dot.join(module_seq)+'.'+str(module)
434 433 module_port = self.device.port_address
435 434 read_route = 'http://'+module_ip+':'+str(module_port)+'/read'
436 435
437 436 module_status = json.loads(self.module_status)
438 437 print(read_route)
439 438
440 439 module_bits = ''
441 440
442 441 try:
443 442 r_read = requests.get(read_route, timeout=0.5)
444 443 answer = r_read.json()
445 444 module_bits = answer['allbits']
446 445 except:
447 446 return {}
448 447
449 448 return module_bits
450 449
451 450 def read_device(self):
452 451
453 452 parms = {}
454 453 # Reads active modules.
455 454 module_status = json.loads(self.module_status)
456 455 total = 0
457 456 for status in module_status:
458 457 if module_status[status] != 0:
459 458 module_bits = self.read_module(int(status))
460 459 bits={}
461 460 if module_bits:
462 461 bits = (str(module_bits['um2']) + str(module_bits['um1']) + str(module_bits['um0']) +
463 462 str(module_bits['dm2']) + str(module_bits['dm1']) + str(module_bits['dm0']) )
464 463 parms[str(status)] = bits
465 464
466 465 total +=1
467 466
468 467 if total==0:
469 468 self.message = "No ABS Module detected. Please select 'Status'."
470 469 return False
471 470
472 471
473 472
474 473 self.message = "ABS Modules have been read"
475 474 #monitoreo_tx = JROABSClnt_01CeCnMod000000MNTR10
476 475 return parms
477 476
478 477
479 478 def connected_modules(self):
480 479 """
481 480 This function returns the number of connected abs-modules without updating.
482 481 """
483 482 num = 0
484 483 print(self.module_status)
485 484 for i, status in enumerate(self.module_status):
486 485 if status != '0':
487 486 num += 1
488 487 #print('status {}:{}'.format(i+1, status))
489 488 return num
490 489
491 490 def send_multicast(self, message):
492 491
493 492 multicast_group = ('224.3.29.71', 10000)
494 493 # Create the datagram socket
495 494 sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
496 495 sock.settimeout(1)
497 # sock.bind((local_ip, 10000))
498 496 local_ip = os.environ.get('LOCAL_IP', '127.0.0.1')
499 local_ip = '192.168.1.128'
500 497 sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_IF, socket.inet_aton(local_ip))
501 sent = sock.sendto(message, multicast_group)
498 sock.sendto(message, multicast_group)
502 499 print('Sending ' + message)
503 500 return sock
504 501
505 502 def status_device(self):
506 503 """
507 504 This function returns the status of all abs-modules as one.
508 505 If at least one module is connected, its answer is "1"
509 506 """
510 507
511 508 sock = self.send_multicast('MNTR')
512 509
513 510 n = 0
514 511 status = ['0'] * 64
515 512 for i in range(32):
516 513 #if True:
517 514 try:
518 515 address = None
519 516 data, address = sock.recvfrom(1024)
520 print address, data
521 if data == '1':
522 status[int(address[0][10:])-1] = '3'
523 elif data == '0':
524 status[int(address[0][10:])-1] = '1'
517 x = int(address[0][10:])-1
518 if data[0] == '1':
519 remote = fromChar2Binary(data[1])
520 local = ABSBeam.objects.get(pk=self.active_beam).module_6bits(x)
521 if local == remote:
522 status[x] = '3'
523 print('Module: {} connected...igual'.format(address))
524 else:
525 status[x] = '2'
526 print('Module: {} connected...diferente'.format(address))
527 elif data[0] == '0':
528 status[x] = '1'
525 529 n += 1
526 print('Module: {} connected'.format(address))
527 530 except:
528 531 print('Module: {} error'.format(address))
529 532 pass
530 533 sock.close()
531 534
532 535 if n > 0:
533 536 self.message = 'ABS modules Status have been updated.'
534 537 self.device.status = 1
535 538 else:
536 539 self.device.status = 0
537 540 self.message = 'No ABS module is connected.'
538 541 self.module_status = ''.join(status)
539 542 self.save()
540 543
541 544 return self.device.status
542 545
543 546
544 547 def send_beam(self, beam_pos):
545 548 """
546 549 This function connects to a multicast group and sends the beam number
547 550 to all abs modules.
548 551 """
549 552
550 553 # Se manda a cero RC para poder realizar cambio de beam
551 554 if self.experiment is None:
552 555 confs = []
553 556 else:
554 557 confs = Configuration.objects.filter(experiment = self.experiment).filter(type=0)
555 558 confdds = ''
556 559 confjars = ''
557 560 confrc = ''
558 561 #TO STOP DEVICES: DDS-JARS-RC
559 562 for i in range(0,len(confs)):
560 563 if i==0:
561 564 for conf in confs:
562 565 if conf.device.device_type.name == 'dds':
563 566 confdds = conf
564 567 confdds.stop_device()
565 568 break
566 569 if i==1:
567 570 for conf in confs:
568 571 if conf.device.device_type.name == 'jars':
569 572 confjars = conf
570 573 confjars.stop_device()
571 574 break
572 575 if i==2:
573 576 for conf in confs:
574 577 if conf.device.device_type.name == 'rc':
575 578 confrc = conf
576 579 confrc.stop_device()
577 580 break
578 581 if beam_pos > 0:
579 582 beam_pos = beam_pos - 1
580 583 else:
581 584 beam_pos = 0
582 585
583 586 #El indice del apunte debe ser menor que el numero total de apuntes
584 587 #El servidor tcp en el embebido comienza a contar desde 0
585 588 status = ['0'] * 64
586 589 message = 'CHGB{}'.format(beam_pos)
587 590 sock = self.send_multicast(message)
588 591 for i in range(32):
589 592 try:
590 593 data, address = sock.recvfrom(1024)
591 594 print address, data
592 595 if data == '1':
593 596 status[int(address[0][10:])-1] = '3'
594 597 elif data == '0':
595 598 status[int(address[0][10:])-1] = '1'
596 599 except Exception as e:
597 600 print 'Error {}'.format(e)
598 601 pass
599 602
600 603 sock.close()
601 604
602 605 #Start DDS-RC-JARS
603 606 if confdds:
604 607 confdds.start_device()
605 608 if confrc:
606 609 #print confrc
607 610 confrc.start_device()
608 611 if confjars:
609 612 confjars.start_device()
610 613
611 614 self.message = "ABS Beam has been changed"
612 615 self.module_status = ''.join(status)
613 616 self.save()
614 617 return True
615 618
616 619
617 620 def get_absolute_url_import(self):
618 621 return reverse('url_import_abs_conf', args=[str(self.id)])
619 622
620 623
621 624 class ABSBeam(models.Model):
622 625
623 626 name = models.CharField(max_length=60, default='Beam')
624 627 antenna = models.CharField(verbose_name='Antenna', max_length=1000, default=antenna_default)
625 628 abs_conf = models.ForeignKey(ABSConfiguration, null=True, verbose_name='ABS Configuration')
626 629 tx = models.CharField(verbose_name='Tx', max_length=1000, default=tx_default)
627 630 rx = models.CharField(verbose_name='Rx', max_length=1000, default=rx_default)
628 631 s_time = models.TimeField(verbose_name='Star Time', default='00:00:00')
629 632 e_time = models.TimeField(verbose_name='End Time', default='23:59:59')
630 633 ues = models.CharField(verbose_name='Ues', max_length=100, default=ues_default)
631 634 only_rx = models.CharField(verbose_name='Only RX', max_length=40, default=onlyrx_default)
632 635
633 636 class Meta:
634 637 db_table = 'abs_beams'
635 638
636 639 def __unicode__(self):
637 640 return u'%s' % (self.name)
638 641
639 642 def parms_to_dict(self):
640 643
641 644 parameters = {}
642 645 parameters['name'] = self.name
643 646 parameters['antenna'] = ast.literal_eval(self.antenna)
644 647 parameters['abs_conf'] = self.abs_conf.name
645 648 parameters['tx'] = ast.literal_eval(self.tx)
646 649 parameters['rx'] = ast.literal_eval(self.rx)
647 650 parameters['s_time'] = self.s_time.strftime("%H:%M:%S")
648 651 parameters['e_time'] = self.e_time.strftime("%H:%M:%S")
649 652 parameters['ues'] = ast.literal_eval(self.ues)
650 653 parameters['only_rx'] = json.loads(self.only_rx)
651 654
652 655 return parameters
653 656
654 657 def dict_to_parms(self, parameters):
655 658
656 659 self.name = parameters['name']
657 660 self.antenna = json.dumps(parameters['antenna'])
658 661 #self.abs_conf = parameters['abs_conf']
659 662 self.tx = json.dumps(parameters['tx'])
660 663 self.rx = json.dumps(parameters['rx'])
661 664 #self.s_time = parameters['s_time']
662 665 #self.e_time = parameters['e_time']
663 666 self.ues = json.dumps(parameters['ues'])
664 667 self.only_rx = json.dumps(parameters['only_rx'])
665 668 self.save()
666 669
667 670
668 671 def clone(self, **kwargs):
669 672
670 673 self.pk = None
671 674 self.id = None
672 675 for attr, value in kwargs.items():
673 676 setattr(self, attr, value)
674 677
675 678 self.save()
676 679
677 680 return self
678 681
679 682
680 683 def module_6bits(self, module):
681 684 """
682 685 This function reads antenna pattern and choose 6bits (upbits-downbits) for one abs module
683 686 """
684 687 module += 1
685 688 if module > 64:
686 689 beam_bits = ""
687 690 return beam_bits
688 691
689 692 data = ast.literal_eval(self.antenna)
690 693 up_data = data['antenna_up']
691 694 down_data = data['antenna_down']
692 695
693 696 pos = ip2position(module)
694 697 up_value = up_data[pos[0]][pos[1]]
695 698 down_value = down_data[pos[0]][pos[1]]
696 699
697 700 up_bits = up_conv_bits(up_value)
698 701 down_bits = down_conv_bits(down_value)
699 702 beam_bits = up_bits+down_bits
700 703
701 704 return beam_bits
702 705
703 706
704 707 @property
705 708 def get_upvalues(self):
706 709 """
707 710 This function reads antenna pattern and show the up-value of one abs module
708 711 """
709 712
710 713 data = ast.literal_eval(self.antenna)
711 714 up_data = data['antenna_up']
712 715
713 716 up_values = []
714 717 for data in up_data:
715 718 for i in range(0,8):
716 719 up_values.append(data[i])
717 720
718 721 return up_values
719 722
720 723 @property
721 724 def antenna_upvalues(self):
722 725 """
723 726 This function reads antenna pattern and show the up - values of one abs beam
724 727 in a particular order
725 728 """
726 729 data = ast.literal_eval(self.antenna)
727 730 up_data = data['antenna_up']
728 731
729 732 return up_data
730 733
731 734 @property
732 735 def antenna_downvalues(self):
733 736 """
734 737 This function reads antenna pattern and show the down - values of one abs beam
735 738 in a particular order
736 739 """
737 740 data = ast.literal_eval(self.antenna)
738 741 down_data = data['antenna_down']
739 742
740 743 return down_data
741 744
742 745 @property
743 746 def get_downvalues(self):
744 747 """
745 748 This function reads antenna pattern and show the down-value of one abs module
746 749 """
747 750
748 751 data = ast.literal_eval(self.antenna)
749 752 down_data = data['antenna_down']
750 753
751 754 down_values = []
752 755 for data in down_data:
753 756 for i in range(0,8):
754 757 down_values.append(data[i])
755 758
756 759 return down_values
757 760
758 761 @property
759 762 def get_up_ues(self):
760 763 """
761 764 This function shows the up-ues-value of one beam
762 765 """
763 766 data = ast.literal_eval(self.ues)
764 767 up_ues = data['up']
765 768
766 769 return up_ues
767 770
768 771 @property
769 772 def get_down_ues(self):
770 773 """
771 774 This function shows the down-ues-value of one beam
772 775 """
773 776 data = ast.literal_eval(self.ues)
774 777 down_ues = data['down']
775 778
776 779 return down_ues
777 780
778 781 @property
779 782 def get_up_onlyrx(self):
780 783 """
781 784 This function shows the up-onlyrx-value of one beam
782 785 """
783 786 data = json.loads(self.only_rx)
784 787 up_onlyrx = data['up']
785 788
786 789 return up_onlyrx
787 790
788 791 @property
789 792 def get_down_onlyrx(self):
790 793 """
791 794 This function shows the down-onlyrx-value of one beam
792 795 """
793 796 data = json.loads(self.only_rx)
794 797 down_onlyrx = data['down']
795 798
796 799 return down_onlyrx
797 800
798 801 @property
799 802 def get_tx(self):
800 803 """
801 804 This function shows the tx-values of one beam
802 805 """
803 806 data = json.loads(self.tx)
804 807
805 808 return data
806 809
807 810 @property
808 811 def get_uptx(self):
809 812 """
810 813 This function shows the up-tx-values of one beam
811 814 """
812 815 data = json.loads(self.tx)
813 816 up_data = data['up']
814 817
815 818 up_values = []
816 819 for data in up_data:
817 820 for i in range(0,8):
818 821 up_values.append(data[i])
819 822
820 823 return up_values
821 824
822 825 @property
823 826 def get_downtx(self):
824 827 """
825 828 This function shows the down-tx-values of one beam
826 829 """
827 830 data = json.loads(self.tx)
828 831 down_data = data['down']
829 832
830 833 down_values = []
831 834 for data in down_data:
832 835 for i in range(0,8):
833 836 down_values.append(data[i])
834 837
835 838 return down_values
836 839
837 840
838 841
839 842 @property
840 843 def get_rx(self):
841 844 """
842 845 This function shows the rx-values of one beam
843 846 """
844 847 data = json.loads(self.rx)
845 848
846 849 return data
847 850
848 851 @property
849 852 def get_uprx(self):
850 853 """
851 854 This function shows the up-rx-values of one beam
852 855 """
853 856 data = json.loads(self.rx)
854 857 up_data = data['up']
855 858
856 859 up_values = []
857 860 for data in up_data:
858 861 for i in range(0,8):
859 862 up_values.append(data[i])
860 863
861 864 return up_values
862 865
863 866 @property
864 867 def get_downrx(self):
865 868 """
866 869 This function shows the down-rx-values of one beam
867 870 """
868 871 data = json.loads(self.rx)
869 872 down_data = data['down']
870 873
871 874 down_values = []
872 875 for data in down_data:
873 876 for i in range(0,8):
874 877 down_values.append(data[i])
875 878
876 879 return down_values
@@ -1,342 +1,336
1 1 {% extends "dev_conf.html" %} {% load static %} {% load bootstrap3 %} {% load main_tags %}
2 2 {% block extra-head %}
3 3 <style>
4 4 .abs {
5 5 width: auto;
6 6 display: inline-block;
7 7 text-align: center;
8 8 }
9 9
10 10 .abs td {
11 11 padding: 4px;
12 12 }
13 13
14 14 .module td {
15 15 padding: 4px 15px 4px 15px;
16 16 font-weight: bold;
17 17 border: 1px solid
18 18 }
19 19
20 20 .legend {
21 21 margin-left: 15px;
22 22 display: inline-block;
23 23 border: 2px solid;
24 24 vertical-align: top;
25 25 }
26 26
27 27 .legend th {
28 28 border-bottom: 1px dashed;
29 29 font-weight: bold;
30 30 vertical-align: center;
31 31 text-align: center;
32 32 }
33 33
34 34 .legend td {
35 35 padding: 2px;
36 36 text-align: center;
37 font-weight: bold;
37 38 }
38 39
39 40 </style>
40 41 {% endblock %}
41 42 {% block extra-menu-actions %}
42 43 <li>
43 44 <a href="{{ dev_conf.get_absolute_url_plot }}" target="_blank">
44 45 <span class="glyphicon glyphicon-picture" aria-hidden="true"></span> View Patterns </a>
45 46 </li>
46 47 {% endblock %}
47 48 {% block extra-content %}
48 49 {% if beams %}
49 50 <h4>Beams:</h4>
50 51 <div class="container">
51 52 <ul class="nav nav-pills">
52 53 {% for beam in beams %}
53 54 <li {%if beam.pk == active_beam %} class="active" {% endif %}>
54 55 <a data-toggle="pill" href="#menu{{forloop.counter}}">{{forloop.counter}}</a>
55 56 </li>
56 57 {% endfor %}
57 58 </ul>
58 59
59 60 <div class="tab-content">
60 61 {% for beam in beams %}
61 62 <div id="menu{{forloop.counter}}" class="tab-pane fade {%if beam.pk == active_beam %}active in{% endif %}">
62 63 <h3>{%if beam.pk == active_beam %}Active Beam: {%endif%}{{beam.name}}</h3>
63 64 <table id="abs_pattern{{forloop.counter}}" class="abs">
64 65 <tr>
65 66 <td>
66 67 <b>North Quarter</b>
67 68 <table class="module">
68 69 <tr>
69 70 <td title='{{module_messages.1}}'><span {%if beam.pk == active_beam %} {{color_status.1}} {%endif%}>{{beam.get_upvalues.0}}</span></td>
70 71 <td title='{{module_messages.2}}'><span {%if beam.pk == active_beam %} {{color_status.2}} {%endif%}>{{beam.get_upvalues.1}}</span></td>
71 72 <td title='{{module_messages.3}}'><span {%if beam.pk == active_beam %} {{color_status.3}} {%endif%}>{{beam.get_upvalues.2}}</span></td>
72 73 <td title='{{module_messages.4}}'><span {%if beam.pk == active_beam %} {{color_status.4}} {%endif%}>{{beam.get_upvalues.3}}</span></td>
73 74 </tr>
74 75 <tr>
75 76 <td title='{{module_messages.1}}'><span {%if beam.pk == active_beam %} {{color_status.1}} {%endif%}>{{beam.get_downvalues.0}}</span></td>
76 77 <td title='{{module_messages.2}}'><span {%if beam.pk == active_beam %} {{color_status.2}} {%endif%}>{{beam.get_downvalues.1}}</span></td>
77 78 <td title='{{module_messages.3}}'> <span {%if beam.pk == active_beam %} {{color_status.3}} {%endif%}>{{beam.get_downvalues.2}}</span></td>
78 79 <td title='{{module_messages.4}}'> <span {%if beam.pk == active_beam %} {{color_status.4}} {%endif%}>{{beam.get_downvalues.3}}</span></td>
79 80 </tr>
80 81 <tr>
81 82 <td title='{{module_messages.9}}'> <span {%if beam.pk == active_beam %} {{color_status.9}} {%endif%}>{{beam.get_upvalues.8}}</span></td>
82 83 <td title='{{module_messages.10}}'><span {%if beam.pk == active_beam %} {{color_status.10}} {%endif%}>{{beam.get_upvalues.9}}</span></td>
83 84 <td title='{{module_messages.11}}'><span {%if beam.pk == active_beam %} {{color_status.11}} {%endif%}>{{beam.get_upvalues.10}}</span></td>
84 85 <td title='{{module_messages.12}}'><span {%if beam.pk == active_beam %} {{color_status.12}} {%endif%}>{{beam.get_upvalues.11}}</span></td>
85 86 </tr>
86 87 <tr>
87 88 <td title='{{module_messages.9}}'> <span {%if beam.pk == active_beam %} {{color_status.9}} {%endif%}>{{beam.get_downvalues.8}}</span></td>
88 89 <td title='{{module_messages.10}}'><span {%if beam.pk == active_beam %} {{color_status.10}} {%endif%}>{{beam.get_downvalues.9}}</span></td>
89 90 <td title='{{module_messages.11}}'><span {%if beam.pk == active_beam %} {{color_status.11}} {%endif%}>{{beam.get_downvalues.10}}</span></td>
90 91 <td title='{{module_messages.12}}'><span {%if beam.pk == active_beam %} {{color_status.12}} {%endif%}>{{beam.get_downvalues.11}}</span></td>
91 92 </tr>
92 93 <tr>
93 94 <td title='{{module_messages.17}}'><span {%if beam.pk == active_beam %} {{color_status.17}} {%endif%}>{{beam.get_upvalues.16}}</span></td>
94 95 <td title='{{module_messages.18}}'><span {%if beam.pk == active_beam %} {{color_status.18}} {%endif%}>{{beam.get_upvalues.17}}</span></td>
95 96 <td title='{{module_messages.19}}'><span {%if beam.pk == active_beam %} {{color_status.19}} {%endif%}>{{beam.get_upvalues.18}}</span></td>
96 97 <td title='{{module_messages.20}}'><span {%if beam.pk == active_beam %} {{color_status.20}} {%endif%}>{{beam.get_upvalues.19}}</span></td>
97 98 </tr>
98 99 <tr>
99 100 <td title='{{module_messages.17}}'><span {%if beam.pk == active_beam %} {{color_status.17}} {%endif%}>{{beam.get_downvalues.16}}</span></td>
100 101 <td title='{{module_messages.18}}'><span {%if beam.pk == active_beam %} {{color_status.18}} {%endif%}>{{beam.get_downvalues.17}}</span></td>
101 102 <td title='{{module_messages.19}}'><span {%if beam.pk == active_beam %} {{color_status.19}} {%endif%}>{{beam.get_downvalues.18}}</span></td>
102 103 <td title='{{module_messages.20}}'><span {%if beam.pk == active_beam %} {{color_status.20}} {%endif%}>{{beam.get_downvalues.19}}</span></td>
103 104 </tr>
104 105 <tr>
105 106 <td title='{{module_messages.25}}'><span {%if beam.pk == active_beam %} {{color_status.25}} {%endif%}>{{beam.get_upvalues.24}}</span></td>
106 107 <td title='{{module_messages.26}}'><span {%if beam.pk == active_beam %} {{color_status.26}} {%endif%}>{{beam.get_upvalues.25}}</span></td>
107 108 <td title='{{module_messages.27}}'><span {%if beam.pk == active_beam %} {{color_status.27}} {%endif%}>{{beam.get_upvalues.26}}</span></td>
108 109 <td title='{{module_messages.28}}'><span {%if beam.pk == active_beam %} {{color_status.28}} {%endif%}>{{beam.get_upvalues.27}}</span></td>
109 110 </tr>
110 111 <tr>
111 112 <td title='{{module_messages.25}}'><span {%if beam.pk == active_beam %} {{color_status.25}} {%endif%}>{{beam.get_downvalues.24}}</span></td>
112 113 <td title='{{module_messages.26}}'><span {%if beam.pk == active_beam %} {{color_status.26}} {%endif%}>{{beam.get_downvalues.25}}</span></td>
113 114 <td title='{{module_messages.27}}'><span {%if beam.pk == active_beam %} {{color_status.27}} {%endif%}>{{beam.get_downvalues.26}}</span></td>
114 115 <td title='{{module_messages.28}}'><span {%if beam.pk == active_beam %} {{color_status.28}} {%endif%}>{{beam.get_downvalues.27}}</span></td>
115 116 </tr>
116 117 </table>
117 118 </td>
118 119 <td>
119 120 <b>East Quarter</b>
120 121 <table class="module">
121 122 <tr>
122 123 <td title='{{module_messages.5}}'> <span {%if beam.pk == active_beam %} {{color_status.5}} {%endif%}>{{beam.get_upvalues.4}}</span></td>
123 124 <td title='{{module_messages.6}}'> <span {%if beam.pk == active_beam %} {{color_status.6}} {%endif%}>{{beam.get_upvalues.5}}</span></td>
124 125 <td title='{{module_messages.7}}'> <span {%if beam.pk == active_beam %} {{color_status.7}} {%endif%}>{{beam.get_upvalues.6}}</span></td>
125 126 <td title='{{module_messages.8}}'> <span {%if beam.pk == active_beam %} {{color_status.8}} {%endif%}>{{beam.get_upvalues.7}}</span></td>
126 127 </tr>
127 128 <tr>
128 129 <td title='{{module_messages.5}}'> <span {%if beam.pk == active_beam %} {{color_status.5}} {%endif%}>{{beam.get_downvalues.4}}</span></td>
129 130 <td title='{{module_messages.6}}'> <span {%if beam.pk == active_beam %} {{color_status.6}} {%endif%}>{{beam.get_downvalues.5}}</span></td>
130 131 <td title='{{module_messages.7}}'> <span {%if beam.pk == active_beam %} {{color_status.7}} {%endif%}>{{beam.get_downvalues.6}}</span></td>
131 132 <td title='{{module_messages.8}}'> <span {%if beam.pk == active_beam %} {{color_status.8}} {%endif%}>{{beam.get_downvalues.7}}</span></td>
132 133 </tr>
133 134 <tr>
134 135 <td title='{{module_messages.13}}'><span {%if beam.pk == active_beam %} {{color_status.13}} {%endif%}>{{beam.get_upvalues.12}}</span></td>
135 136 <td title='{{module_messages.14}}'><span {%if beam.pk == active_beam %} {{color_status.14}} {%endif%}>{{beam.get_upvalues.13}}</span></td>
136 137 <td title='{{module_messages.15}}'><span {%if beam.pk == active_beam %} {{color_status.15}} {%endif%}>{{beam.get_upvalues.14}}</span></td>
137 138 <td title='{{module_messages.16}}'><span {%if beam.pk == active_beam %} {{color_status.16}} {%endif%}>{{beam.get_upvalues.15}}</span></td>
138 139 </tr>
139 140 <tr>
140 141 <td title='{{module_messages.13}}'><span {%if beam.pk == active_beam %} {{color_status.13}} {%endif%}>{{beam.get_downvalues.12}}</span></td>
141 142 <td title='{{module_messages.14}}'><span {%if beam.pk == active_beam %} {{color_status.14}} {%endif%}>{{beam.get_downvalues.13}}</span></td>
142 143 <td title='{{module_messages.15}}'><span {%if beam.pk == active_beam %} {{color_status.15}} {%endif%}>{{beam.get_downvalues.14}}</span></td>
143 144 <td title='{{module_messages.16}}'><span {%if beam.pk == active_beam %} {{color_status.16}} {%endif%}>{{beam.get_downvalues.15}}</span></td>
144 145 </tr>
145 146 <tr>
146 147 <td title='{{module_messages.21}}'><span {%if beam.pk == active_beam %} {{color_status.21}} {%endif%}>{{beam.get_upvalues.20}}</span></td>
147 148 <td title='{{module_messages.22}}'><span {%if beam.pk == active_beam %} {{color_status.22}} {%endif%}>{{beam.get_upvalues.21}}</span></td>
148 149 <td title='{{module_messages.23}}'><span {%if beam.pk == active_beam %} {{color_status.23}} {%endif%}>{{beam.get_upvalues.22}}</span></td>
149 150 <td title='{{module_messages.24}}'><span {%if beam.pk == active_beam %} {{color_status.24}} {%endif%}>{{beam.get_upvalues.23}}</span></td>
150 151 </tr>
151 152 <tr>
152 153 <td title='{{module_messages.21}}'><span {%if beam.pk == active_beam %} {{color_status.21}} {%endif%}>{{beam.get_downvalues.20}}</span></td>
153 154 <td title='{{module_messages.22}}'><span {%if beam.pk == active_beam %} {{color_status.22}} {%endif%}>{{beam.get_downvalues.21}}</span></td>
154 155 <td title='{{module_messages.23}}'><span {%if beam.pk == active_beam %} {{color_status.23}} {%endif%}>{{beam.get_downvalues.22}}</span></td>
155 156 <td title='{{module_messages.24}}'><span {%if beam.pk == active_beam %} {{color_status.24}} {%endif%}>{{beam.get_downvalues.23}}</span></td>
156 157 </tr>
157 158 <tr>
158 159 <td title='{{module_messages.29}}'><span {%if beam.pk == active_beam %} {{color_status.29}} {%endif%}>{{beam.get_upvalues.28}}</span></td>
159 160 <td title='{{module_messages.30}}'><span {%if beam.pk == active_beam %} {{color_status.30}} {%endif%}>{{beam.get_upvalues.29}}</span></td>
160 161 <td title='{{module_messages.31}}'><span {%if beam.pk == active_beam %} {{color_status.31}} {%endif%}>{{beam.get_upvalues.30}}</span></td>
161 162 <td title='{{module_messages.32}}'><span {%if beam.pk == active_beam %} {{color_status.32}} {%endif%}>{{beam.get_upvalues.31}}</span></td>
162 163 </tr>
163 164 <tr>
164 165 <td title='{{module_messages.29}}'><span {%if beam.pk == active_beam %} {{color_status.29}} {%endif%}>{{beam.get_downvalues.28}}</span></td>
165 166 <td title='{{module_messages.30}}'><span {%if beam.pk == active_beam %} {{color_status.30}} {%endif%}>{{beam.get_downvalues.29}}</span></td>
166 167 <td title='{{module_messages.31}}'><span {%if beam.pk == active_beam %} {{color_status.31}} {%endif%}>{{beam.get_downvalues.30}}</span></td>
167 168 <td title='{{module_messages.32}}'><span {%if beam.pk == active_beam %} {{color_status.32}} {%endif%}>{{beam.get_downvalues.31}}</span></td>
168 169 </tr>
169 170 </table>
170 171 </td>
171 172 </tr>
172 173 <tr>
173 174 <td>
174 175 <b>West Quarter</b>
175 176 <table class="module">
176 177 <tr>
177 178 <td title='{{module_messages.33}}'><span {%if beam.pk == active_beam %} {{color_status.33}} {%endif%}>{{beam.get_upvalues.32}}</span></td>
178 179 <td title='{{module_messages.34}}'><span {%if beam.pk == active_beam %} {{color_status.34}} {%endif%}>{{beam.get_upvalues.33}}</span></td>
179 180 <td title='{{module_messages.35}}'><span {%if beam.pk == active_beam %} {{color_status.35}} {%endif%}>{{beam.get_upvalues.34}}</span></td>
180 181 <td title='{{module_messages.36}}'><span {%if beam.pk == active_beam %} {{color_status.36}} {%endif%}>{{beam.get_upvalues.35}}</span></td>
181 182 </tr>
182 183 <tr>
183 184 <td title='{{module_messages.33}}'><span {%if beam.pk == active_beam %} {{color_status.33}} {%endif%}>{{beam.get_downvalues.32}}</span></td>
184 185 <td title='{{module_messages.34}}'><span {%if beam.pk == active_beam %} {{color_status.34}} {%endif%}>{{beam.get_downvalues.33}}</span></td>
185 186 <td title='{{module_messages.35}}'><span {%if beam.pk == active_beam %} {{color_status.35}} {%endif%}>{{beam.get_downvalues.34}}</span></td>
186 187 <td title='{{module_messages.36}}'><span {%if beam.pk == active_beam %} {{color_status.36}} {%endif%}>{{beam.get_downvalues.35}}</span></td>
187 188 </tr>
188 189 <tr>
189 190 <td title='{{module_messages.41}}'><span {%if beam.pk == active_beam %} {{color_status.41}} {%endif%}>{{beam.get_upvalues.40}}</span></td>
190 191 <td title='{{module_messages.42}}'><span {%if beam.pk == active_beam %} {{color_status.42}} {%endif%}>{{beam.get_upvalues.41}}</span></td>
191 192 <td title='{{module_messages.43}}'><span {%if beam.pk == active_beam %} {{color_status.43}} {%endif%}>{{beam.get_upvalues.42}}</span></td>
192 193 <td title='{{module_messages.44}}'><span {%if beam.pk == active_beam %} {{color_status.44}} {%endif%}>{{beam.get_upvalues.43}}</span></td>
193 194 </tr>
194 195 <tr>
195 196 <td title='{{module_messages.41}}'><span {%if beam.pk == active_beam %} {{color_status.41}} {%endif%}>{{beam.get_downvalues.40}}</span></td>
196 197 <td title='{{module_messages.42}}'><span {%if beam.pk == active_beam %} {{color_status.42}} {%endif%}>{{beam.get_downvalues.41}}</span></td>
197 198 <td title='{{module_messages.43}}'><span {%if beam.pk == active_beam %} {{color_status.43}} {%endif%}>{{beam.get_downvalues.42}}</span></td>
198 199 <td title='{{module_messages.44}}'><span {%if beam.pk == active_beam %} {{color_status.44}} {%endif%}>{{beam.get_downvalues.43}}</span></td>
199 200 </tr>
200 201 <tr>
201 202 <td title='{{module_messages.49}}'><span {%if beam.pk == active_beam %} {{color_status.49}} {%endif%}>{{beam.get_upvalues.48}}</span></td>
202 203 <td title='{{module_messages.51}}'><span {%if beam.pk == active_beam %} {{color_status.50}} {%endif%}>{{beam.get_upvalues.49}}</span></td>
203 204 <td title='{{module_messages.52}}'><span {%if beam.pk == active_beam %} {{color_status.51}} {%endif%}>{{beam.get_upvalues.50}}</span></td>
204 205 <td title='{{module_messages.53}}'><span {%if beam.pk == active_beam %} {{color_status.52}} {%endif%}>{{beam.get_upvalues.51}}</span></td>
205 206 </tr>
206 207 <tr>
207 208 <td title='{{module_messages.49}}'><span {%if beam.pk == active_beam %} {{color_status.49}} {%endif%}>{{beam.get_downvalues.48}}</span></td>
208 209 <td title='{{module_messages.50}}'><span {%if beam.pk == active_beam %} {{color_status.50}} {%endif%}>{{beam.get_downvalues.49}}</span></td>
209 210 <td title='{{module_messages.51}}'><span {%if beam.pk == active_beam %} {{color_status.51}} {%endif%}>{{beam.get_downvalues.50}}</span></td>
210 211 <td title='{{module_messages.52}}'><span {%if beam.pk == active_beam %} {{color_status.52}} {%endif%}>{{beam.get_downvalues.51}}</span></td>
211 212 </tr>
212 213 <tr>
213 214 <td title='{{module_messages.57}}'><span {%if beam.pk == active_beam %} {{color_status.57}} {%endif%}>{{beam.get_upvalues.56}}</span></td>
214 215 <td title='{{module_messages.58}}'><span {%if beam.pk == active_beam %} {{color_status.58}} {%endif%}>{{beam.get_upvalues.57}}</span></td>
215 216 <td title='{{module_messages.59}}'><span {%if beam.pk == active_beam %} {{color_status.59}} {%endif%}>{{beam.get_upvalues.58}}</span></td>
216 217 <td title='{{module_messages.60}}'><span {%if beam.pk == active_beam %} {{color_status.60}} {%endif%}>{{beam.get_upvalues.59}}</span></td>
217 218 </tr>
218 219 <tr>
219 220 <td title='{{module_messages.57}}'><span {%if beam.pk == active_beam %} {{color_status.57}} {%endif%}>{{beam.get_downvalues.56}}</span></td>
220 221 <td title='{{module_messages.58}}'><span {%if beam.pk == active_beam %} {{color_status.58}} {%endif%}>{{beam.get_downvalues.57}}</span></td>
221 222 <td title='{{module_messages.59}}'><span {%if beam.pk == active_beam %} {{color_status.59}} {%endif%}>{{beam.get_downvalues.58}}</span></td>
222 223 <td title='{{module_messages.60}}'><span {%if beam.pk == active_beam %} {{color_status.60}} {%endif%}>{{beam.get_downvalues.59}}</span></td>
223 224 </tr>
224 225 </table>
225 226 </td>
226 227 <td>
227 228 <b>South Quarter</b>
228 229 <table class="module">
229 230 <tr>
230 231 <td title='{{module_messages.37}}'><span {%if beam.pk == active_beam %} {{color_status.37}} {%endif%}>{{beam.get_upvalues.36}}</span></td>
231 232 <td title='{{module_messages.38}}'><span {%if beam.pk == active_beam %} {{color_status.38}} {%endif%}>{{beam.get_upvalues.37}}</span></td>
232 233 <td title='{{module_messages.39}}'><span {%if beam.pk == active_beam %} {{color_status.39}} {%endif%}>{{beam.get_upvalues.38}}</span></td>
233 234 <td title='{{module_messages.40}}'><span {%if beam.pk == active_beam %} {{color_status.40}} {%endif%}>{{beam.get_upvalues.39}}</span></td>
234 235 </tr>
235 236 <tr>
236 237 <td title='{{module_messages.37}}'><span {%if beam.pk == active_beam %} {{color_status.37}} {%endif%}>{{beam.get_downvalues.36}}</span></td>
237 238 <td title='{{module_messages.38}}'><span {%if beam.pk == active_beam %} {{color_status.38}} {%endif%}>{{beam.get_downvalues.37}}</span></td>
238 239 <td title='{{module_messages.39}}'><span {%if beam.pk == active_beam %} {{color_status.39}} {%endif%}>{{beam.get_downvalues.38}}</span></td>
239 240 <td title='{{module_messages.40}}'><span {%if beam.pk == active_beam %} {{color_status.40}} {%endif%}>{{beam.get_downvalues.39}}</span></td>
240 241 </tr>
241 242 <tr>
242 243 <td title='{{module_messages.45}}'><span {%if beam.pk == active_beam %} {{color_status.45}} {%endif%}>{{beam.get_upvalues.44}}</span></td>
243 244 <td title='{{module_messages.46}}'><span {%if beam.pk == active_beam %} {{color_status.46}} {%endif%}>{{beam.get_upvalues.45}}</span></td>
244 245 <td title='{{module_messages.47}}'><span {%if beam.pk == active_beam %} {{color_status.47}} {%endif%}>{{beam.get_upvalues.46}}</span></td>
245 246 <td title='{{module_messages.48}}'><span {%if beam.pk == active_beam %} {{color_status.48}} {%endif%}>{{beam.get_upvalues.47}}</span></td>
246 247 </tr>
247 248 <tr>
248 249 <td title='{{module_messages.45}}'><span {%if beam.pk == active_beam %} {{color_status.45}} {%endif%}>{{beam.get_downvalues.44}}</span></td>
249 250 <td title='{{module_messages.46}}'><span {%if beam.pk == active_beam %} {{color_status.46}} {%endif%}>{{beam.get_downvalues.45}}</span></td>
250 251 <td title='{{module_messages.47}}'><span {%if beam.pk == active_beam %} {{color_status.47}} {%endif%}>{{beam.get_downvalues.46}}</span></td>
251 252 <td title='{{module_messages.48}}'><span {%if beam.pk == active_beam %} {{color_status.48}} {%endif%}>{{beam.get_downvalues.47}}</span></td>
252 253 </tr>
253 254 <tr>
254 255 <td title='{{module_messages.53}}'><span {%if beam.pk == active_beam %} {{color_status.53}} {%endif%}>{{beam.get_upvalues.52}}</span></td>
255 256 <td title='{{module_messages.54}}'><span {%if beam.pk == active_beam %} {{color_status.54}} {%endif%}>{{beam.get_upvalues.53}}</span></td>
256 257 <td title='{{module_messages.55}}'><span {%if beam.pk == active_beam %} {{color_status.55}} {%endif%}>{{beam.get_upvalues.54}}</span></td>
257 258 <td title='{{module_messages.56}}'><span {%if beam.pk == active_beam %} {{color_status.56}} {%endif%}>{{beam.get_upvalues.55}}</span></td>
258 259 </tr>
259 260 <tr>
260 261 <td title='{{module_messages.53}}'><span {%if beam.pk == active_beam %} {{color_status.53}} {%endif%}>{{beam.get_downvalues.52}}</span></td>
261 262 <td title='{{module_messages.54}}'><span {%if beam.pk == active_beam %} {{color_status.54}} {%endif%}>{{beam.get_downvalues.53}}</span></td>
262 263 <td title='{{module_messages.55}}'><span {%if beam.pk == active_beam %} {{color_status.55}} {%endif%}>{{beam.get_downvalues.54}}</span></td>
263 264 <td title='{{module_messages.56}}'><span {%if beam.pk == active_beam %} {{color_status.56}} {%endif%}>{{beam.get_downvalues.55}}</span></td>
264 265 </tr>
265 266 <tr>
266 267 <td title='{{module_messages.61}}'><span {%if beam.pk == active_beam %} {{color_status.61}} {%endif%}>{{beam.get_upvalues.60}}</span></td>
267 268 <td title='{{module_messages.62}}'><span {%if beam.pk == active_beam %} {{color_status.62}} {%endif%}>{{beam.get_upvalues.61}}</span></td>
268 269 <td title='{{module_messages.63}}'><span {%if beam.pk == active_beam %} {{color_status.63}} {%endif%}>{{beam.get_upvalues.62}}</span></td>
269 270 <td title='{{module_messages.64}}'><span {%if beam.pk == active_beam %} {{color_status.64}} {%endif%}>{{beam.get_upvalues.63}}</span></td>
270 271 </tr>
271 272 <tr>
272 273 <td title='{{module_messages.61}}'><span {%if beam.pk == active_beam %} {{color_status.61}} {%endif%}>{{beam.get_downvalues.60}}</span></td>
273 274 <td title='{{module_messages.62}}'><span {%if beam.pk == active_beam %} {{color_status.62}} {%endif%}>{{beam.get_downvalues.61}}</span></td>
274 275 <td title='{{module_messages.63}}'><span {%if beam.pk == active_beam %} {{color_status.63}} {%endif%}>{{beam.get_downvalues.62}}</span></td>
275 276 <td title='{{module_messages.64}}'><span {%if beam.pk == active_beam %} {{color_status.64}} {%endif%}>{{beam.get_downvalues.63}}</span></td>
276 277 </tr>
277 278 </table>
278 279 </td>
279 280 </tr>
280 281 </table>
281 282
282 283 {% if beam.id == active_beam %}
283 284 <table class="legend">
284 285 <tr>
285 <th colspan="2">Legend</th>
286 <th>Legend</th>
286 287 </tr>
287 288 <tr>
288 <td class="text-danger">
289 <i>RED</i>
290 </td>
291 <td>Disconnected</td>
289 <td class="text-warning">Connected</td>
292 290 </tr>
293 291 <tr>
294 <td class="text-warning">
295 <i>ORANGE</i>
296 </td>
297 <td>Connected</td>
292 <td class="text-success">Running</td>
298 293 </tr>
299 294 <tr>
300 <td class="text-success">
301 <i>GREEN</i>
302 </td>
303 <td>Running
304 </td>
295 <td class="text-info">Mismath</td>
296 </tr>
297 <tr>
298 <td class="text-danger">Disconnected</td>
305 299 </tr>
306 300 </table>
307 301 {% else %}
308 302 <div style="vertical-align: top; display:inline-block;">
309 303 <button id="send_beam{{forloop.counter}}" type="button" class="btn btn-default">
310 304 <span class="glyphicon glyphicon-export" aria-hidden="true"></span>
311 305 Change Beam</button>
312 306 </div>
313 307 {% endif %}
314 308 </div>
315 309 {% endfor %}
316 310 </div>
317 311 </div>
318 312
319 313
320 314 {% else %}
321 315 <p style="color:#b4bcc2; margin-left: 5%;">
322 316 <i>No Beams...</i>
323 317 </p>
324 318 {% endif %} {% endblock extra-content %} {% block extra-js%}
325 319 <script>
326 320 $(document).ready(function () {
327 321
328 322 {% for beam in beams %}
329 323
330 324 {% if dev_conf.operation_mode == 1 %}
331 325 $("#send_beam{{forloop.counter}}").prop('disabled', true)
332 326 {% else %}
333 327 $("#send_beam{{forloop.counter}}").click(function () {
334 328 document.location = "{% url 'url_send_beam' dev_conf.id beam.id %}";
335 329 });
336 330 {% endif %}
337 331
338 332 {% endfor %}
339 333
340 334
341 335 });
342 336 </script> {% endblock %} No newline at end of file
@@ -1,415 +1,433
1 1 from django.shortcuts import render_to_response
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.core.urlresolvers import reverse
8 8 from django.views.decorators.csrf import csrf_exempt
9 from django.utils.safestring import mark_safe
9 10
10 11 from datetime import datetime
11 12 from time import sleep
12 13 import os
13 14 import io
14 15
15 16 from apps.main.models import Device, Configuration, Experiment
16 17 from apps.main.views import sidebar
17 18
18 19 from .models import ABSConfiguration, ABSBeam
19 20 from .forms import ABSConfigurationForm, ABSBeamEditForm, ABSBeamAddForm, ABSImportForm
20 21
21 22 from .utils.overJroShow import overJroShow
22 23 from .utils.OverJRO import OverJRO
23 24 # Create your views here.
24 25 import json, ast
25 26
26 27
27 28 def get_values_from_form(form_data):
28 29
29 30 sublistup = []
30 31 sublistdown = []
31 32 subtxlistup = []
32 33 subtxlistdown = []
33 34 subrxlistup = []
34 35 subrxlistdown = []
35 36
36 37 up_values_list = []
37 38 down_values_list = []
38 39 up_txvalues_list = []
39 40 down_txvalues_list = []
40 41 up_rxvalues_list = []
41 42 down_rxvalues_list = []
42 43
43 44 values_list = {}
44 45 cont = 1
45 46
46 47 for i in range(1,65):
47 48 x = float(form_data['abs_up'+str(i)])
48 49 y = float(form_data['abs_down'+str(i)])
49 50 sublistup.append(x)
50 51 sublistdown.append(y)
51 52
52 53 if str(i) in form_data.getlist('uptx_checks'):
53 54 subtxlistup.append(1)
54 55 else:
55 56 subtxlistup.append(0)
56 57 if str(i) in form_data.getlist('downtx_checks'):
57 58 subtxlistdown.append(1)
58 59 else:
59 60 subtxlistdown.append(0)
60 61
61 62 if str(i) in form_data.getlist('uprx_checks'):
62 63 subrxlistup.append(1)
63 64 else:
64 65 subrxlistup.append(0)
65 66 if str(i) in form_data.getlist('downrx_checks'):
66 67 subrxlistdown.append(1)
67 68 else:
68 69 subrxlistdown.append(0)
69 70
70 71 cont = cont+1
71 72
72 73 if cont == 9:
73 74 up_values_list.append(sublistup)
74 75 down_values_list.append(sublistdown)
75 76 sublistup = []
76 77 sublistdown = []
77 78
78 79 up_txvalues_list.append(subtxlistup)
79 80 down_txvalues_list.append(subtxlistdown)
80 81 subtxlistup = []
81 82 subtxlistdown = []
82 83 up_rxvalues_list.append(subrxlistup)
83 84 down_rxvalues_list.append(subrxlistdown)
84 85 subrxlistup = []
85 86 subrxlistdown = []
86 87 cont = 1
87 88
88 89
89 90 list_uesup = []
90 91 list_uesdown = []
91 92 for i in range(1,5):
92 93 if form_data['ues_up'+str(i)] == '':
93 94 list_uesup.append(0.0)
94 95 else:
95 96 list_uesup.append(float(form_data['ues_up'+str(i)]))
96 97
97 98 if form_data['ues_down'+str(i)] == '':
98 99 list_uesdown.append(0.0)
99 100 else:
100 101 list_uesdown.append(float(form_data['ues_down'+str(i)]))
101 102
102 103 onlyrx_list = form_data.getlist('onlyrx')
103 104 only_rx = {}
104 105 if '1' in onlyrx_list:
105 106 only_rx['up'] = True
106 107 else:
107 108 only_rx['up'] = False
108 109 if '2' in onlyrx_list:
109 110 only_rx['down'] = True
110 111 else:
111 112 only_rx['down'] = False
112 113
113 114 antenna = {'antenna_up': up_values_list, 'antenna_down': down_values_list}
114 115 tx = {'up': up_txvalues_list, 'down': down_txvalues_list}
115 116 rx = {'up': up_rxvalues_list, 'down': down_rxvalues_list}
116 117 ues = {'up': list_uesup, 'down': list_uesdown}
117 118 name = str(form_data['beam_name'])
118 119
119 120 beam_data = {'name': name, 'antenna': antenna, 'tx': tx, 'rx': rx, 'ues': ues, 'only_rx': only_rx}
120 121
121 122 return beam_data
122 123
123 124
124 125 def abs_conf(request, id_conf):
125 126
126 127 conf = get_object_or_404(ABSConfiguration, pk=id_conf)
127 128 beams = ABSBeam.objects.filter(abs_conf=conf)
128 129 #------------Colors for Active Beam:-------------
129 130 all_status = {}
130 131 module_messages = json.loads(conf.module_messages)
131 132
132 133 color_status = {}
133 134 for i, status in enumerate(conf.module_status):
134 135 if status == '3': #Running background-color: #00cc00;
135 136 all_status['{}'.format(i+1)] = 2
136 137 color_status['{}'.format(i+1)] = 'class=text-success'#'bgcolor=#00cc00'
138 elif status == '2':
139 all_status['{}'.format(i+1)] = 1
140 color_status['{}'.format(i+1)] = 'class=text-info'
137 141 elif status == '1': #Connected background-color: #ee902c;
138 142 all_status['{}'.format(i+1)] = 1
139 143 color_status['{}'.format(i+1)] = 'class=text-warning'#'bgcolor=#ee902c'
140 144 else: #Disconnected background-color: #ff0000;
141 145 all_status['{}'.format(i+1)] = 0
142 146 color_status['{}'.format(i+1)] = 'class=text-danger'#'bgcolor=#FF0000'
143 147 #------------------------------------------------
144 148
145 149 kwargs = {}
146 150 kwargs['connected_modules'] = str(conf.connected_modules())+'/64'
147 151 kwargs['dev_conf'] = conf
148 152
149 153 if conf.operation_mode == 0:
150 154 kwargs['dev_conf_keys'] = ['label', 'operation_mode']
151 155 else:
152 156 kwargs['dev_conf_keys'] = ['label', 'operation_mode', 'operation_value']
153 157
154 158 kwargs['title'] = 'ABS Configuration'
155 159 kwargs['suptitle'] = 'Details'
156 160 kwargs['button'] = 'Edit Configuration'
157 161
158 162 if conf.active_beam != 0:
159 163 kwargs['active_beam'] = int(conf.active_beam)
160 164
161 165 kwargs['beams'] = beams
162 166 kwargs['modules_status'] = all_status
163 167 kwargs['color_status'] = color_status
164 168 kwargs['module_messages'] = module_messages
165 169 ###### SIDEBAR ######
166 170 kwargs.update(sidebar(conf=conf))
167 171
168 172 return render(request, 'abs_conf.html', kwargs)
169 173
170 174
171 175 def abs_conf_edit(request, id_conf):
172 176
173 177 conf = get_object_or_404(ABSConfiguration, pk=id_conf)
174 178
175 179 beams = ABSBeam.objects.filter(abs_conf=conf)
176 180
177 181 if request.method=='GET':
178 182 form = ABSConfigurationForm(instance=conf)
179 183
180 184 if request.method=='POST':
181 185 form = ABSConfigurationForm(request.POST, instance=conf)
182 186
183 187 if form.is_valid():
184 188 conf = form.save(commit=False)
185 189 conf.save()
186 190 return redirect('url_abs_conf', id_conf=conf.id)
187 191
188 192 ###### SIDEBAR ######
189 193 kwargs = {}
190 194
191 195 kwargs['dev_conf'] = conf
192 196 #kwargs['id_dev'] = conf.id
193 197 kwargs['id_conf'] = conf.id
194 198 kwargs['form'] = form
195 199 kwargs['abs_beams'] = beams
196 200 kwargs['title'] = 'Device Configuration'
197 201 kwargs['suptitle'] = 'Edit'
198 202 kwargs['button'] = 'Save'
199 203
200 204 kwargs['edit'] = True
201 205
202 206 return render(request, 'abs_conf_edit.html', kwargs)
203 207
204 208 @csrf_exempt
205 209 def abs_conf_alert(request):
206 210
207 211 if request.method == 'POST':
208 212 print request.POST
209 213 return HttpResponse(json.dumps({'result':1}), content_type='application/json')
210 214 else:
211 215 return redirect('index')
212 216
213 217
214 218 def import_file(request, id_conf):
215 219
216 220 conf = get_object_or_404(ABSConfiguration, pk=id_conf)
217 221 if request.method=='POST':
218 222 form = ABSImportForm(request.POST, request.FILES)
219 223 if form.is_valid():
220 224 try:
221 225 parms = conf.import_from_file(request.FILES['file_name'])
222 226
223 227 if parms:
224 228 conf.update_from_file(parms)
225 229 messages.success(request, 'Configuration "%s" loaded succesfully' % request.FILES['file_name'])
226 230 return redirect(conf.get_absolute_url_edit())
227 231
228 232 except Exception as e:
229 233 messages.error(request, 'Error parsing file: "%s" - %s' % (request.FILES['file_name'], e))
230 234
231 235 else:
232 236 messages.warning(request, 'Your current configuration will be replaced')
233 237 form = ABSImportForm()
234 238
235 239 kwargs = {}
236 240 kwargs['form'] = form
237 241 kwargs['title'] = 'ABS Configuration'
238 242 kwargs['suptitle'] = 'Import file'
239 243 kwargs['button'] = 'Upload'
240 244 kwargs['previous'] = conf.get_absolute_url()
241 245
242 246 return render(request, 'abs_import.html', kwargs)
243 247
244 248
245 249 def send_beam(request, id_conf, id_beam):
246 250
247 251 conf = get_object_or_404(ABSConfiguration, pk=id_conf)
252
253 abs = request.user.profile.abs_active
254 if abs<>conf:
255 url = '#' if abs is None else abs.get_absolute_url()
256 label = 'None' if abs is None else abs.label
257 messages.warning(
258 request,
259 mark_safe('The current configuration has not been written in the modules, the active configuration is <a href="{}">{}</a>'.format(
260 url,
261 label
262 ))
263 )
264 return redirect(conf.get_absolute_url())
265
248 266 beam = get_object_or_404(ABSBeam, pk=id_beam)
249 267 beams_list = ABSBeam.objects.filter(abs_conf=conf)
250 268 conf.active_beam = id_beam
251 269
252 270 i = 0
253 271 for b in beams_list:
254 272 if b.id == int(id_beam):
255 273 break
256 274 else:
257 275 i += 1
258 276 beam_pos = i + 1 #Estandarizar
259 277 print '%s Position: %s' % (beam.name, str(beam_pos))
260 278 conf.send_beam(beam_pos)
261 279
262 280 return redirect('url_abs_conf', conf.id)
263 281
264 282
265 283 def add_beam(request, id_conf):
266 284
267 285 conf = get_object_or_404(ABSConfiguration, pk=id_conf)
268 286 confs = Configuration.objects.all()
269 287
270 288 if request.method=='GET':
271 289 form = ABSBeamAddForm()
272 290
273 291 if request.method=='POST':
274 292 form = ABSBeamAddForm(request.POST)
275 293
276 294 beam_data = get_values_from_form(request.POST)
277 295
278 296 new_beam = ABSBeam(
279 297 name = beam_data['name'],
280 298 antenna = json.dumps(beam_data['antenna']),
281 299 abs_conf = conf,
282 300 tx = json.dumps(beam_data['tx']),
283 301 rx = json.dumps(beam_data['rx']),
284 302 ues = json.dumps(beam_data['ues']),
285 303 only_rx = json.dumps(beam_data['only_rx'])
286 304 )
287 305 new_beam.save()
288 306 messages.success(request, 'Beam: "%s" has been added.' % new_beam.name)
289 307
290 308 return redirect('url_edit_abs_conf', conf.id)
291 309
292 310 ###### SIDEBAR ######
293 311 kwargs = {}
294 312
295 313 #kwargs['dev_conf'] = conf.device
296 314 #kwargs['id_dev'] = conf.device
297 315 kwargs['id_conf'] = conf.id
298 316 kwargs['form'] = form
299 317 kwargs['title'] = 'ABS Beams'
300 318 kwargs['suptitle'] = 'Add Beam'
301 319 kwargs['button'] = 'Add'
302 320 kwargs['no_sidebar'] = True
303 321
304 322 #kwargs['previous'] = conf.get_absolute_url_edit()
305 323 kwargs['edit'] = True
306 324
307 325 return render(request, 'abs_add_beam.html', kwargs)
308 326
309 327
310 328 def edit_beam(request, id_conf, id_beam):
311 329
312 330 conf = get_object_or_404(ABSConfiguration, pk=id_conf)
313 331 beam = get_object_or_404(ABSBeam, pk=id_beam)
314 332
315 333 if request.method=='GET':
316 334 form = ABSBeamEditForm(initial={'beam': beam})
317 335
318 336 if request.method=='POST':
319 337 form = ABSBeamEditForm(request.POST)
320 338
321 339 beam_data = get_values_from_form(request.POST)
322 340
323 341 beam.dict_to_parms(beam_data)
324 342 beam.save()
325 343
326 344 messages.success(request, 'Beam: "%s" has been updated.' % beam.name)
327 345
328 346 return redirect('url_edit_abs_conf', conf.id)
329 347
330 348 ###### SIDEBAR ######
331 349 kwargs = {}
332 350
333 351 kwargs['id_conf'] = conf.id
334 352 kwargs['form'] = form
335 353 kwargs['title'] = 'ABS Beams'
336 354 kwargs['suptitle'] = 'Edit Beam'
337 355 kwargs['button'] = 'Save'
338 356 kwargs['no_sidebar'] = True
339 357
340 358 #kwargs['previous'] = conf.get_absolute_url_edit()
341 359 kwargs['edit'] = True
342 360
343 361 return render(request, 'abs_edit_beam.html', kwargs)
344 362
345 363
346 364
347 365 def remove_beam(request, id_conf, id_beam):
348 366
349 367 conf = get_object_or_404(ABSConfiguration, pk=id_conf)
350 368 beam = get_object_or_404(ABSBeam, pk=id_beam)
351 369
352 370 if request.method=='POST':
353 371 if beam:
354 372 try:
355 373 beam.delete()
356 374 messages.success(request, 'Beam: "%s" has been deleted.' % beam)
357 375 except:
358 376 messages.error(request, 'Unable to delete beam: "%s".' % beam)
359 377
360 378 return redirect('url_edit_abs_conf', conf.id)
361 379
362 380 ###### SIDEBAR ######
363 381 kwargs = {}
364 382
365 383 kwargs['object'] = beam
366 384 kwargs['delete'] = True
367 385 kwargs['title'] = 'Delete'
368 386 kwargs['suptitle'] = 'Beam'
369 387 kwargs['previous'] = conf.get_absolute_url_edit()
370 388 return render(request, 'confirm.html', kwargs)
371 389
372 390
373 391
374 392 def plot_patterns(request, id_conf, id_beam=None):
375 393
376 394 kwargs = {}
377 395 conf = get_object_or_404(ABSConfiguration, pk=id_conf)
378 396 beams = ABSBeam.objects.filter(abs_conf=conf)
379 397
380 398 if id_beam:
381 399 beam = get_object_or_404(ABSBeam, pk=id_beam)
382 400 kwargs['beam'] = beam
383 401
384 402 ###### SIDEBAR ######
385 403
386 404 kwargs['dev_conf'] = conf.device
387 405 kwargs['id_dev'] = conf.device
388 406 kwargs['id_conf'] = conf.id
389 407 kwargs['abs_beams'] = beams
390 408 kwargs['title'] = 'ABS Patterns'
391 409 kwargs['suptitle'] = conf.name
392 410 kwargs['no_sidebar'] = True
393 411
394 412 return render(request, 'abs_patterns.html', kwargs)
395 413
396 414
397 415 def plot_pattern(request, id_conf, id_beam, antenna):
398 416
399 417 if antenna=='down':
400 418 sleep(3)
401 419
402 420 conf = get_object_or_404(ABSConfiguration, pk=id_conf)
403 421 beam = get_object_or_404(ABSBeam, pk=id_beam)
404 422 just_rx = 1 if json.loads(beam.only_rx)[antenna] else 0
405 423 phases = json.loads(beam.antenna)['antenna_{}'.format(antenna)]
406 424 gain_tx = json.loads(beam.tx)[antenna]
407 425 gain_rx = json.loads(beam.rx)[antenna]
408 426 ues = json.loads(beam.ues)[antenna]
409 427 newOverJro = overJroShow(beam.name)
410 428 fig = newOverJro.plotPattern2(datetime.today(), phases, gain_tx, gain_rx, ues, just_rx)
411 429 buf = io.BytesIO()
412 430 fig.savefig(buf, format='png')
413 431 response = HttpResponse(buf.getvalue(), content_type='image/png')
414 432 return response
415 433
@@ -1,122 +1,130
1 1 [
2 2 {
3 3 "fields": {
4 4 "name": "JRO",
5 5 "description": ""
6 6 },
7 7 "model": "main.location",
8 8 "pk": 1
9 9 },
10 10 {
11 11 "fields": {
12 12 "name": "JASMET",
13 13 "description": ""
14 14 },
15 15 "model": "main.location",
16 16 "pk": 2
17 17 },
18 18 {
19 19 "fields": {
20 20 "name": "SOUSY",
21 21 "description": ""
22 22 },
23 23 "model": "main.location",
24 24 "pk": 3
25 25 },
26 26 {
27 27 "fields": {
28 28 "name": "JULIA",
29 29 "description": ""
30 30 },
31 31 "model": "main.location",
32 32 "pk": 4
33 33 },
34 34 {
35 35 "fields": {
36 36 "name": "CLAIRE",
37 37 "description": ""
38 38 },
39 39 "model": "main.location",
40 40 "pk": 5
41 41 },
42 42 {
43 43 "fields": {
44 44 "name": "IDI",
45 45 "description": ""
46 46 },
47 47 "model": "main.location",
48 48 "pk": 6
49 49 },
50 50 {
51 51 "fields": {
52 52 "name": "rc",
53 53 "description": ""
54 54 },
55 55 "model": "main.devicetype",
56 56 "pk": 1
57 57 },
58 58 {
59 59 "fields": {
60 60 "name": "dds",
61 61 "description": ""
62 62 },
63 63 "model": "main.devicetype",
64 64 "pk": 2
65 65 },
66 66 {
67 67 "fields": {
68 68 "name": "cgs",
69 69 "description": ""
70 70 },
71 71 "model": "main.devicetype",
72 72 "pk": 3
73 73 },
74 74 {
75 75 "fields": {
76 76 "name": "jars",
77 77 "description": ""
78 78 },
79 79 "model": "main.devicetype",
80 80 "pk": 4
81 81 },
82 82 {
83 83 "fields": {
84 84 "name": "abs",
85 85 "description": ""
86 86 },
87 87 "model": "main.devicetype",
88 88 "pk": 5
89 89 },
90 90 {
91 91 "fields": {
92 92 "name": "Operator"
93 93 },
94 94 "model": "auth.group",
95 95 "pk": 1
96 96 },
97 97 {
98 98 "fields": {
99 99 "name": "Developer"
100 100 },
101 101 "model": "auth.group",
102 102 "pk": 2
103 103 },
104 104 {
105 105 "fields": {
106 106 "password": "pbkdf2_sha256$24000$6RRL7xETgdgN$ORRPhrITZKzTTZHCm8T+Er6ght415kYKeU7QP3rry5M=",
107 107 "last_login": null,
108 108 "is_superuser": true,
109 109 "username": "admin",
110 110 "first_name": "Administrador",
111 111 "last_name": "IDI",
112 112 "email": "admin@admin.com",
113 113 "is_staff": true,
114 114 "is_active": true,
115 115 "date_joined": "2017-01-12T16:10:24.383",
116 116 "groups": [],
117 117 "user_permissions": []
118 118 },
119 119 "model": "auth.user",
120 120 "pk": 1
121 },
122 {
123 "fields": {
124 "user": 1,
125 "theme": "spacelab"
126 },
127 "model": "main.profile",
128 "pk": 1
121 129 }
122 130 ] No newline at end of file
@@ -1,809 +1,811
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.core.urlresolvers 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 }
37 37
38 38 RADAR_STATES = (
39 39 (0, 'No connected'),
40 40 (1, 'Connected'),
41 41 (2, 'Configured'),
42 42 (3, 'Running'),
43 43 (4, 'Scheduled'),
44 44 )
45 45
46 46 EXPERIMENT_TYPE = (
47 47 (0, 'RAW_DATA'),
48 48 (1, 'PDATA'),
49 49 )
50 50
51 51 DECODE_TYPE = (
52 52 (0, 'None'),
53 53 (1, 'TimeDomain'),
54 54 (2, 'FreqDomain'),
55 55 (3, 'InvFreqDomain'),
56 56 )
57 57
58 58 DEV_STATES = (
59 59 (0, 'No connected'),
60 60 (1, 'Connected'),
61 61 (2, 'Configured'),
62 62 (3, 'Running'),
63 63 (4, 'Unknown'),
64 64 )
65 65
66 66 DEV_TYPES = (
67 67 ('', 'Select a device type'),
68 68 ('rc', 'Radar Controller'),
69 69 ('dds', 'Direct Digital Synthesizer'),
70 70 ('jars', 'Jicamarca Radar Acquisition System'),
71 71 ('usrp', 'Universal Software Radio Peripheral'),
72 72 ('cgs', 'Clock Generator System'),
73 73 ('abs', 'Automatic Beam Switching'),
74 74 )
75 75
76 76 EXP_STATES = (
77 77 (0,'Error'), #RED
78 78 (1,'Configured'), #BLUE
79 79 (2,'Running'), #GREEN
80 80 (3,'Scheduled'), #YELLOW
81 81 (4,'Not Configured'), #WHITE
82 82 )
83 83
84 84 CONF_TYPES = (
85 85 (0, 'Active'),
86 86 (1, 'Historical'),
87 87 )
88 88
89 89 class Profile(models.Model):
90 90 user = models.OneToOneField(User, on_delete=models.CASCADE)
91 theme = models.CharField(max_length=30, default='yeti')
91 theme = models.CharField(max_length=30, default='spacelab')
92 abs_active = models.ForeignKey('Configuration', null=True, blank=True, verbose_name='Current ABS')
93
92 94
93 95 @receiver(post_save, sender=User)
94 96 def create_user_profile(sender, instance, created, **kwargs):
95 97 if created:
96 98 Profile.objects.create(user=instance)
97 99
98 100 @receiver(post_save, sender=User)
99 101 def save_user_profile(sender, instance, **kwargs):
100 102 instance.profile.save()
101 103
102 104
103 105 class Location(models.Model):
104 106
105 107 name = models.CharField(max_length = 30)
106 108 description = models.TextField(blank=True, null=True)
107 109
108 110 class Meta:
109 111 db_table = 'db_location'
110 112
111 113 def __str__(self):
112 114 return u'%s' % self.name
113 115
114 116 def get_absolute_url(self):
115 117 return reverse('url_location', args=[str(self.id)])
116 118
117 119
118 120 class DeviceType(models.Model):
119 121
120 122 name = models.CharField(max_length = 10, choices = DEV_TYPES, default = 'rc')
121 123 sequence = models.PositiveSmallIntegerField(default=1000)
122 124 description = models.TextField(blank=True, null=True)
123 125
124 126 class Meta:
125 127 db_table = 'db_device_types'
126 128
127 129 def __str__(self):
128 130 return u'%s' % self.get_name_display()
129 131
130 132 class Device(models.Model):
131 133
132 134 device_type = models.ForeignKey(DeviceType, on_delete=models.CASCADE)
133 135 location = models.ForeignKey(Location, on_delete=models.CASCADE)
134 136 ip_address = models.GenericIPAddressField(protocol='IPv4', default='0.0.0.0')
135 137 port_address = models.PositiveSmallIntegerField(default=2000)
136 138 description = models.TextField(blank=True, null=True)
137 139 status = models.PositiveSmallIntegerField(default=0, choices=DEV_STATES)
138 140
139 141 class Meta:
140 142 db_table = 'db_devices'
141 143
142 144 def __str__(self):
143 145 ret = u'{} [{}]'.format(self.device_type.name.upper(), self.location.name)
144 146
145 147 return ret
146 148
147 149 @property
148 150 def name(self):
149 151 return str(self)
150 152
151 153 def get_status(self):
152 154 return self.status
153 155
154 156 @property
155 157 def status_color(self):
156 158 color = 'muted'
157 159 if self.status == 0:
158 160 color = "danger"
159 161 elif self.status == 1:
160 162 color = "warning"
161 163 elif self.status == 2:
162 164 color = "info"
163 165 elif self.status == 3:
164 166 color = "success"
165 167
166 168 return color
167 169
168 170 def url(self, path=None):
169 171
170 172 if path:
171 173 return 'http://{}:{}/{}/'.format(self.ip_address, self.port_address, path)
172 174 else:
173 175 return 'http://{}:{}/'.format(self.ip_address, self.port_address)
174 176
175 177 def get_absolute_url(self):
176 178 return reverse('url_device', args=[str(self.id)])
177 179
178 180 def get_absolute_url_edit(self):
179 181 return reverse('url_edit_device', args=[str(self.id)])
180 182
181 183 def get_absolute_url_delete(self):
182 184 return reverse('url_delete_device', args=[str(self.id)])
183 185
184 186 def change_ip(self, ip_address, mask, gateway, dns, **kwargs):
185 187
186 188 if self.device_type.name=='dds':
187 189 try:
188 190 answer = dds_api.change_ip(ip = self.ip_address,
189 191 port = self.port_address,
190 192 new_ip = ip_address,
191 193 mask = mask,
192 194 gateway = gateway)
193 195 if answer[0]=='1':
194 196 self.message = '25|DDS - {}'.format(answer)
195 197 self.ip_address = ip_address
196 198 self.save()
197 199 else:
198 200 self.message = '30|DDS - {}'.format(answer)
199 201 return False
200 202 except Exception as e:
201 203 self.message = '40|{}'.format(str(e))
202 204 return False
203 205
204 206 elif self.device_type.name=='rc':
205 207 headers = {'content-type': "application/json",
206 208 'cache-control': "no-cache"}
207 209
208 210 ip = [int(x) for x in ip_address.split('.')]
209 211 dns = [int(x) for x in dns.split('.')]
210 212 gateway = [int(x) for x in gateway.split('.')]
211 213 subnet = [int(x) for x in mask.split('.')]
212 214
213 215 payload = {
214 216 "ip": ip,
215 217 "dns": dns,
216 218 "gateway": gateway,
217 219 "subnet": subnet
218 220 }
219 221
220 222 req = requests.post(self.url('changeip'), data=json.dumps(payload), headers=headers)
221 223 try:
222 224 answer = req.json()
223 225 if answer['changeip']=='ok':
224 226 self.message = '25|IP succesfully changed'
225 227 self.ip_address = ip_address
226 228 self.save()
227 229 else:
228 230 self.message = '30|An error ocuur when changing IP'
229 231 except Exception as e:
230 232 self.message = '40|{}'.format(str(e))
231 233 else:
232 234 self.message = 'Not implemented'
233 235 return False
234 236
235 237 return True
236 238
237 239
238 240 class Campaign(models.Model):
239 241
240 242 template = models.BooleanField(default=False)
241 243 name = models.CharField(max_length=60, unique=True)
242 244 start_date = models.DateTimeField(blank=True, null=True)
243 245 end_date = models.DateTimeField(blank=True, null=True)
244 246 tags = models.CharField(max_length=40, blank=True, null=True)
245 247 description = models.TextField(blank=True, null=True)
246 248 experiments = models.ManyToManyField('Experiment', blank=True)
247 249 author = models.ForeignKey(User, null=True, blank=True)
248 250
249 251 class Meta:
250 252 db_table = 'db_campaigns'
251 253 ordering = ('name',)
252 254
253 255 def __str__(self):
254 256 if self.template:
255 257 return u'{} (template)'.format(self.name)
256 258 else:
257 259 return u'{}'.format(self.name)
258 260
259 261 def jsonify(self):
260 262
261 263 data = {}
262 264
263 265 ignored = ('template')
264 266
265 267 for field in self._meta.fields:
266 268 if field.name in ignored:
267 269 continue
268 270 data[field.name] = field.value_from_object(self)
269 271
270 272 data['start_date'] = data['start_date'].strftime('%Y-%m-%d')
271 273 data['end_date'] = data['end_date'].strftime('%Y-%m-%d')
272 274
273 275 return data
274 276
275 277 def parms_to_dict(self):
276 278
277 279 params = Params({})
278 280 params.add(self.jsonify(), 'campaigns')
279 281
280 282 for exp in Experiment.objects.filter(campaign = self):
281 283 params.add(exp.jsonify(), 'experiments')
282 284 configurations = Configuration.objects.filter(experiment=exp, type=0)
283 285
284 286 for conf in configurations:
285 287 params.add(conf.jsonify(), 'configurations')
286 288 if conf.device.device_type.name=='rc':
287 289 for line in conf.get_lines():
288 290 params.add(line.jsonify(), 'lines')
289 291
290 292 return params.data
291 293
292 294 def dict_to_parms(self, parms, CONF_MODELS):
293 295
294 296 experiments = Experiment.objects.filter(campaign = self)
295 297
296 298 if experiments:
297 299 for experiment in experiments:
298 300 experiment.delete()
299 301
300 302 for id_exp in parms['experiments']['allIds']:
301 303 exp_parms = parms['experiments']['byId'][id_exp]
302 304 dum = (datetime.now() - datetime(1970, 1, 1)).total_seconds()
303 305 exp = Experiment(name='{}'.format(dum))
304 306 exp.save()
305 307 exp.dict_to_parms(parms, CONF_MODELS, id_exp=id_exp)
306 308 self.experiments.add(exp)
307 309
308 310 camp_parms = parms['campaigns']['byId'][parms['campaigns']['allIds'][0]]
309 311
310 312 self.name = '{}-{}'.format(camp_parms['name'], datetime.now().strftime('%y%m%d'))
311 313 self.start_date = camp_parms['start_date']
312 314 self.end_date = camp_parms['end_date']
313 315 self.tags = camp_parms['tags']
314 316 self.save()
315 317
316 318 return self
317 319
318 320 def get_experiments_by_radar(self, radar=None):
319 321
320 322 ret = []
321 323 if radar:
322 324 locations = Location.objects.filter(pk=radar)
323 325 else:
324 326 locations = set([e.location for e in self.experiments.all()])
325 327
326 328 for loc in locations:
327 329 dum = {}
328 330 dum['name'] = loc.name
329 331 dum['id'] = loc.pk
330 332 dum['experiments'] = [e for e in self.experiments.all() if e.location==loc]
331 333 ret.append(dum)
332 334
333 335 return ret
334 336
335 337 def get_absolute_url(self):
336 338 return reverse('url_campaign', args=[str(self.id)])
337 339
338 340 def get_absolute_url_edit(self):
339 341 return reverse('url_edit_campaign', args=[str(self.id)])
340 342
341 343 def get_absolute_url_delete(self):
342 344 return reverse('url_delete_campaign', args=[str(self.id)])
343 345
344 346 def get_absolute_url_export(self):
345 347 return reverse('url_export_campaign', args=[str(self.id)])
346 348
347 349 def get_absolute_url_import(self):
348 350 return reverse('url_import_campaign', args=[str(self.id)])
349 351
350 352
351 353 class RunningExperiment(models.Model):
352 354 radar = models.OneToOneField('Location', on_delete=models.CASCADE)
353 355 running_experiment = models.ManyToManyField('Experiment', blank = True)
354 356 status = models.PositiveSmallIntegerField(default=0, choices=RADAR_STATES)
355 357
356 358
357 359 class Experiment(models.Model):
358 360
359 361 template = models.BooleanField(default=False)
360 362 name = models.CharField(max_length=40, default='', unique=True)
361 363 location = models.ForeignKey('Location', null=True, blank=True, on_delete=models.CASCADE)
362 364 freq = models.FloatField(verbose_name='Operating Freq. (MHz)', validators=[MinValueValidator(1), MaxValueValidator(10000)], default=49.9200)
363 365 start_time = models.TimeField(default='00:00:00')
364 366 end_time = models.TimeField(default='23:59:59')
365 367 task = models.CharField(max_length=36, default='', blank=True, null=True)
366 368 status = models.PositiveSmallIntegerField(default=4, choices=EXP_STATES)
367 369 author = models.ForeignKey(User, null=True, blank=True)
368 370 hash = models.CharField(default='', max_length=64, null=True, blank=True)
369 371
370 372 class Meta:
371 373 db_table = 'db_experiments'
372 374 ordering = ('template', 'name')
373 375
374 376 def __str__(self):
375 377 if self.template:
376 378 return u'%s (template)' % (self.name)
377 379 else:
378 380 return u'%s' % (self.name)
379 381
380 382 def jsonify(self):
381 383
382 384 data = {}
383 385
384 386 ignored = ('template')
385 387
386 388 for field in self._meta.fields:
387 389 if field.name in ignored:
388 390 continue
389 391 data[field.name] = field.value_from_object(self)
390 392
391 393 data['start_time'] = data['start_time'].strftime('%H:%M:%S')
392 394 data['end_time'] = data['end_time'].strftime('%H:%M:%S')
393 395 data['location'] = self.location.name
394 396 data['configurations'] = ['{}'.format(conf.pk) for
395 397 conf in Configuration.objects.filter(experiment=self, type=0)]
396 398
397 399 return data
398 400
399 401 @property
400 402 def radar_system(self):
401 403 return self.location
402 404
403 405 def clone(self, **kwargs):
404 406
405 407 confs = Configuration.objects.filter(experiment=self, type=0)
406 408 self.pk = None
407 409 self.name = '{}_{:%y%m%d}'.format(self.name, datetime.now())
408 410 for attr, value in kwargs.items():
409 411 setattr(self, attr, value)
410 412
411 413 self.save()
412 414
413 415 for conf in confs:
414 416 conf.clone(experiment=self, template=False)
415 417
416 418 return self
417 419
418 420 def start(self):
419 421 '''
420 422 Configure and start experiments's devices
421 423 ABS-CGS-DDS-RC-JARS
422 424 '''
423 425
424 426 result = 2
425 427 confs = []
426 428 allconfs = Configuration.objects.filter(experiment=self, type = 0).order_by('-device__device_type__sequence')
427 429 rc_mix = [conf for conf in allconfs if conf.device.device_type.name=='rc' and conf.mix]
428 430 if rc_mix:
429 431 for conf in allconfs:
430 432 if conf.device.device_type.name == 'rc' and not conf.mix:
431 433 continue
432 434 confs.append(conf)
433 435 else:
434 436 confs = allconfs
435 437 #Only Configured Devices.
436 438 for conf in confs:
437 439 if conf.device.status in (0, 4):
438 440 result = 0
439 441 return result
440 442 for conf in confs:
441 443 conf.stop_device()
442 444 conf.write_device()
443 445 conf.start_device()
444 446 time.sleep(1)
445 447
446 448 return result
447 449
448 450
449 451 def stop(self):
450 452 '''
451 453 Stop experiments's devices
452 454 DDS-JARS-RC-CGS-ABS
453 455 '''
454 456
455 457 result = 1
456 458
457 459 confs = Configuration.objects.filter(experiment=self, type = 0).order_by('device__device_type__sequence')
458 460 confs=confs.exclude(device__device_type__name='cgs')
459 461 for conf in confs:
460 462 if conf.device.status in (0, 4):
461 463 result = 0
462 464 continue
463 465 conf.stop_device()
464 466
465 467 return result
466 468
467 469
468 470 def get_status(self):
469 471
470 472 if self.status == 3:
471 473 return
472 474
473 475 confs = Configuration.objects.filter(experiment=self, type=0)
474 476
475 477 for conf in confs:
476 478 conf.status_device()
477 479
478 480 total = confs.aggregate(models.Sum('device__status'))['device__status__sum']
479 481
480 482 if total==2*confs.count():
481 483 status = 1
482 484 elif total == 3*confs.count():
483 485 status = 2
484 486 else:
485 487 status = 0
486 488
487 489 self.status = status
488 490 self.save()
489 491
490 492 def status_color(self):
491 493 color = 'muted'
492 494 if self.status == 0:
493 495 color = "danger"
494 496 elif self.status == 1:
495 497 color = "info"
496 498 elif self.status == 2:
497 499 color = "success"
498 500 elif self.status == 3:
499 501 color = "warning"
500 502
501 503 return color
502 504
503 505 def parms_to_dict(self):
504 506
505 507 params = Params({})
506 508 params.add(self.jsonify(), 'experiments')
507 509
508 510 configurations = Configuration.objects.filter(experiment=self, type=0)
509 511
510 512 for conf in configurations:
511 513 params.add(conf.jsonify(), 'configurations')
512 514 if conf.device.device_type.name=='rc':
513 515 for line in conf.get_lines():
514 516 params.add(line.jsonify(), 'lines')
515 517
516 518 return params.data
517 519
518 520 def dict_to_parms(self, parms, CONF_MODELS, id_exp=None):
519 521
520 522 configurations = Configuration.objects.filter(experiment=self)
521 523
522 524 if id_exp is not None:
523 525 exp_parms = parms['experiments']['byId'][id_exp]
524 526 else:
525 527 exp_parms = parms['experiments']['byId'][parms['experiments']['allIds'][0]]
526 528
527 529 if configurations:
528 530 for configuration in configurations:
529 531 configuration.delete()
530 532
531 533 for id_conf in exp_parms['configurations']:
532 534 conf_parms = parms['configurations']['byId'][id_conf]
533 535 device = Device.objects.filter(device_type__name=conf_parms['device_type'])[0]
534 536 model = CONF_MODELS[conf_parms['device_type']]
535 537 conf = model(
536 538 experiment = self,
537 539 device = device,
538 540 )
539 541 conf.dict_to_parms(parms, id=id_conf)
540 542
541 543
542 544 location, created = Location.objects.get_or_create(name=exp_parms['location'])
543 545 self.name = '{}-{}'.format(exp_parms['name'], datetime.now().strftime('%y%m%d'))
544 546 self.location = location
545 547 self.start_time = exp_parms['start_time']
546 548 self.end_time = exp_parms['end_time']
547 549 self.save()
548 550
549 551 return self
550 552
551 553 def get_absolute_url(self):
552 554 return reverse('url_experiment', args=[str(self.id)])
553 555
554 556 def get_absolute_url_edit(self):
555 557 return reverse('url_edit_experiment', args=[str(self.id)])
556 558
557 559 def get_absolute_url_delete(self):
558 560 return reverse('url_delete_experiment', args=[str(self.id)])
559 561
560 562 def get_absolute_url_import(self):
561 563 return reverse('url_import_experiment', args=[str(self.id)])
562 564
563 565 def get_absolute_url_export(self):
564 566 return reverse('url_export_experiment', args=[str(self.id)])
565 567
566 568 def get_absolute_url_start(self):
567 569 return reverse('url_start_experiment', args=[str(self.id)])
568 570
569 571 def get_absolute_url_stop(self):
570 572 return reverse('url_stop_experiment', args=[str(self.id)])
571 573
572 574
573 575 class Configuration(PolymorphicModel):
574 576
575 577 template = models.BooleanField(default=False)
576 578 # name = models.CharField(verbose_name="Configuration Name", max_length=40, default='')
577 579 label = models.CharField(verbose_name="Label", max_length=40, default='', blank=True, null=True)
578 580 experiment = models.ForeignKey('Experiment', verbose_name='Experiment', null=True, blank=True, on_delete=models.CASCADE)
579 581 device = models.ForeignKey('Device', verbose_name='Device', null=True, on_delete=models.CASCADE)
580 582 type = models.PositiveSmallIntegerField(default=0, choices=CONF_TYPES)
581 583 created_date = models.DateTimeField(auto_now_add=True)
582 584 programmed_date = models.DateTimeField(auto_now=True)
583 585 parameters = models.TextField(default='{}')
584 586 author = models.ForeignKey(User, null=True, blank=True)
585 587 hash = models.CharField(default='', max_length=64, null=True, blank=True)
586 588 message = ""
587 589
588 590 class Meta:
589 591 db_table = 'db_configurations'
590 592 ordering = ('device__device_type__name',)
591 593
592 594 def __str__(self):
593 595
594 596 ret = u'{} '.format(self.device.device_type.name.upper())
595 597
596 598 if 'mix' in [f.name for f in self._meta.get_fields()]:
597 599 if self.mix:
598 600 ret = '{} MIX '.format(self.device.device_type.name.upper())
599 601
600 602 if 'label' in [f.name for f in self._meta.get_fields()]:
601 603 ret += '{}'.format(self.label)
602 604
603 605 if self.template:
604 606 ret += ' (template)'
605 607
606 608 return ret
607 609
608 610 @property
609 611 def name(self):
610 612
611 613 return str(self)
612 614
613 615 def jsonify(self):
614 616
615 617 data = {}
616 618
617 619 ignored = ('type', 'polymorphic_ctype', 'configuration_ptr',
618 620 'created_date', 'programmed_date', 'template', 'device',
619 621 'experiment')
620 622
621 623 for field in self._meta.fields:
622 624 if field.name in ignored:
623 625 continue
624 626 data[field.name] = field.value_from_object(self)
625 627
626 628 data['device_type'] = self.device.device_type.name
627 629
628 630 if self.device.device_type.name == 'rc':
629 631 data['lines'] = ['{}'.format(line.pk) for line in self.get_lines()]
630 632 data['delays'] = self.get_delays()
631 633 data['pulses'] = self.get_pulses()
632 634
633 635 elif self.device.device_type.name == 'jars':
634 636 data['decode_type'] = DECODE_TYPE[self.decode_data][1]
635 637
636 638 elif self.device.device_type.name == 'dds':
637 639 data['frequencyA_Mhz'] = float(data['frequencyA_Mhz'])
638 640 data['frequencyB_Mhz'] = float(data['frequencyB_Mhz'])
639 641 data['phaseA'] = dds_data.phase_to_binary(data['phaseA_degrees'])
640 642 data['phaseB'] = dds_data.phase_to_binary(data['phaseB_degrees'])
641 643
642 644 return data
643 645
644 646 def clone(self, **kwargs):
645 647
646 648 self.pk = None
647 649 self.id = None
648 650 for attr, value in kwargs.items():
649 651 setattr(self, attr, value)
650 652
651 653 self.save()
652 654
653 655 return self
654 656
655 657 def parms_to_dict(self):
656 658
657 659 params = Params({})
658 660 params.add(self.jsonify(), 'configurations')
659 661
660 662 if self.device.device_type.name=='rc':
661 663 for line in self.get_lines():
662 664 params.add(line.jsonify(), 'lines')
663 665
664 666 return params.data
665 667
666 668 def parms_to_text(self):
667 669
668 670 raise NotImplementedError("This method should be implemented in %s Configuration model" %str(self.device.device_type.name).upper())
669 671
670 672
671 673 def parms_to_binary(self):
672 674
673 675 raise NotImplementedError("This method should be implemented in %s Configuration model" %str(self.device.device_type.name).upper())
674 676
675 677
676 678 def dict_to_parms(self, parameters, id=None):
677 679
678 680 params = Params(parameters)
679 681
680 682 if id:
681 683 data = params.get_conf(id_conf=id)
682 684 else:
683 685 data = params.get_conf(dtype=self.device.device_type.name)
684 686
685 687 if data['device_type']=='rc':
686 688 self.clean_lines()
687 689 lines = data.pop('lines', None)
688 690 for line_id in lines:
689 691 pass
690 692
691 693 for key, value in data.items():
692 694 if key not in ('id', 'device_type'):
693 695 setattr(self, key, value)
694 696
695 697 self.save()
696 698
697 699
698 700 def export_to_file(self, format="json"):
699 701
700 702 content_type = ''
701 703
702 704 if format == 'racp':
703 705 content_type = 'text/plain'
704 706 filename = '%s_%s.%s' %(self.device.device_type.name, self.name, 'racp')
705 707 content = self.parms_to_text(file_format = 'racp')
706 708
707 709 if format == 'text':
708 710 content_type = 'text/plain'
709 711 filename = '%s_%s.%s' %(self.device.device_type.name, self.name, self.device.device_type.name)
710 712 content = self.parms_to_text()
711 713
712 714 if format == 'binary':
713 715 content_type = 'application/octet-stream'
714 716 filename = '%s_%s.bin' %(self.device.device_type.name, self.name)
715 717 content = self.parms_to_binary()
716 718
717 719 if not content_type:
718 720 content_type = 'application/json'
719 721 filename = '%s_%s.json' %(self.device.device_type.name, self.name)
720 722 content = json.dumps(self.parms_to_dict(), indent=2)
721 723
722 724 fields = {'content_type':content_type,
723 725 'filename':filename,
724 726 'content':content
725 727 }
726 728
727 729 return fields
728 730
729 731 def import_from_file(self, fp):
730 732
731 733 parms = {}
732 734
733 735 path, ext = os.path.splitext(fp.name)
734 736
735 737 if ext == '.json':
736 738 parms = json.load(fp)
737 739
738 740 if ext == '.dds':
739 741 lines = fp.readlines()
740 742 parms = dds_data.text_to_dict(lines)
741 743
742 744 if ext == '.racp':
743 745 if self.device.device_type.name == 'jars':
744 746 parms = RacpFile(fp).to_dict()
745 747 parms['filter_parms'] = json.loads(self.filter_parms)
746 748 return parms
747 749 parms = RCFile(fp).to_dict()
748 750
749 751 return parms
750 752
751 753 def status_device(self):
752 754
753 755 self.message = 'Function not implemented'
754 756 return False
755 757
756 758
757 759 def stop_device(self):
758 760
759 761 self.message = 'Function not implemented'
760 762 return False
761 763
762 764
763 765 def start_device(self):
764 766
765 767 self.message = 'Function not implemented'
766 768 return False
767 769
768 770
769 771 def write_device(self, parms):
770 772
771 773 self.message = 'Function not implemented'
772 774 return False
773 775
774 776
775 777 def read_device(self):
776 778
777 779 self.message = 'Function not implemented'
778 780 return False
779 781
780 782
781 783 def get_absolute_url(self):
782 784 return reverse('url_%s_conf' % self.device.device_type.name, args=[str(self.id)])
783 785
784 786 def get_absolute_url_edit(self):
785 787 return reverse('url_edit_%s_conf' % self.device.device_type.name, args=[str(self.id)])
786 788
787 789 def get_absolute_url_delete(self):
788 790 return reverse('url_delete_dev_conf', args=[str(self.id)])
789 791
790 792 def get_absolute_url_import(self):
791 793 return reverse('url_import_dev_conf', args=[str(self.id)])
792 794
793 795 def get_absolute_url_export(self):
794 796 return reverse('url_export_dev_conf', args=[str(self.id)])
795 797
796 798 def get_absolute_url_write(self):
797 799 return reverse('url_write_dev_conf', args=[str(self.id)])
798 800
799 801 def get_absolute_url_read(self):
800 802 return reverse('url_read_dev_conf', args=[str(self.id)])
801 803
802 804 def get_absolute_url_start(self):
803 805 return reverse('url_start_dev_conf', args=[str(self.id)])
804 806
805 807 def get_absolute_url_stop(self):
806 808 return reverse('url_stop_dev_conf', args=[str(self.id)])
807 809
808 810 def get_absolute_url_status(self):
809 811 return reverse('url_status_dev_conf', args=[str(self.id)])
@@ -1,1850 +1,1865
1 1 import ast
2 2 import json
3 3 import hashlib
4 4 from datetime import datetime, timedelta
5 5
6 6 from django.shortcuts import render, redirect, get_object_or_404, HttpResponse
7 7 from django.utils.safestring import mark_safe
8 8 from django.http import HttpResponseRedirect
9 9 from django.core.urlresolvers import reverse
10 10 from django.db.models import Q
11 11 from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
12 12 from django.contrib import messages
13 13 from django.http.request import QueryDict
14 14 from django.contrib.auth.decorators import login_required, user_passes_test
15 15
16 16 try:
17 17 from urllib.parse import urlencode
18 18 except ImportError:
19 19 from urllib import urlencode
20 20
21 21 from .forms import CampaignForm, ExperimentForm, DeviceForm, ConfigurationForm, LocationForm, UploadFileForm, DownloadFileForm, OperationForm, NewForm
22 22 from .forms import OperationSearchForm, FilterForm, ChangeIpForm
23 23
24 24 from .tasks import task_start
25 25
26 26 from apps.rc.forms import RCConfigurationForm, RCLineCode, RCMixConfigurationForm
27 27 from apps.dds.forms import DDSConfigurationForm
28 28 from apps.jars.forms import JARSConfigurationForm
29 29 from apps.cgs.forms import CGSConfigurationForm
30 30 from apps.abs.forms import ABSConfigurationForm
31 31 from apps.usrp.forms import USRPConfigurationForm
32 32 from .utils import Params
33 33
34 34 from .models import Campaign, Experiment, Device, Configuration, Location, RunningExperiment, DEV_STATES
35 35 from apps.cgs.models import CGSConfiguration
36 36 from apps.jars.models import JARSConfiguration, EXPERIMENT_TYPE
37 37 from apps.usrp.models import USRPConfiguration
38 38 from apps.abs.models import ABSConfiguration
39 39 from apps.rc.models import RCConfiguration, RCLine, RCLineType
40 40 from apps.dds.models import DDSConfiguration
41 41
42 42 from radarsys.celery import app
43 43
44 44
45 45 CONF_FORMS = {
46 46 'rc': RCConfigurationForm,
47 47 'dds': DDSConfigurationForm,
48 48 'jars': JARSConfigurationForm,
49 49 'cgs': CGSConfigurationForm,
50 50 'abs': ABSConfigurationForm,
51 51 'usrp': USRPConfigurationForm,
52 52 }
53 53
54 54 CONF_MODELS = {
55 55 'rc': RCConfiguration,
56 56 'dds': DDSConfiguration,
57 57 'jars': JARSConfiguration,
58 58 'cgs': CGSConfiguration,
59 59 'abs': ABSConfiguration,
60 60 'usrp': USRPConfiguration,
61 61 }
62 62
63 63 MIX_MODES = {
64 64 '0': 'P',
65 65 '1': 'S',
66 66 }
67 67
68 68 MIX_OPERATIONS = {
69 69 '0': 'OR',
70 70 '1': 'XOR',
71 71 '2': 'AND',
72 72 '3': 'NAND',
73 73 }
74 74
75 75
76 76 def is_developer(user):
77 77
78 78 groups = [str(g.name) for g in user.groups.all()]
79 79 return 'Developer' in groups or user.is_staff
80 80
81 81
82 82 def is_operator(user):
83 83
84 84 groups = [str(g.name) for g in user.groups.all()]
85 85 return 'Operator' in groups or user.is_staff
86 86
87 87
88 88 def has_been_modified(model):
89 89
90 90 prev_hash = model.hash
91 91 new_hash = hashlib.sha256(str(model.parms_to_dict)).hexdigest()
92 92 if prev_hash != new_hash:
93 93 model.hash = new_hash
94 94 model.save()
95 95 return True
96 96 return False
97 97
98 98
99 99 def index(request):
100 100 kwargs = {'no_sidebar': True}
101 101
102 102 return render(request, 'index.html', kwargs)
103 103
104 104
105 105 def locations(request):
106 106
107 107 page = request.GET.get('page')
108 108 order = ('name',)
109 109
110 110 kwargs = get_paginator(Location, page, order)
111 111
112 112 kwargs['keys'] = ['name', 'description']
113 113 kwargs['title'] = 'Radar System'
114 114 kwargs['suptitle'] = 'List'
115 115 kwargs['no_sidebar'] = True
116 116
117 117 return render(request, 'base_list.html', kwargs)
118 118
119 119
120 120 def location(request, id_loc):
121 121
122 122 location = get_object_or_404(Location, pk=id_loc)
123 123
124 124 kwargs = {}
125 125 kwargs['location'] = location
126 126 kwargs['location_keys'] = ['name', 'description']
127 127
128 128 kwargs['title'] = 'Location'
129 129 kwargs['suptitle'] = 'Details'
130 130
131 131 return render(request, 'location.html', kwargs)
132 132
133 133
134 134 @login_required
135 135 def location_new(request):
136 136
137 137 if request.method == 'GET':
138 138 form = LocationForm()
139 139
140 140 if request.method == 'POST':
141 141 form = LocationForm(request.POST)
142 142
143 143 if form.is_valid():
144 144 form.save()
145 145 return redirect('url_locations')
146 146
147 147 kwargs = {}
148 148 kwargs['form'] = form
149 149 kwargs['title'] = 'Radar System'
150 150 kwargs['suptitle'] = 'New'
151 151 kwargs['button'] = 'Create'
152 152
153 153 return render(request, 'base_edit.html', kwargs)
154 154
155 155
156 156 @login_required
157 157 def location_edit(request, id_loc):
158 158
159 159 location = get_object_or_404(Location, pk=id_loc)
160 160
161 161 if request.method == 'GET':
162 162 form = LocationForm(instance=location)
163 163
164 164 if request.method == 'POST':
165 165 form = LocationForm(request.POST, instance=location)
166 166
167 167 if form.is_valid():
168 168 form.save()
169 169 return redirect('url_locations')
170 170
171 171 kwargs = {}
172 172 kwargs['form'] = form
173 173 kwargs['title'] = 'Location'
174 174 kwargs['suptitle'] = 'Edit'
175 175 kwargs['button'] = 'Update'
176 176
177 177 return render(request, 'base_edit.html', kwargs)
178 178
179 179
180 180 @login_required
181 181 def location_delete(request, id_loc):
182 182
183 183 location = get_object_or_404(Location, pk=id_loc)
184 184
185 185 if request.method == 'POST':
186 186
187 187 if is_developer(request.user):
188 188 location.delete()
189 189 return redirect('url_locations')
190 190
191 191 messages.error(request, 'Not enough permission to delete this object')
192 192 return redirect(location.get_absolute_url())
193 193
194 194 kwargs = {
195 195 'title': 'Delete',
196 196 'suptitle': 'Location',
197 197 'object': location,
198 198 'delete': True
199 199 }
200 200
201 201 return render(request, 'confirm.html', kwargs)
202 202
203 203
204 204 def devices(request):
205 205
206 206 page = request.GET.get('page')
207 207 order = ('location', 'device_type')
208 208
209 209 filters = request.GET.copy()
210 210 kwargs = get_paginator(Device, page, order, filters)
211 211 form = FilterForm(initial=request.GET, extra_fields=['tags'])
212 212
213 213 kwargs['keys'] = ['device_type', 'location',
214 214 'ip_address', 'port_address', 'actions']
215 215 kwargs['title'] = 'Device'
216 216 kwargs['suptitle'] = 'List'
217 217 kwargs['no_sidebar'] = True
218 218 kwargs['form'] = form
219 219 kwargs['add_url'] = reverse('url_add_device')
220 220 filters.pop('page', None)
221 221 kwargs['q'] = urlencode(filters)
222 222 kwargs['menu_devices'] = 'active'
223 223 return render(request, 'base_list.html', kwargs)
224 224
225 225
226 226 def device(request, id_dev):
227 227
228 228 device = get_object_or_404(Device, pk=id_dev)
229 229
230 230 kwargs = {}
231 231 kwargs['device'] = device
232 232 kwargs['device_keys'] = ['device_type',
233 233 'ip_address', 'port_address', 'description']
234 234
235 235 kwargs['title'] = 'Device'
236 236 kwargs['suptitle'] = 'Details'
237 237 kwargs['menu_devices'] = 'active'
238 238
239 239 return render(request, 'device.html', kwargs)
240 240
241 241
242 242 @login_required
243 243 def device_new(request):
244 244
245 245 if request.method == 'GET':
246 246 form = DeviceForm()
247 247
248 248 if request.method == 'POST':
249 249 form = DeviceForm(request.POST)
250 250
251 251 if form.is_valid():
252 252 form.save()
253 253 return redirect('url_devices')
254 254
255 255 kwargs = {}
256 256 kwargs['form'] = form
257 257 kwargs['title'] = 'Device'
258 258 kwargs['suptitle'] = 'New'
259 259 kwargs['button'] = 'Create'
260 260 kwargs['menu_devices'] = 'active'
261 261
262 262 return render(request, 'base_edit.html', kwargs)
263 263
264 264
265 265 @login_required
266 266 def device_edit(request, id_dev):
267 267
268 268 device = get_object_or_404(Device, pk=id_dev)
269 269
270 270 if request.method == 'GET':
271 271 form = DeviceForm(instance=device)
272 272
273 273 if request.method == 'POST':
274 274 form = DeviceForm(request.POST, instance=device)
275 275
276 276 if form.is_valid():
277 277 form.save()
278 278 return redirect(device.get_absolute_url())
279 279
280 280 kwargs = {}
281 281 kwargs['form'] = form
282 282 kwargs['title'] = 'Device'
283 283 kwargs['suptitle'] = 'Edit'
284 284 kwargs['button'] = 'Update'
285 285 kwargs['menu_devices'] = 'active'
286 286
287 287 return render(request, 'base_edit.html', kwargs)
288 288
289 289
290 290 @login_required
291 291 def device_delete(request, id_dev):
292 292
293 293 device = get_object_or_404(Device, pk=id_dev)
294 294
295 295 if request.method == 'POST':
296 296
297 297 if is_developer(request.user):
298 298 device.delete()
299 299 return redirect('url_devices')
300 300
301 301 messages.error(request, 'Not enough permission to delete this object')
302 302 return redirect(device.get_absolute_url())
303 303
304 304 kwargs = {
305 305 'title': 'Delete',
306 306 'suptitle': 'Device',
307 307 'object': device,
308 308 'delete': True
309 309 }
310 310 kwargs['menu_devices'] = 'active'
311 311
312 312 return render(request, 'confirm.html', kwargs)
313 313
314 314
315 315 @login_required
316 316 def device_change_ip(request, id_dev):
317 317
318 318 device = get_object_or_404(Device, pk=id_dev)
319 319
320 320 if request.method == 'POST':
321 321
322 322 if is_developer(request.user):
323 323 device.change_ip(**request.POST.dict())
324 324 level, message = device.message.split('|')
325 325 messages.add_message(request, level, message)
326 326 else:
327 327 messages.error(
328 328 request, 'Not enough permission to delete this object')
329 329 return redirect(device.get_absolute_url())
330 330
331 331 kwargs = {
332 332 'title': 'Device',
333 333 'suptitle': 'Change IP',
334 334 'object': device,
335 335 'previous': device.get_absolute_url(),
336 336 'form': ChangeIpForm(initial={'ip_address': device.ip_address}),
337 337 'message': ' ',
338 338 }
339 339 kwargs['menu_devices'] = 'active'
340 340
341 341 return render(request, 'confirm.html', kwargs)
342 342
343 343
344 344 def campaigns(request):
345 345
346 346 page = request.GET.get('page')
347 347 order = ('-start_date',)
348 348 filters = request.GET.copy()
349 349
350 350 kwargs = get_paginator(Campaign, page, order, filters)
351 351
352 352 form = FilterForm(initial=request.GET, extra_fields=[
353 353 'range_date', 'tags', 'template'])
354 354 kwargs['keys'] = ['name', 'start_date', 'end_date', 'actions']
355 355 kwargs['title'] = 'Campaign'
356 356 kwargs['suptitle'] = 'List'
357 357 kwargs['no_sidebar'] = True
358 358 kwargs['form'] = form
359 359 kwargs['add_url'] = reverse('url_add_campaign')
360 360 filters.pop('page', None)
361 361 kwargs['q'] = urlencode(filters)
362 362 kwargs['menu_campaigns'] = 'active'
363 363
364 364 return render(request, 'base_list.html', kwargs)
365 365
366 366
367 367 def campaign(request, id_camp):
368 368
369 369 campaign = get_object_or_404(Campaign, pk=id_camp)
370 370 experiments = Experiment.objects.filter(campaign=campaign)
371 371
372 372 form = CampaignForm(instance=campaign)
373 373
374 374 kwargs = {}
375 375 kwargs['campaign'] = campaign
376 376 kwargs['campaign_keys'] = ['template', 'name',
377 377 'start_date', 'end_date', 'tags', 'description']
378 378
379 379 kwargs['experiments'] = experiments
380 380 kwargs['experiment_keys'] = [
381 381 'name', 'radar_system', 'start_time', 'end_time']
382 382
383 383 kwargs['title'] = 'Campaign'
384 384 kwargs['suptitle'] = 'Details'
385 385
386 386 kwargs['form'] = form
387 387 kwargs['button'] = 'Add Experiment'
388 388 kwargs['menu_campaigns'] = 'active'
389 389
390 390 return render(request, 'campaign.html', kwargs)
391 391
392 392
393 393 @login_required
394 394 def campaign_new(request):
395 395
396 396 kwargs = {}
397 397
398 398 if request.method == 'GET':
399 399
400 400 if 'template' in request.GET:
401 401 if request.GET['template'] == '0':
402 402 form = NewForm(initial={'create_from': 2},
403 403 template_choices=Campaign.objects.filter(template=True).values_list('id', 'name'))
404 404 else:
405 405 kwargs['button'] = 'Create'
406 406 kwargs['experiments'] = Configuration.objects.filter(
407 407 experiment=request.GET['template'])
408 408 kwargs['experiment_keys'] = ['name', 'start_time', 'end_time']
409 409 camp = Campaign.objects.get(pk=request.GET['template'])
410 410 form = CampaignForm(instance=camp,
411 411 initial={'name': '{}_{:%Y%m%d}'.format(camp.name, datetime.now()),
412 412 'template': False})
413 413 elif 'blank' in request.GET:
414 414 kwargs['button'] = 'Create'
415 415 form = CampaignForm()
416 416 else:
417 417 form = NewForm()
418 418
419 419 if request.method == 'POST':
420 420 kwargs['button'] = 'Create'
421 421 post = request.POST.copy()
422 422 experiments = []
423 423
424 424 for id_exp in post.getlist('experiments'):
425 425 exp = Experiment.objects.get(pk=id_exp)
426 426 new_exp = exp.clone(template=False)
427 427 experiments.append(new_exp)
428 428
429 429 post.setlist('experiments', [])
430 430
431 431 form = CampaignForm(post)
432 432
433 433 if form.is_valid():
434 434 campaign = form.save(commit=False)
435 435 campaign.author = request.user
436 436 for exp in experiments:
437 437 campaign.experiments.add(exp)
438 438 campaign.save()
439 439 return redirect('url_campaign', id_camp=campaign.id)
440 440
441 441 kwargs['form'] = form
442 442 kwargs['title'] = 'Campaign'
443 443 kwargs['suptitle'] = 'New'
444 444 kwargs['menu_campaigns'] = 'active'
445 445
446 446 return render(request, 'campaign_edit.html', kwargs)
447 447
448 448
449 449 @login_required
450 450 def campaign_edit(request, id_camp):
451 451
452 452 campaign = get_object_or_404(Campaign, pk=id_camp)
453 453
454 454 if request.method == 'GET':
455 455 form = CampaignForm(instance=campaign)
456 456
457 457 if request.method == 'POST':
458 458 exps = campaign.experiments.all().values_list('pk', flat=True)
459 459 post = request.POST.copy()
460 460 new_exps = post.getlist('experiments')
461 461 post.setlist('experiments', [])
462 462 form = CampaignForm(post, instance=campaign)
463 463
464 464 if form.is_valid():
465 465 camp = form.save()
466 466 for id_exp in new_exps:
467 467 if int(id_exp) in exps:
468 468 exps.pop(id_exp)
469 469 else:
470 470 exp = Experiment.objects.get(pk=id_exp)
471 471 if exp.template:
472 472 camp.experiments.add(exp.clone(template=False))
473 473 else:
474 474 camp.experiments.add(exp)
475 475
476 476 for id_exp in exps:
477 477 camp.experiments.remove(Experiment.objects.get(pk=id_exp))
478 478
479 479 return redirect('url_campaign', id_camp=id_camp)
480 480
481 481 kwargs = {}
482 482 kwargs['form'] = form
483 483 kwargs['title'] = 'Campaign'
484 484 kwargs['suptitle'] = 'Edit'
485 485 kwargs['button'] = 'Update'
486 486 kwargs['menu_campaigns'] = 'active'
487 487
488 488 return render(request, 'campaign_edit.html', kwargs)
489 489
490 490
491 491 @login_required
492 492 def campaign_delete(request, id_camp):
493 493
494 494 campaign = get_object_or_404(Campaign, pk=id_camp)
495 495
496 496 if request.method == 'POST':
497 497 if is_developer(request.user):
498 498
499 499 for exp in campaign.experiments.all():
500 500 for conf in Configuration.objects.filter(experiment=exp):
501 501 conf.delete()
502 502 exp.delete()
503 503 campaign.delete()
504 504
505 505 return redirect('url_campaigns')
506 506
507 507 messages.error(request, 'Not enough permission to delete this object')
508 508 return redirect(campaign.get_absolute_url())
509 509
510 510 kwargs = {
511 511 'title': 'Delete',
512 512 'suptitle': 'Campaign',
513 513 'object': campaign,
514 514 'delete': True
515 515 }
516 516 kwargs['menu_campaigns'] = 'active'
517 517
518 518 return render(request, 'confirm.html', kwargs)
519 519
520 520
521 521 @login_required
522 522 def campaign_export(request, id_camp):
523 523
524 524 campaign = get_object_or_404(Campaign, pk=id_camp)
525 525 content = campaign.parms_to_dict()
526 526 content_type = 'application/json'
527 527 filename = '%s_%s.json' % (campaign.name, campaign.id)
528 528
529 529 response = HttpResponse(content_type=content_type)
530 530 response['Content-Disposition'] = 'attachment; filename="%s"' % filename
531 531 response.write(json.dumps(content, indent=2))
532 532
533 533 return response
534 534
535 535
536 536 @login_required
537 537 def campaign_import(request, id_camp):
538 538
539 539 campaign = get_object_or_404(Campaign, pk=id_camp)
540 540
541 541 if request.method == 'GET':
542 542 file_form = UploadFileForm()
543 543
544 544 if request.method == 'POST':
545 545 file_form = UploadFileForm(request.POST, request.FILES)
546 546
547 547 if file_form.is_valid():
548 548 new_camp = campaign.dict_to_parms(
549 549 json.load(request.FILES['file']), CONF_MODELS)
550 550 messages.success(
551 551 request, "Parameters imported from: '%s'." % request.FILES['file'].name)
552 552 return redirect(new_camp.get_absolute_url_edit())
553 553
554 554 messages.error(request, "Could not import parameters from file")
555 555
556 556 kwargs = {}
557 557 kwargs['title'] = 'Campaign'
558 558 kwargs['form'] = file_form
559 559 kwargs['suptitle'] = 'Importing file'
560 560 kwargs['button'] = 'Import'
561 561 kwargs['menu_campaigns'] = 'active'
562 562
563 563 return render(request, 'campaign_import.html', kwargs)
564 564
565 565
566 566 def experiments(request):
567 567
568 568 page = request.GET.get('page')
569 569 order = ('location',)
570 570 filters = request.GET.copy()
571 571
572 572 if 'my experiments' in filters:
573 573 filters.pop('my experiments', None)
574 574 filters['mine'] = request.user.id
575 575
576 576 kwargs = get_paginator(Experiment, page, order, filters)
577 577
578 578 fields = ['tags', 'template']
579 579 if request.user.is_authenticated:
580 580 fields.append('my experiments')
581 581
582 582 form = FilterForm(initial=request.GET, extra_fields=fields)
583 583
584 584 kwargs['keys'] = ['name', 'radar_system',
585 585 'start_time', 'end_time', 'actions']
586 586 kwargs['title'] = 'Experiment'
587 587 kwargs['suptitle'] = 'List'
588 588 kwargs['no_sidebar'] = True
589 589 kwargs['form'] = form
590 590 kwargs['add_url'] = reverse('url_add_experiment')
591 591 filters = request.GET.copy()
592 592 filters.pop('page', None)
593 593 kwargs['q'] = urlencode(filters)
594 594 kwargs['menu_experiments'] = 'active'
595 595
596 596 return render(request, 'base_list.html', kwargs)
597 597
598 598
599 599 def experiment(request, id_exp):
600 600
601 601 experiment = get_object_or_404(Experiment, pk=id_exp)
602 602
603 603 configurations = Configuration.objects.filter(
604 604 experiment=experiment, type=0)
605 605
606 606 kwargs = {}
607 607
608 608 kwargs['experiment_keys'] = ['template', 'radar_system',
609 609 'name', 'freq', 'start_time', 'end_time']
610 610 kwargs['experiment'] = experiment
611 611 kwargs['configuration_keys'] = ['name', 'device__ip_address',
612 612 'device__port_address', 'device__status']
613 613 kwargs['configurations'] = configurations
614 614 kwargs['title'] = 'Experiment'
615 615 kwargs['suptitle'] = 'Details'
616 616 kwargs['button'] = 'Add Configuration'
617 617 kwargs['menu_experiments'] = 'active'
618 618
619 619 ###### SIDEBAR ######
620 620 kwargs.update(sidebar(experiment=experiment))
621 621
622 622 return render(request, 'experiment.html', kwargs)
623 623
624 624
625 625 @login_required
626 626 def experiment_new(request, id_camp=None):
627 627
628 628 if not is_developer(request.user):
629 629 messages.error(
630 630 request, 'Developer required, to create new Experiments')
631 631 return redirect('index')
632 632 kwargs = {}
633 633
634 634 if request.method == 'GET':
635 635 if 'template' in request.GET:
636 636 if request.GET['template'] == '0':
637 637 form = NewForm(initial={'create_from': 2},
638 638 template_choices=Experiment.objects.filter(template=True).values_list('id', 'name'))
639 639 else:
640 640 kwargs['button'] = 'Create'
641 641 kwargs['configurations'] = Configuration.objects.filter(
642 642 experiment=request.GET['template'])
643 643 kwargs['configuration_keys'] = ['name', 'device__name',
644 644 'device__ip_address', 'device__port_address']
645 645 exp = Experiment.objects.get(pk=request.GET['template'])
646 646 form = ExperimentForm(instance=exp,
647 647 initial={'name': '{}_{:%y%m%d}'.format(exp.name, datetime.now()),
648 648 'template': False})
649 649 elif 'blank' in request.GET:
650 650 kwargs['button'] = 'Create'
651 651 form = ExperimentForm()
652 652 else:
653 653 form = NewForm()
654 654
655 655 if request.method == 'POST':
656 656 form = ExperimentForm(request.POST)
657 657 if form.is_valid():
658 658 experiment = form.save(commit=False)
659 659 experiment.author = request.user
660 660 experiment.save()
661 661
662 662 if 'template' in request.GET:
663 663 configurations = Configuration.objects.filter(
664 664 experiment=request.GET['template'], type=0)
665 665 for conf in configurations:
666 666 conf.clone(experiment=experiment, template=False)
667 667
668 668 return redirect('url_experiment', id_exp=experiment.id)
669 669
670 670 kwargs['form'] = form
671 671 kwargs['title'] = 'Experiment'
672 672 kwargs['suptitle'] = 'New'
673 673 kwargs['menu_experiments'] = 'active'
674 674
675 675 return render(request, 'experiment_edit.html', kwargs)
676 676
677 677
678 678 @login_required
679 679 def experiment_edit(request, id_exp):
680 680
681 681 experiment = get_object_or_404(Experiment, pk=id_exp)
682 682
683 683 if request.method == 'GET':
684 684 form = ExperimentForm(instance=experiment)
685 685
686 686 if request.method == 'POST':
687 687 form = ExperimentForm(request.POST, instance=experiment)
688 688
689 689 if form.is_valid():
690 690 experiment = form.save()
691 691 return redirect('url_experiment', id_exp=experiment.id)
692 692
693 693 kwargs = {}
694 694 kwargs['form'] = form
695 695 kwargs['title'] = 'Experiment'
696 696 kwargs['suptitle'] = 'Edit'
697 697 kwargs['button'] = 'Update'
698 698 kwargs['menu_experiments'] = 'active'
699 699
700 700 return render(request, 'experiment_edit.html', kwargs)
701 701
702 702
703 703 @login_required
704 704 def experiment_delete(request, id_exp):
705 705
706 706 experiment = get_object_or_404(Experiment, pk=id_exp)
707 707
708 708 if request.method == 'POST':
709 709 if is_developer(request.user):
710 710 for conf in Configuration.objects.filter(experiment=experiment):
711 711 conf.delete()
712 712 experiment.delete()
713 713 return redirect('url_experiments')
714 714
715 715 messages.error(request, 'Not enough permission to delete this object')
716 716 return redirect(experiment.get_absolute_url())
717 717
718 718 kwargs = {
719 719 'title': 'Delete',
720 720 'suptitle': 'Experiment',
721 721 'object': experiment,
722 722 'delete': True
723 723 }
724 724
725 725 return render(request, 'confirm.html', kwargs)
726 726
727 727
728 728 @login_required
729 729 def experiment_export(request, id_exp):
730 730
731 731 experiment = get_object_or_404(Experiment, pk=id_exp)
732 732 content = experiment.parms_to_dict()
733 733 content_type = 'application/json'
734 734 filename = '%s_%s.json' % (experiment.name, experiment.id)
735 735
736 736 response = HttpResponse(content_type=content_type)
737 737 response['Content-Disposition'] = 'attachment; filename="%s"' % filename
738 738 response.write(json.dumps(content, indent=2))
739 739
740 740 return response
741 741
742 742
743 743 @login_required
744 744 def experiment_import(request, id_exp):
745 745
746 746 experiment = get_object_or_404(Experiment, pk=id_exp)
747 747 configurations = Configuration.objects.filter(experiment=experiment)
748 748
749 749 if request.method == 'GET':
750 750 file_form = UploadFileForm()
751 751
752 752 if request.method == 'POST':
753 753 file_form = UploadFileForm(request.POST, request.FILES)
754 754
755 755 if file_form.is_valid():
756 756 new_exp = experiment.dict_to_parms(
757 757 json.load(request.FILES['file']), CONF_MODELS)
758 758 messages.success(
759 759 request, "Parameters imported from: '%s'." % request.FILES['file'].name)
760 760 return redirect(new_exp.get_absolute_url_edit())
761 761
762 762 messages.error(request, "Could not import parameters from file")
763 763
764 764 kwargs = {}
765 765 kwargs['title'] = 'Experiment'
766 766 kwargs['form'] = file_form
767 767 kwargs['suptitle'] = 'Importing file'
768 768 kwargs['button'] = 'Import'
769 769 kwargs['menu_experiments'] = 'active'
770 770
771 771 kwargs.update(sidebar(experiment=experiment))
772 772
773 773 return render(request, 'experiment_import.html', kwargs)
774 774
775 775
776 776 @login_required
777 777 def experiment_start(request, id_exp):
778 778
779 779 exp = get_object_or_404(Experiment, pk=id_exp)
780 780
781 781 if exp.status == 2:
782 782 messages.warning(request, 'Experiment {} already runnnig'.format(exp))
783 783 else:
784 784 exp.status = exp.start()
785 785 if exp.status == 0:
786 786 messages.error(request, 'Experiment {} not start'.format(exp))
787 787 if exp.status == 2:
788 788 messages.success(request, 'Experiment {} started'.format(exp))
789 789
790 790 exp.save()
791 791
792 792 return redirect(exp.get_absolute_url())
793 793
794 794
795 795 @login_required
796 796 def experiment_stop(request, id_exp):
797 797
798 798 exp = get_object_or_404(Experiment, pk=id_exp)
799 799
800 800 if exp.status == 2:
801 801 exp.status = exp.stop()
802 802 exp.save()
803 803 messages.success(request, 'Experiment {} stopped'.format(exp))
804 804 else:
805 805 messages.error(request, 'Experiment {} not running'.format(exp))
806 806
807 807 return redirect(exp.get_absolute_url())
808 808
809 809
810 810 def experiment_status(request, id_exp):
811 811
812 812 exp = get_object_or_404(Experiment, pk=id_exp)
813 813
814 814 exp.get_status()
815 815
816 816 return redirect(exp.get_absolute_url())
817 817
818 818
819 819 @login_required
820 820 def experiment_mix(request, id_exp):
821 821
822 822 experiment = get_object_or_404(Experiment, pk=id_exp)
823 823 rc_confs = [conf for conf in RCConfiguration.objects.filter(
824 824 experiment=id_exp,
825 825 type=0,
826 826 mix=False)]
827 827
828 828 if len(rc_confs) < 2:
829 829 messages.warning(
830 830 request, 'You need at least two RC Configurations to make a mix')
831 831 return redirect(experiment.get_absolute_url())
832 832
833 833 mix_confs = RCConfiguration.objects.filter(experiment=id_exp, mix=True, type=0)
834 834
835 835 if mix_confs:
836 836 mix = mix_confs[0]
837 837 else:
838 838 mix = RCConfiguration(experiment=experiment,
839 839 device=rc_confs[0].device,
840 840 ipp=rc_confs[0].ipp,
841 841 clock_in=rc_confs[0].clock_in,
842 842 clock_divider=rc_confs[0].clock_divider,
843 843 mix=True,
844 844 parameters='')
845 845 mix.save()
846 846
847 847 line_type = RCLineType.objects.get(name='mix')
848 848 for i in range(len(rc_confs[0].get_lines())):
849 849 line = RCLine(rc_configuration=mix, line_type=line_type, channel=i)
850 850 line.save()
851 851
852 852 initial = {'name': mix.name,
853 853 'result': parse_mix_result(mix.parameters),
854 854 'delay': 0,
855 855 'mask': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
856 856 }
857 857
858 858 if request.method == 'GET':
859 859 form = RCMixConfigurationForm(confs=rc_confs, initial=initial)
860 860
861 861 if request.method == 'POST':
862 862 result = mix.parameters
863 863
864 864 if '{}|'.format(request.POST['experiment']) in result:
865 865 messages.error(request, 'Configuration already added')
866 866 else:
867 867 if 'operation' in request.POST:
868 868 operation = MIX_OPERATIONS[request.POST['operation']]
869 869 else:
870 870 operation = ' '
871 871
872 872 mode = MIX_MODES[request.POST['mode']]
873 873
874 874 if result:
875 875 result = '{}-{}|{}|{}|{}|{}'.format(mix.parameters,
876 876 request.POST['experiment'],
877 877 mode,
878 878 operation,
879 879 float(
880 880 request.POST['delay']),
881 881 parse_mask(
882 882 request.POST.getlist('mask'))
883 883 )
884 884 else:
885 885 result = '{}|{}|{}|{}|{}'.format(request.POST['experiment'],
886 886 mode,
887 887 operation,
888 888 float(request.POST['delay']),
889 889 parse_mask(
890 890 request.POST.getlist('mask'))
891 891 )
892 892
893 893 mix.parameters = result
894 894 mix.save()
895 895 mix.update_pulses()
896 896
897 897 initial['result'] = parse_mix_result(result)
898 898 initial['name'] = mix.name
899 899
900 900 form = RCMixConfigurationForm(initial=initial, confs=rc_confs)
901 901
902 902 kwargs = {
903 903 'title': 'Experiment',
904 904 'suptitle': 'Mix Configurations',
905 905 'form': form,
906 906 'extra_button': 'Delete',
907 907 'button': 'Add',
908 908 'cancel': 'Back',
909 909 'previous': experiment.get_absolute_url(),
910 910 'id_exp': id_exp,
911 911
912 912 }
913 913 kwargs['menu_experiments'] = 'active'
914 914
915 915 return render(request, 'experiment_mix.html', kwargs)
916 916
917 917
918 918 @login_required
919 919 def experiment_mix_delete(request, id_exp):
920 920
921 921 conf = RCConfiguration.objects.get(experiment=id_exp, mix=True, type=0)
922 922 values = conf.parameters.split('-')
923 923 conf.parameters = '-'.join(values[:-1])
924 924 conf.save()
925 925
926 926 return redirect('url_mix_experiment', id_exp=id_exp)
927 927
928 928
929 929 def experiment_summary(request, id_exp):
930 930
931 931 experiment = get_object_or_404(Experiment, pk=id_exp)
932 932 configurations = Configuration.objects.filter(
933 933 experiment=experiment, type=0)
934 934
935 935 kwargs = {}
936 936 kwargs['experiment_keys'] = ['radar_system',
937 937 'name', 'freq', 'start_time', 'end_time']
938 938 kwargs['experiment'] = experiment
939 939 kwargs['configurations'] = []
940 940 kwargs['title'] = 'Experiment Summary'
941 941 kwargs['suptitle'] = 'Details'
942 942 kwargs['button'] = 'Verify Parameters'
943 943
944 944 c_vel = 3.0*(10**8) # m/s
945 945 ope_freq = experiment.freq*(10**6) # 1/s
946 946 radar_lambda = c_vel/ope_freq # m
947 947 kwargs['radar_lambda'] = radar_lambda
948 948
949 949 ipp = None
950 950 nsa = 1
951 951 code_id = 0
952 952 tx_line = {}
953 953
954 954 for configuration in configurations.filter(device__device_type__name = 'rc'):
955 955
956 956 if configuration.mix:
957 957 continue
958 958 conf = {'conf': configuration}
959 959 conf['keys'] = []
960 960 conf['NTxs'] = configuration.ntx
961 961 conf['keys'].append('NTxs')
962 962 ipp = configuration.ipp
963 963 conf['IPP'] = ipp
964 964 conf['keys'].append('IPP')
965 965 lines = configuration.get_lines(line_type__name='tx')
966 966
967 967 for tx_line in lines:
968 968 tx_params = json.loads(tx_line.params)
969 969 conf[tx_line.get_name()] = '{} Km'.format(tx_params['pulse_width'])
970 970 conf['keys'].append(tx_line.get_name())
971 971 delays = tx_params['delays']
972 972 if delays not in ('', '0'):
973 973 n = len(delays.split(','))
974 974 taus = '{} Taus: {}'.format(n, delays)
975 975 else:
976 976 taus = '-'
977 977 conf['Taus ({})'.format(tx_line.get_name())] = taus
978 978 conf['keys'].append('Taus ({})'.format(tx_line.get_name()))
979 979 for code_line in configuration.get_lines(line_type__name='codes'):
980 980 code_params = json.loads(code_line.params)
981 981 code_id = code_params['code']
982 982 if tx_line.pk == int(code_params['TX_ref']):
983 983 conf['Code ({})'.format(tx_line.get_name())] = '{}:{}'.format(RCLineCode.objects.get(pk=code_params['code']),
984 984 '-'.join(code_params['codes']))
985 985 conf['keys'].append('Code ({})'.format(tx_line.get_name()))
986 986
987 987 for windows_line in configuration.get_lines(line_type__name='windows'):
988 988 win_params = json.loads(windows_line.params)
989 989 if tx_line.pk == int(win_params['TX_ref']):
990 990 windows = ''
991 991 nsa = win_params['params'][0]['number_of_samples']
992 992 for i, params in enumerate(win_params['params']):
993 993 windows += 'W{}: Ho={first_height} km DH={resolution} km NSA={number_of_samples}<br>'.format(
994 994 i, **params)
995 995 conf['Window'] = mark_safe(windows)
996 996 conf['keys'].append('Window')
997 997
998 998 kwargs['configurations'].append(conf)
999 999
1000 1000 for configuration in configurations.filter(device__device_type__name = 'jars'):
1001 1001
1002 1002 conf = {'conf': configuration}
1003 1003 conf['keys'] = []
1004 1004 conf['Type of Data'] = EXPERIMENT_TYPE[configuration.exp_type][1]
1005 1005 conf['keys'].append('Type of Data')
1006 1006 channels_number = configuration.channels_number
1007 1007 exp_type = configuration.exp_type
1008 1008 fftpoints = configuration.fftpoints
1009 1009 filter_parms = json.loads(configuration.filter_parms)
1010 1010 spectral_number = configuration.spectral_number
1011 1011 acq_profiles = configuration.acq_profiles
1012 1012 cohe_integr = configuration.cohe_integr
1013 1013 profiles_block = configuration.profiles_block
1014 1014
1015 1015 conf['Num of Profiles'] = acq_profiles
1016 1016 conf['keys'].append('Num of Profiles')
1017 1017
1018 1018 conf['Prof per Block'] = profiles_block
1019 1019 conf['keys'].append('Prof per Block')
1020 1020
1021 1021 conf['Blocks per File'] = configuration.raw_data_blocks
1022 1022 conf['keys'].append('Blocks per File')
1023 1023
1024 1024 if exp_type == 0: # Short
1025 1025 bytes_ = 2
1026 1026 b = nsa*2*bytes_*channels_number
1027 1027 else: # Float
1028 1028 bytes_ = 4
1029 1029 channels = channels_number + spectral_number
1030 1030 b = nsa*2*bytes_*fftpoints*channels
1031 1031
1032 1032 codes_num = 7
1033 1033 if code_id == 2:
1034 1034 codes_num = 7
1035 1035 elif code_id == 12:
1036 1036 codes_num = 15
1037 1037
1038 1038 #Jars filter values:
1039 1039
1040 1040 clock = float(filter_parms['clock'])
1041 1041 filter_2 = int(filter_parms['cic_2'])
1042 1042 filter_5 = int(filter_parms['cic_5'])
1043 1043 filter_fir = int(filter_parms['fir'])
1044 1044 Fs_MHz = clock/(filter_2*filter_5*filter_fir)
1045 1045
1046 1046 #Jars values:
1047 1047 if ipp is not None:
1048 1048 IPP_units = ipp/0.15*Fs_MHz
1049 1049 IPP_us = IPP_units / Fs_MHz
1050 1050 IPP_s = IPP_units / (Fs_MHz * (10**6))
1051 1051 Ts = 1/(Fs_MHz*(10**6))
1052 1052
1053 1053 Va = radar_lambda/(4*Ts*cohe_integr)
1054 1054 rate_bh = ((nsa-codes_num)*channels_number*2 *
1055 1055 bytes_/IPP_us)*(36*(10**8)/cohe_integr)
1056 1056 rate_gh = rate_bh/(1024*1024*1024)
1057 1057
1058 1058 conf['Time per Block'] = IPP_s * profiles_block * cohe_integr
1059 1059 conf['keys'].append('Time per Block')
1060 1060 conf['Acq time'] = IPP_s * acq_profiles
1061 1061 conf['keys'].append('Acq time')
1062 1062 conf['Data rate'] = str(rate_gh)+" (GB/h)"
1063 1063 conf['keys'].append('Data rate')
1064 1064 conf['Va (m/s)'] = Va
1065 1065 conf['keys'].append('Va (m/s)')
1066 1066 conf['Vrange (m/s)'] = 3/(2*IPP_s*cohe_integr)
1067 1067 conf['keys'].append('Vrange (m/s)')
1068 1068
1069 1069 kwargs['configurations'].append(conf)
1070 1070 kwargs['menu_experiments'] = 'active'
1071 1071
1072 1072 ###### SIDEBAR ######
1073 1073 kwargs.update(sidebar(experiment=experiment))
1074 1074
1075 1075 return render(request, 'experiment_summary.html', kwargs)
1076 1076
1077 1077
1078 1078 @login_required
1079 1079 def experiment_verify(request, id_exp):
1080 1080
1081 1081 experiment = get_object_or_404(Experiment, pk=id_exp)
1082 1082 experiment_data = experiment.parms_to_dict()
1083 1083 configurations = Configuration.objects.filter(
1084 1084 experiment=experiment, type=0)
1085 1085
1086 1086 kwargs = {}
1087 1087
1088 1088 kwargs['experiment_keys'] = ['template',
1089 1089 'radar_system', 'name', 'start_time', 'end_time']
1090 1090 kwargs['experiment'] = experiment
1091 1091
1092 1092 kwargs['configuration_keys'] = ['name', 'device__ip_address',
1093 1093 'device__port_address', 'device__status']
1094 1094 kwargs['configurations'] = configurations
1095 1095 kwargs['experiment_data'] = experiment_data
1096 1096
1097 1097 kwargs['title'] = 'Verify Experiment'
1098 1098 kwargs['suptitle'] = 'Parameters'
1099 1099
1100 1100 kwargs['button'] = 'Update'
1101 1101
1102 1102 jars_conf = False
1103 1103 rc_conf = False
1104 1104 dds_conf = False
1105 1105
1106 1106 for configuration in configurations:
1107 1107 #-------------------- JARS -----------------------:
1108 1108 if configuration.device.device_type.name == 'jars':
1109 1109 jars_conf = True
1110 1110 jars = configuration
1111 1111 kwargs['jars_conf'] = jars_conf
1112 1112 filter_parms = json.loads(jars.filter_parms)
1113 1113 kwargs['filter_parms'] = filter_parms
1114 1114 #--Sampling Frequency
1115 1115 clock = filter_parms['clock']
1116 1116 filter_2 = filter_parms['cic_2']
1117 1117 filter_5 = filter_parms['cic_5']
1118 1118 filter_fir = filter_parms['fir']
1119 1119 samp_freq_jars = clock/filter_2/filter_5/filter_fir
1120 1120
1121 1121 kwargs['samp_freq_jars'] = samp_freq_jars
1122 1122 kwargs['jars'] = configuration
1123 1123
1124 1124 #--------------------- RC ----------------------:
1125 1125 if configuration.device.device_type.name == 'rc' and not configuration.mix:
1126 1126 rc_conf = True
1127 1127 rc = configuration
1128 1128
1129 1129 rc_parms = configuration.parms_to_dict()
1130 1130
1131 1131 win_lines = rc.get_lines(line_type__name='windows')
1132 1132 if win_lines:
1133 1133 dh = json.loads(win_lines[0].params)['params'][0]['resolution']
1134 1134 #--Sampling Frequency
1135 1135 samp_freq_rc = 0.15/dh
1136 1136 kwargs['samp_freq_rc'] = samp_freq_rc
1137 1137
1138 1138 kwargs['rc_conf'] = rc_conf
1139 1139 kwargs['rc'] = configuration
1140 1140
1141 1141 #-------------------- DDS ----------------------:
1142 1142 if configuration.device.device_type.name == 'dds':
1143 1143 dds_conf = True
1144 1144 dds = configuration
1145 1145 dds_parms = configuration.parms_to_dict()
1146 1146
1147 1147 kwargs['dds_conf'] = dds_conf
1148 1148 kwargs['dds'] = configuration
1149 1149
1150 1150 #------------Validation------------:
1151 1151 #Clock
1152 1152 if dds_conf and rc_conf and jars_conf:
1153 1153 if float(filter_parms['clock']) != float(rc_parms['configurations']['byId'][str(rc.pk)]['clock_in']) and float(rc_parms['configurations']['byId'][str(rc.pk)]['clock_in']) != float(dds_parms['configurations']['byId'][str(dds.pk)]['clock']):
1154 1154 messages.warning(request, "Devices don't have the same clock.")
1155 1155 elif rc_conf and jars_conf:
1156 1156 if float(filter_parms['clock']) != float(rc_parms['configurations']['byId'][str(rc.pk)]['clock_in']):
1157 1157 messages.warning(request, "Devices don't have the same clock.")
1158 1158 elif rc_conf and dds_conf:
1159 1159 if float(rc_parms['configurations']['byId'][str(rc.pk)]['clock_in']) != float(dds_parms['configurations']['byId'][str(dds.pk)]['clock']):
1160 1160 messages.warning(request, "Devices don't have the same clock.")
1161 1161 if float(samp_freq_rc) != float(dds_parms['configurations']['byId'][str(dds.pk)]['frequencyA']):
1162 1162 messages.warning(
1163 1163 request, "Devices don't have the same Frequency A.")
1164 1164
1165 1165 #------------POST METHOD------------:
1166 1166 if request.method == 'POST':
1167 1167 if request.POST['suggest_clock']:
1168 1168 try:
1169 1169 suggest_clock = float(request.POST['suggest_clock'])
1170 1170 except:
1171 1171 messages.warning(request, "Invalid value in CLOCK IN.")
1172 1172 return redirect('url_verify_experiment', id_exp=experiment.id)
1173 1173 else:
1174 1174 suggest_clock = ""
1175 1175 if suggest_clock:
1176 1176 if rc_conf:
1177 1177 rc.clock_in = suggest_clock
1178 1178 rc.save()
1179 1179 if jars_conf:
1180 1180 filter_parms = jars.filter_parms
1181 1181 filter_parms = ast.literal_eval(filter_parms)
1182 1182 filter_parms['clock'] = suggest_clock
1183 1183 jars.filter_parms = json.dumps(filter_parms)
1184 1184 jars.save()
1185 1185 kwargs['filter_parms'] = filter_parms
1186 1186 if dds_conf:
1187 1187 dds.clock = suggest_clock
1188 1188 dds.save()
1189 1189
1190 1190 if request.POST['suggest_frequencyA']:
1191 1191 try:
1192 1192 suggest_frequencyA = float(request.POST['suggest_frequencyA'])
1193 1193 except:
1194 1194 messages.warning(request, "Invalid value in FREQUENCY A.")
1195 1195 return redirect('url_verify_experiment', id_exp=experiment.id)
1196 1196 else:
1197 1197 suggest_frequencyA = ""
1198 1198 if suggest_frequencyA:
1199 1199 if jars_conf:
1200 1200 filter_parms = jars.filter_parms
1201 1201 filter_parms = ast.literal_eval(filter_parms)
1202 1202 filter_parms['fch'] = suggest_frequencyA
1203 1203 jars.filter_parms = json.dumps(filter_parms)
1204 1204 jars.save()
1205 1205 kwargs['filter_parms'] = filter_parms
1206 1206 if dds_conf:
1207 1207 dds.frequencyA_Mhz = request.POST['suggest_frequencyA']
1208 1208 dds.save()
1209 1209
1210 1210 kwargs['menu_experiments'] = 'active'
1211 1211 kwargs.update(sidebar(experiment=experiment))
1212 1212 return render(request, 'experiment_verify.html', kwargs)
1213 1213
1214 1214
1215 1215 def parse_mix_result(s):
1216 1216
1217 1217 values = s.split('-')
1218 1218 html = 'EXP MOD OPE DELAY MASK\r\n'
1219 1219
1220 1220 if not values or values[0] in ('', ' '):
1221 1221 return mark_safe(html)
1222 1222
1223 1223 for i, value in enumerate(values):
1224 1224 if not value:
1225 1225 continue
1226 1226 pk, mode, operation, delay, mask = value.split('|')
1227 1227 conf = RCConfiguration.objects.get(pk=pk)
1228 1228 if i == 0:
1229 1229 html += '{:20.18}{:3}{:4}{:9}km{:>6}\r\n'.format(
1230 1230 conf.name,
1231 1231 mode,
1232 1232 ' ',
1233 1233 delay,
1234 1234 mask)
1235 1235 else:
1236 1236 html += '{:20.18}{:3}{:4}{:9}km{:>6}\r\n'.format(
1237 1237 conf.name,
1238 1238 mode,
1239 1239 operation,
1240 1240 delay,
1241 1241 mask)
1242 1242
1243 1243 return mark_safe(html)
1244 1244
1245 1245
1246 1246 def parse_mask(l):
1247 1247
1248 1248 values = []
1249 1249
1250 1250 for x in range(16):
1251 1251 if '{}'.format(x) in l:
1252 1252 values.append(1)
1253 1253 else:
1254 1254 values.append(0)
1255 1255
1256 1256 values.reverse()
1257 1257
1258 1258 return int(''.join([str(x) for x in values]), 2)
1259 1259
1260 1260
1261 1261 def dev_confs(request):
1262 1262
1263 1263 page = request.GET.get('page')
1264 1264 order = ('programmed_date', )
1265 1265 filters = request.GET.copy()
1266 1266 if 'my configurations' in filters:
1267 1267 filters.pop('my configurations', None)
1268 1268 filters['mine'] = request.user.id
1269 1269 kwargs = get_paginator(Configuration, page, order, filters)
1270 1270 fields = ['tags', 'template', 'historical']
1271 1271 if request.user.is_authenticated:
1272 1272 fields.append('my configurations')
1273 1273 form = FilterForm(initial=request.GET, extra_fields=fields)
1274 1274 kwargs['keys'] = ['name', 'experiment',
1275 1275 'type', 'programmed_date', 'actions']
1276 1276 kwargs['title'] = 'Configuration'
1277 1277 kwargs['suptitle'] = 'List'
1278 1278 kwargs['no_sidebar'] = True
1279 1279 kwargs['form'] = form
1280 1280 kwargs['add_url'] = reverse('url_add_dev_conf', args=[0])
1281 1281 filters = request.GET.copy()
1282 1282 filters.pop('page', None)
1283 1283 kwargs['q'] = urlencode(filters)
1284 1284 kwargs['menu_configurations'] = 'active'
1285 1285
1286 1286 return render(request, 'base_list.html', kwargs)
1287 1287
1288 1288
1289 1289 def dev_conf(request, id_conf):
1290 1290
1291 1291 conf = get_object_or_404(Configuration, pk=id_conf)
1292 1292
1293 1293 return redirect(conf.get_absolute_url())
1294 1294
1295 1295
1296 1296 @login_required
1297 1297 def dev_conf_new(request, id_exp=0, id_dev=0):
1298 1298
1299 1299 if not is_developer(request.user):
1300 1300 messages.error(
1301 1301 request, 'Developer required, to create new configurations')
1302 1302 return redirect('index')
1303 1303
1304 1304 initial = {}
1305 1305 kwargs = {}
1306 1306
1307 1307 if id_exp != 0:
1308 1308 initial['experiment'] = id_exp
1309 1309
1310 1310 if id_dev != 0:
1311 1311 initial['device'] = id_dev
1312 1312
1313 1313 if request.method == 'GET':
1314 1314
1315 1315 if id_dev:
1316 1316 kwargs['button'] = 'Create'
1317 1317 device = Device.objects.get(pk=id_dev)
1318 1318 DevConfForm = CONF_FORMS[device.device_type.name]
1319 1319 initial['name'] = request.GET['name']
1320 1320 form = DevConfForm(initial=initial)
1321 1321 else:
1322 1322 if 'template' in request.GET:
1323 1323 if request.GET['template'] == '0':
1324 1324 choices = [(conf.pk, '{}'.format(conf))
1325 1325 for conf in Configuration.objects.filter(template=True)]
1326 1326 form = NewForm(initial={'create_from': 2},
1327 1327 template_choices=choices)
1328 1328 else:
1329 1329 kwargs['button'] = 'Create'
1330 1330 conf = Configuration.objects.get(
1331 1331 pk=request.GET['template'])
1332 1332 id_dev = conf.device.pk
1333 1333 DevConfForm = CONF_FORMS[conf.device.device_type.name]
1334 1334 form = DevConfForm(instance=conf,
1335 1335 initial={'name': '{}_{:%y%m%d}'.format(conf.name, datetime.now()),
1336 1336 'template': False,
1337 1337 'experiment': id_exp})
1338 1338 elif 'blank' in request.GET:
1339 1339 kwargs['button'] = 'Create'
1340 1340 form = ConfigurationForm(initial=initial)
1341 1341 else:
1342 1342 form = NewForm()
1343 1343
1344 1344 if request.method == 'POST':
1345 1345
1346 1346 device = Device.objects.get(pk=request.POST['device'])
1347 1347 DevConfForm = CONF_FORMS[device.device_type.name]
1348 1348
1349 1349 form = DevConfForm(request.POST)
1350 1350 kwargs['button'] = 'Create'
1351 1351 if form.is_valid():
1352 1352 conf = form.save(commit=False)
1353 1353 conf.author = request.user
1354 1354 conf.save()
1355 1355
1356 1356 if 'template' in request.GET and conf.device.device_type.name == 'rc':
1357 1357 lines = RCLine.objects.filter(
1358 1358 rc_configuration=request.GET['template'])
1359 1359 for line in lines:
1360 1360 line.clone(rc_configuration=conf)
1361 1361
1362 1362 new_lines = conf.get_lines()
1363 1363 for line in new_lines:
1364 1364 line_params = json.loads(line.params)
1365 1365 if 'TX_ref' in line_params:
1366 1366 ref_line = RCLine.objects.get(pk=line_params['TX_ref'])
1367 1367 line_params['TX_ref'] = ['{}'.format(
1368 1368 l.pk) for l in new_lines if l.get_name() == ref_line.get_name()][0]
1369 1369 line.params = json.dumps(line_params)
1370 1370 line.save()
1371 1371
1372 1372 return redirect('url_dev_conf', id_conf=conf.pk)
1373 1373
1374 1374 kwargs['id_exp'] = id_exp
1375 1375 kwargs['form'] = form
1376 1376 kwargs['title'] = 'Configuration'
1377 1377 kwargs['suptitle'] = 'New'
1378 1378 kwargs['menu_configurations'] = 'active'
1379 1379
1380 1380 if id_dev != 0:
1381 1381 device = Device.objects.get(pk=id_dev)
1382 1382 kwargs['device'] = device.device_type.name
1383 1383
1384 1384 return render(request, 'dev_conf_edit.html', kwargs)
1385 1385
1386 1386
1387 1387 @login_required
1388 1388 def dev_conf_edit(request, id_conf):
1389 1389
1390 1390 conf = get_object_or_404(Configuration, pk=id_conf)
1391 1391
1392 1392 DevConfForm = CONF_FORMS[conf.device.device_type.name]
1393 1393
1394 1394 if request.method == 'GET':
1395 1395 form = DevConfForm(instance=conf)
1396 1396
1397 1397 if request.method == 'POST':
1398 1398 form = DevConfForm(request.POST, instance=conf)
1399 1399
1400 1400 if form.is_valid():
1401 1401 form.save()
1402 1402 return redirect('url_dev_conf', id_conf=id_conf)
1403 1403
1404 1404 kwargs = {}
1405 1405 kwargs['form'] = form
1406 1406 kwargs['title'] = 'Device Configuration'
1407 1407 kwargs['suptitle'] = 'Edit'
1408 1408 kwargs['button'] = 'Update'
1409 1409 kwargs['menu_configurations'] = 'active'
1410 1410
1411 1411 ###### SIDEBAR ######
1412 1412 kwargs.update(sidebar(conf=conf))
1413 1413
1414 1414 return render(request, '%s_conf_edit.html' % conf.device.device_type.name, kwargs)
1415 1415
1416 1416
1417 1417 @login_required
1418 1418 def dev_conf_start(request, id_conf):
1419 1419
1420 1420 conf = get_object_or_404(Configuration, pk=id_conf)
1421 1421
1422 1422 if conf.start_device():
1423 1423 messages.success(request, conf.message)
1424 1424 else:
1425 1425 messages.error(request, conf.message)
1426 1426
1427 1427 #conf.status_device()
1428 1428
1429 1429 return redirect(conf.get_absolute_url())
1430 1430
1431 1431
1432 1432 @login_required
1433 1433 def dev_conf_stop(request, id_conf):
1434 1434
1435 1435 conf = get_object_or_404(Configuration, pk=id_conf)
1436 1436
1437 1437 if conf.stop_device():
1438 1438 messages.success(request, conf.message)
1439 1439 else:
1440 1440 messages.error(request, conf.message)
1441 1441
1442 1442 #conf.status_device()
1443 1443
1444 1444 return redirect(conf.get_absolute_url())
1445 1445
1446 1446
1447 @login_required
1447 1448 def dev_conf_status(request, id_conf):
1448 1449
1449 1450 conf = get_object_or_404(Configuration, pk=id_conf)
1450 1451
1452 if conf.device.device_type.name == 'abs':
1453 abs = request.user.profile.abs_active
1454 if abs<>conf:
1455 url = '#' if abs is None else abs.get_absolute_url()
1456 label = 'None' if abs is None else abs.label
1457 messages.warning(
1458 request,
1459 mark_safe('The current configuration has not been written in the modules, the active configuration is <a href="{}">{}</a>'.format(
1460 url,
1461 label
1462 ))
1463 )
1464 return redirect(conf.get_absolute_url())
1465
1451 1466 if conf.status_device():
1452 1467 messages.success(request, conf.message)
1453 1468 else:
1454 1469 messages.error(request, conf.message)
1455 1470
1456 1471 return redirect(conf.get_absolute_url())
1457 1472
1458 1473
1459 1474 @login_required
1460 1475 def dev_conf_reset(request, id_conf):
1461 1476
1462 1477 conf = get_object_or_404(Configuration, pk=id_conf)
1463 1478
1464 1479 if conf.reset_device():
1465 1480 messages.success(request, conf.message)
1466 1481 else:
1467 1482 messages.error(request, conf.message)
1468 1483
1469 1484 return redirect(conf.get_absolute_url())
1470 1485
1471 1486
1472 1487 @login_required
1473 1488 def dev_conf_write(request, id_conf):
1474 1489
1475 1490 conf = get_object_or_404(Configuration, pk=id_conf)
1476 1491
1477 1492 if conf.write_device():
1478 1493 messages.success(request, conf.message)
1479 1494 if has_been_modified(conf):
1480 1495 conf.clone(type=1, template=False)
1481 1496 else:
1482 1497 messages.error(request, conf.message)
1483 1498
1484 1499 return redirect(get_object_or_404(Configuration, pk=id_conf).get_absolute_url())
1485 1500
1486 1501
1487 1502 @login_required
1488 1503 def dev_conf_read(request, id_conf):
1489 1504
1490 1505 conf = get_object_or_404(Configuration, pk=id_conf)
1491 1506
1492 1507 DevConfForm = CONF_FORMS[conf.device.device_type.name]
1493 1508
1494 1509 if request.method == 'GET':
1495 1510
1496 1511 parms = conf.read_device()
1497 1512 #conf.status_device()
1498 1513
1499 1514 if not parms:
1500 1515 messages.error(request, conf.message)
1501 1516 return redirect(conf.get_absolute_url())
1502 1517
1503 1518 form = DevConfForm(initial=parms, instance=conf)
1504 1519
1505 1520 if request.method == 'POST':
1506 1521 form = DevConfForm(request.POST, instance=conf)
1507 1522
1508 1523 if form.is_valid():
1509 1524 form.save()
1510 1525 return redirect(conf.get_absolute_url())
1511 1526
1512 1527 messages.error(request, "Parameters could not be saved")
1513 1528
1514 1529 kwargs = {}
1515 1530 kwargs['id_dev'] = conf.id
1516 1531 kwargs['form'] = form
1517 1532 kwargs['title'] = 'Device Configuration'
1518 1533 kwargs['suptitle'] = 'Parameters read from device'
1519 1534 kwargs['button'] = 'Save'
1520 1535
1521 1536 ###### SIDEBAR ######
1522 1537 kwargs.update(sidebar(conf=conf))
1523 1538
1524 1539 return render(request, '%s_conf_edit.html' % conf.device.device_type.name, kwargs)
1525 1540
1526 1541
1527 1542 @login_required
1528 1543 def dev_conf_import(request, id_conf):
1529 1544
1530 1545 conf = get_object_or_404(Configuration, pk=id_conf)
1531 1546 DevConfForm = CONF_FORMS[conf.device.device_type.name]
1532 1547
1533 1548 if request.method == 'GET':
1534 1549 file_form = UploadFileForm()
1535 1550
1536 1551 if request.method == 'POST':
1537 1552 file_form = UploadFileForm(request.POST, request.FILES)
1538 1553
1539 1554 if file_form.is_valid():
1540 1555
1541 1556 data = conf.import_from_file(request.FILES['file'])
1542 1557 parms = Params(data=data).get_conf(
1543 1558 dtype=conf.device.device_type.name)
1544 1559
1545 1560 if parms:
1546 1561
1547 1562 form = DevConfForm(initial=parms, instance=conf)
1548 1563
1549 1564 kwargs = {}
1550 1565 kwargs['id_dev'] = conf.id
1551 1566 kwargs['form'] = form
1552 1567 kwargs['title'] = 'Device Configuration'
1553 1568 kwargs['suptitle'] = 'Parameters imported'
1554 1569 kwargs['button'] = 'Save'
1555 1570 kwargs['action'] = conf.get_absolute_url_edit()
1556 1571 kwargs['previous'] = conf.get_absolute_url()
1557 1572
1558 1573 ###### SIDEBAR ######
1559 1574 kwargs.update(sidebar(conf=conf))
1560 1575
1561 1576 messages.success(
1562 1577 request, "Parameters imported from: '%s'." % request.FILES['file'].name)
1563 1578
1564 1579 return render(request, '%s_conf_edit.html' % conf.device.device_type.name, kwargs)
1565 1580
1566 1581 messages.error(request, "Could not import parameters from file")
1567 1582
1568 1583 kwargs = {}
1569 1584 kwargs['id_dev'] = conf.id
1570 1585 kwargs['title'] = 'Device Configuration'
1571 1586 kwargs['form'] = file_form
1572 1587 kwargs['suptitle'] = 'Importing file'
1573 1588 kwargs['button'] = 'Import'
1574 1589 kwargs['menu_configurations'] = 'active'
1575 1590
1576 1591 kwargs.update(sidebar(conf=conf))
1577 1592
1578 1593 return render(request, 'dev_conf_import.html', kwargs)
1579 1594
1580 1595
1581 1596 @login_required
1582 1597 def dev_conf_export(request, id_conf):
1583 1598
1584 1599 conf = get_object_or_404(Configuration, pk=id_conf)
1585 1600
1586 1601 if request.method == 'GET':
1587 1602 file_form = DownloadFileForm(conf.device.device_type.name)
1588 1603
1589 1604 if request.method == 'POST':
1590 1605 file_form = DownloadFileForm(
1591 1606 conf.device.device_type.name, request.POST)
1592 1607
1593 1608 if file_form.is_valid():
1594 1609 fields = conf.export_to_file(
1595 1610 format=file_form.cleaned_data['format'])
1596 1611 if not fields['content']:
1597 1612 messages.error(request, conf.message)
1598 1613 return redirect(conf.get_absolute_url_export())
1599 1614 response = HttpResponse(content_type=fields['content_type'])
1600 1615 response['Content-Disposition'] = 'attachment; filename="%s"' % fields['filename']
1601 1616 response.write(fields['content'])
1602 1617
1603 1618 return response
1604 1619
1605 1620 messages.error(request, "Could not export parameters")
1606 1621
1607 1622 kwargs = {}
1608 1623 kwargs['id_dev'] = conf.id
1609 1624 kwargs['title'] = 'Device Configuration'
1610 1625 kwargs['form'] = file_form
1611 1626 kwargs['suptitle'] = 'Exporting file'
1612 1627 kwargs['button'] = 'Export'
1613 1628 kwargs['menu_configurations'] = 'active'
1614 1629
1615 1630 return render(request, 'dev_conf_export.html', kwargs)
1616 1631
1617 1632
1618 1633 @login_required
1619 1634 def dev_conf_delete(request, id_conf):
1620 1635
1621 1636 conf = get_object_or_404(Configuration, pk=id_conf)
1622 1637
1623 1638 if request.method == 'POST':
1624 1639 if is_developer(request.user):
1625 1640 conf.delete()
1626 1641 return redirect('url_dev_confs')
1627 1642
1628 1643 messages.error(request, 'Not enough permission to delete this object')
1629 1644 return redirect(conf.get_absolute_url())
1630 1645
1631 1646 kwargs = {
1632 1647 'title': 'Delete',
1633 1648 'suptitle': 'Configuration',
1634 1649 'object': conf,
1635 1650 'delete': True
1636 1651 }
1637 1652 kwargs['menu_configurations'] = 'active'
1638 1653
1639 1654 return render(request, 'confirm.html', kwargs)
1640 1655
1641 1656
1642 1657 def sidebar(**kwargs):
1643 1658
1644 1659 side_data = {}
1645 1660
1646 1661 conf = kwargs.get('conf', None)
1647 1662 experiment = kwargs.get('experiment', None)
1648 1663
1649 1664 if not experiment:
1650 1665 experiment = conf.experiment
1651 1666
1652 1667 if experiment:
1653 1668 side_data['experiment'] = experiment
1654 1669 campaign = experiment.campaign_set.all()
1655 1670 if campaign:
1656 1671 side_data['campaign'] = campaign[0]
1657 1672 experiments = campaign[0].experiments.all().order_by('name')
1658 1673 else:
1659 1674 experiments = [experiment]
1660 1675 configurations = experiment.configuration_set.filter(type=0)
1661 1676 side_data['side_experiments'] = experiments
1662 1677 side_data['side_configurations'] = configurations.order_by(
1663 1678 'device__device_type__name')
1664 1679
1665 1680 return side_data
1666 1681
1667 1682
1668 1683 def get_paginator(model, page, order, filters={}, n=8):
1669 1684
1670 1685 kwargs = {}
1671 1686 query = Q()
1672 1687 if isinstance(filters, QueryDict):
1673 1688 filters = filters.dict()
1674 1689 [filters.pop(key) for key in filters.keys() if filters[key] in ('', ' ')]
1675 1690 filters.pop('page', None)
1676 1691
1677 1692 fields = [f.name for f in model._meta.get_fields()]
1678 1693
1679 1694 if 'template' in filters:
1680 1695 filters['template'] = True
1681 1696 if 'historical' in filters:
1682 1697 filters.pop('historical')
1683 1698 filters['type'] = 1
1684 1699 elif 'type' in fields:
1685 1700 filters['type'] = 0
1686 1701 if 'start_date' in filters:
1687 1702 filters['start_date__gte'] = filters.pop('start_date')
1688 1703 if 'end_date' in filters:
1689 1704 filters['start_date__lte'] = filters.pop('end_date')
1690 1705 if 'tags' in filters:
1691 1706 tags = filters.pop('tags')
1692 1707 if 'tags' in fields:
1693 1708 query = query | Q(tags__icontains=tags)
1694 1709 if 'label' in fields:
1695 1710 query = query | Q(label__icontains=tags)
1696 1711 if 'location' in fields:
1697 1712 query = query | Q(location__name__icontains=tags)
1698 1713 if 'device' in fields:
1699 1714 query = query | Q(device__device_type__name__icontains=tags)
1700 1715 query = query | Q(device__location__name__icontains=tags)
1701 1716 if 'device_type' in fields:
1702 1717 query = query | Q(device_type__name__icontains=tags)
1703 1718
1704 1719 if 'mine' in filters:
1705 1720 filters['author_id'] = filters['mine']
1706 1721 filters.pop('mine')
1707 1722 object_list = model.objects.filter(query, **filters).order_by(*order)
1708 1723 paginator = Paginator(object_list, n)
1709 1724
1710 1725 try:
1711 1726 objects = paginator.page(page)
1712 1727 except PageNotAnInteger:
1713 1728 objects = paginator.page(1)
1714 1729 except EmptyPage:
1715 1730 objects = paginator.page(paginator.num_pages)
1716 1731
1717 1732 kwargs['objects'] = objects
1718 1733 kwargs['offset'] = (int(page)-1)*n if page else 0
1719 1734
1720 1735 return kwargs
1721 1736
1722 1737
1723 1738 def operation(request, id_camp=None):
1724 1739
1725 1740 kwargs = {}
1726 1741 kwargs['title'] = 'Radars Operation'
1727 1742 kwargs['no_sidebar'] = True
1728 1743 kwargs['menu_operation'] = 'active'
1729 1744 campaigns = Campaign.objects.filter(start_date__lte=datetime.now(),
1730 1745 end_date__gte=datetime.now()).order_by('-start_date')
1731 1746
1732 1747 if id_camp:
1733 1748 campaign = get_object_or_404(Campaign, pk=id_camp)
1734 1749 form = OperationForm(
1735 1750 initial={'campaign': campaign.id}, campaigns=campaigns)
1736 1751 kwargs['campaign'] = campaign
1737 1752 else:
1738 1753 # form = OperationForm(campaigns=campaigns)
1739 1754 kwargs['campaigns'] = campaigns
1740 1755 return render(request, 'operation.html', kwargs)
1741 1756
1742 1757 #---Experiment
1743 1758 keys = ['id', 'name', 'start_time', 'end_time', 'status']
1744 1759 kwargs['experiment_keys'] = keys[1:]
1745 1760 kwargs['experiments'] = experiments
1746 1761 #---Radar
1747 1762 kwargs['locations'] = campaign.get_experiments_by_radar()
1748 1763 kwargs['form'] = form
1749 1764
1750 1765 return render(request, 'operation.html', kwargs)
1751 1766
1752 1767
1753 1768 @login_required
1754 1769 def radar_start(request, id_camp, id_radar):
1755 1770
1756 1771 campaign = get_object_or_404(Campaign, pk=id_camp)
1757 1772 experiments = campaign.get_experiments_by_radar(id_radar)[0]['experiments']
1758 1773 now = datetime.now()
1759 1774 for exp in experiments:
1760 1775 start = datetime.combine(datetime.now().date(), exp.start_time)
1761 1776 end = datetime.combine(datetime.now().date(), exp.end_time)
1762 1777 if end < start:
1763 1778 end += timedelta(1)
1764 1779
1765 1780 if exp.status == 2:
1766 1781 messages.warning(
1767 1782 request, 'Experiment {} already running'.format(exp))
1768 1783 continue
1769 1784
1770 1785 if exp.status == 3:
1771 1786 messages.warning(
1772 1787 request, 'Experiment {} already programmed'.format(exp))
1773 1788 continue
1774 1789
1775 1790 if start > campaign.end_date or start < campaign.start_date:
1776 1791 messages.warning(request, 'Experiment {} out of date'.format(exp))
1777 1792 continue
1778 1793
1779 1794 if now > start and now <= end:
1780 1795 exp.status = 3
1781 1796 exp.save()
1782 1797 task = task_start.delay(exp.id)
1783 1798 exp.status = task.wait()
1784 1799 if exp.status == 0:
1785 1800 messages.error(request, 'Experiment {} not start'.format(exp))
1786 1801 if exp.status == 2:
1787 1802 messages.success(request, 'Experiment {} started'.format(exp))
1788 1803 else:
1789 1804 task = task_start.apply_async(
1790 1805 (exp.pk, ), eta=start+timedelta(hours=5))
1791 1806 exp.task = task.id
1792 1807 exp.status = 3
1793 1808 messages.success(
1794 1809 request, 'Experiment {} programmed to start at {}'.format(exp, start))
1795 1810
1796 1811 exp.save()
1797 1812
1798 1813 return HttpResponseRedirect(reverse('url_operation', args=[id_camp]))
1799 1814
1800 1815
1801 1816 @login_required
1802 1817 def radar_stop(request, id_camp, id_radar):
1803 1818
1804 1819 campaign = get_object_or_404(Campaign, pk=id_camp)
1805 1820 experiments = campaign.get_experiments_by_radar(id_radar)[0]['experiments']
1806 1821
1807 1822 for exp in experiments:
1808 1823
1809 1824 if exp.task:
1810 1825 app.control.revoke(exp.task)
1811 1826 if exp.status == 2:
1812 1827 exp.stop()
1813 1828 messages.warning(request, 'Experiment {} stopped'.format(exp))
1814 1829 exp.status = 1
1815 1830 exp.save()
1816 1831
1817 1832 return HttpResponseRedirect(reverse('url_operation', args=[id_camp]))
1818 1833
1819 1834
1820 1835 @login_required
1821 1836 def radar_refresh(request, id_camp, id_radar):
1822 1837
1823 1838 campaign = get_object_or_404(Campaign, pk=id_camp)
1824 1839 experiments = campaign.get_experiments_by_radar(id_radar)[0]['experiments']
1825 1840
1826 1841 for exp in experiments:
1827 1842 exp.get_status()
1828 1843
1829 1844 return HttpResponseRedirect(reverse('url_operation', args=[id_camp]))
1830 1845
1831 1846
1832 1847 def real_time(request):
1833 1848
1834 1849 graphic_path = "/home/fiorella/Pictures/catwbeanie.jpg"
1835 1850
1836 1851 kwargs = {}
1837 1852 kwargs['title'] = 'CLAIRE'
1838 1853 kwargs['suptitle'] = 'Real Time'
1839 1854 kwargs['no_sidebar'] = True
1840 1855 kwargs['graphic_path'] = graphic_path
1841 1856 kwargs['graphic1_path'] = 'http://www.bluemaize.net/im/girls-accessories/shark-beanie-11.jpg'
1842 1857
1843 1858 return render(request, 'real_time.html', kwargs)
1844 1859
1845 1860 def theme(request, theme):
1846 1861
1847 1862 user = request.user
1848 1863 user.profile.theme = theme
1849 1864 user.save()
1850 1865 return redirect('index') No newline at end of file
General Comments 0
You need to be logged in to leave comments. Login now