##// END OF EJS Templates
Check for active configuration for status update
Juan C. Espinoza -
r329:7d210f98eba4
parent child
Show More
@@ -1,879 +1,877
1 1 from django.db import models
2 2 from apps.main.models import Configuration, User
3 3 from django.core.urlresolvers import reverse
4 4 from celery.execute import send_task
5 5 from datetime import datetime
6 6 import ast
7 7 import socket
8 8 import json
9 9 import requests
10 10 import struct
11 11 import os, sys, time
12 12
13 13 antenna_default = json.dumps({
14 14 "antenna_up": [[0.0,0.0,0.0,0.0,0.5,0.5,0.5,0.5],
15 15 [0.0,0.0,0.0,0.0,0.5,0.5,0.5,0.5],
16 16 [0.0,0.0,0.0,0.0,0.5,0.5,0.5,0.5],
17 17 [0.0,0.0,0.0,0.0,0.5,0.5,0.5,0.5],
18 18 [0.5,0.5,0.5,0.5,1.0,1.0,1.0,1.0],
19 19 [0.5,0.5,0.5,0.5,1.0,1.0,1.0,1.0],
20 20 [0.5,0.5,0.5,0.5,1.0,1.0,1.0,1.0],
21 21 [0.5,0.5,0.5,0.5,1.0,1.0,1.0,1.0]
22 22 ]
23 23 ,
24 24 "antenna_down": [[0.0,0.0,0.0,0.0,0.5,0.5,0.5,0.5],
25 25 [0.0,0.0,0.0,0.0,0.5,0.5,0.5,0.5],
26 26 [0.0,0.0,0.0,0.0,0.5,0.5,0.5,0.5],
27 27 [0.0,0.0,0.0,0.0,0.5,0.5,0.5,0.5],
28 28 [0.5,0.5,0.5,0.5,3.0,3.0,3.0,3.0],
29 29 [0.5,0.5,0.5,0.5,3.0,3.0,3.0,3.0],
30 30 [0.5,0.5,0.5,0.5,3.0,3.0,3.0,3.0],
31 31 [0.5,0.5,0.5,0.5,3.0,3.0,3.0,3.0]],
32 32 })
33 33
34 34
35 35 tx_default = json.dumps({
36 36 "up": [[1,1,1,1,0,0,0,0],
37 37 [1,1,1,1,0,0,0,0],
38 38 [1,1,1,1,0,0,0,0],
39 39 [1,1,1,1,0,0,0,0],
40 40 [0,0,0,0,1,1,1,1],
41 41 [0,0,0,0,1,1,1,1],
42 42 [0,0,0,0,1,1,1,1],
43 43 [0,0,0,0,1,1,1,1]],
44 44
45 45 "down": [[1,1,1,1,0,0,0,0],
46 46 [1,1,1,1,0,0,0,0],
47 47 [1,1,1,1,0,0,0,0],
48 48 [1,1,1,1,0,0,0,0],
49 49 [0,0,0,0,1,1,1,1],
50 50 [0,0,0,0,1,1,1,1],
51 51 [0,0,0,0,1,1,1,1],
52 52 [0,0,0,0,1,1,1,1]],
53 53 })
54 54
55 55 rx_default = json.dumps({
56 56 "up": [[1,1,1,1,0,0,0,0],
57 57 [1,1,1,1,0,0,0,0],
58 58 [1,1,1,1,0,0,0,0],
59 59 [1,1,1,1,0,0,0,0],
60 60 [0,0,0,0,1,1,1,1],
61 61 [0,0,0,0,1,1,1,1],
62 62 [0,0,0,0,1,1,1,1],
63 63 [0,0,0,0,1,1,1,1]],
64 64
65 65 "down": [[1,1,1,1,0,0,0,0],
66 66 [1,1,1,1,0,0,0,0],
67 67 [1,1,1,1,0,0,0,0],
68 68 [1,1,1,1,0,0,0,0],
69 69 [0,0,0,0,1,1,1,1],
70 70 [0,0,0,0,1,1,1,1],
71 71 [0,0,0,0,1,1,1,1],
72 72 [0,0,0,0,1,1,1,1]],
73 73 })
74 74
75 75 status_default = '0000000000000000000000000000000000000000000000000000000000000000'
76 76 default_messages = {}
77 77
78 78 for i in range(1,65):
79 79 default_messages[str(i)] = "Module "+str(i)
80 80
81 81
82 82 ues_default = json.dumps({
83 83 "up": [0.533333,0.00000,1.06667,0.00000],
84 84 "down": [0.533333,0.00000,1.06667,0.00000]
85 85 })
86 86
87 87 onlyrx_default = json.dumps({
88 88 "up": False,
89 89 "down": False
90 90 })
91 91
92 92 def up_convertion(cadena):
93 93 valores = []
94 94 for c in cadena:
95 95 if c == 1.0: valores=valores+['000']
96 96 if c == 2.0: valores=valores+['001']
97 97 if c == 3.0: valores=valores+['010']
98 98 if c == 0.0: valores=valores+['011']
99 99 if c == 0.5: valores=valores+['100']
100 100 if c == 1.5: valores=valores+['101']
101 101 if c == 2.5: valores=valores+['110']
102 102 if c == 3.5: valores=valores+['111']
103 103
104 104 return valores
105 105
106 106 def up_conv_bits(value):
107 107
108 108 if value == 1.0: bits="000"
109 109 if value == 2.0: bits="001"
110 110 if value == 3.0: bits="010"
111 111 if value == 0.0: bits="011"
112 112 if value == 0.5: bits="100"
113 113 if value == 1.5: bits="101"
114 114 if value == 2.5: bits="110"
115 115 if value == 3.5: bits="111"
116 116
117 117 return bits
118 118
119 119 def down_convertion(cadena):
120 120 valores = []
121 121 for c in cadena:
122 122 if c == 1.0: valores=valores+['000']
123 123 if c == 2.0: valores=valores+['001']
124 124 if c == 3.0: valores=valores+['010']
125 125 if c == 0.0: valores=valores+['011']
126 126 if c == 0.5: valores=valores+['100']
127 127 if c == 1.5: valores=valores+['101']
128 128 if c == 2.5: valores=valores+['110']
129 129 if c == 3.5: valores=valores+['111']
130 130
131 131 return valores
132 132
133 133 def down_conv_bits(value):
134 134
135 135 if value == 1.0: bits="000"
136 136 if value == 2.0: bits="001"
137 137 if value == 3.0: bits="010"
138 138 if value == 0.0: bits="011"
139 139 if value == 0.5: bits="100"
140 140 if value == 1.5: bits="101"
141 141 if value == 2.5: bits="110"
142 142 if value == 3.5: bits="111"
143 143
144 144 return bits
145 145
146 146 def up_conv_value(bits):
147 147
148 148 if bits == "000": value=1.0
149 149 if bits == "001": value=2.0
150 150 if bits == "010": value=3.0
151 151 if bits == "011": value=0.0
152 152 if bits == "100": value=0.5
153 153 if bits == "101": value=1.5
154 154 if bits == "110": value=2.5
155 155 if bits == "111": value=3.5
156 156
157 157 return value
158 158
159 159 def down_conv_value(bits):
160 160
161 161 if bits == "000": value=1.0
162 162 if bits == "001": value=2.0
163 163 if bits == "010": value=3.0
164 164 if bits == "011": value=0.0
165 165 if bits == "100": value=0.5
166 166 if bits == "101": value=1.5
167 167 if bits == "110": value=2.5
168 168 if bits == "111": value=3.5
169 169
170 170 return value
171 171
172 172 def ip2position(module_number):
173 173 j=0
174 174 i=0
175 175 for x in range(0,module_number-1):
176 176 j=j+1
177 177 if j==8:
178 178 i=i+1
179 179 j=0
180 180
181 181 pos = [i,j]
182 182 return pos
183 183
184 184
185 185 def fromBinary2Char(binary_string):
186 186 number = int(binary_string, 2)
187 187 #Plus 33 to avoid more than 1 characters values such as: '\x01'-'\x1f'
188 188 number = number + 33
189 189 char = chr(number)
190 190 return char
191 191
192 192 def fromChar2Binary(char):
193 193 number = ord(char) - 33
194 194 #Minus 33 to get the real value
195 195 bits = bin(number)[2:]
196 196 #To ensure we have a string with 6bits
197 197 if len(bits) < 6:
198 198 bits = bits.zfill(6)
199 199 return bits
200 200
201 201 OPERATION_MODES = (
202 202 (0, 'Manual'),
203 203 (1, 'Automatic'),
204 204 )
205 205
206 206
207 207 class ABSConfiguration(Configuration):
208 208 active_beam = models.PositiveSmallIntegerField(verbose_name='Active Beam', default=0)
209 209 module_status = models.CharField(verbose_name='Module Status', max_length=10000, default=status_default)
210 210 operation_mode = models.PositiveSmallIntegerField(verbose_name='Operation Mode', choices=OPERATION_MODES, default = 0)
211 211 operation_value = models.FloatField(verbose_name='Periodic (seconds)', default="10", null=True, blank=True)
212 212 module_messages = models.CharField(verbose_name='Modules Messages', max_length=10000, default=json.dumps(default_messages))
213 213
214 214 class Meta:
215 215 db_table = 'abs_configurations'
216 216
217 217 def get_absolute_url_plot(self):
218 218 return reverse('url_plot_abs_patterns', args=[str(self.id)])
219 219
220 220
221 221 def parms_to_dict(self):
222 222
223 223 parameters = {}
224 224
225 225 parameters['device_id'] = self.device.id
226 226 parameters['label'] = self.label
227 227 parameters['device_type'] = self.device.device_type.name
228 228 parameters['beams'] = {}
229 229
230 230 beams = ABSBeam.objects.filter(abs_conf=self)
231 231 b=1
232 232 for beam in beams:
233 233 #absbeam = ABSBeam.objects.get(pk=beams[beam])
234 234 parameters['beams']['beam'+str(b)] = beam.parms_to_dict()#absbeam.parms_to_dict()
235 235 b+=1
236 236
237 237 return parameters
238 238
239 239
240 240 def dict_to_parms(self, parameters):
241 241
242 242 self.label = parameters['label']
243 243
244 244 absbeams = ABSBeam.objects.filter(abs_conf=self)
245 245 beams = parameters['beams']
246 246
247 247 if absbeams:
248 248 beams_number = len(beams)
249 249 absbeams_number = len(absbeams)
250 250 if beams_number==absbeams_number:
251 251 i = 1
252 252 for absbeam in absbeams:
253 253 absbeam.dict_to_parms(beams['beam'+str(i)])
254 254 i = i+1
255 255 elif beams_number > absbeams_number:
256 256 i = 1
257 257 for absbeam in absbeams:
258 258 absbeam.dict_to_parms(beams['beam'+str(i)])
259 259 i=i+1
260 260 for x in range(i,beams_number+1):
261 261 new_beam = ABSBeam(
262 262 name =beams['beam'+str(i)]['name'],
263 263 antenna =json.dumps(beams['beam'+str(i)]['antenna']),
264 264 abs_conf = self,
265 265 tx =json.dumps(beams['beam'+str(i)]['tx']),
266 266 rx =json.dumps(beams['beam'+str(i)]['rx']),
267 267 ues =json.dumps(beams['beam'+str(i)]['ues']),
268 268 only_rx =json.dumps(beams['beam'+str(i)]['only_rx'])
269 269 )
270 270 new_beam.save()
271 271 i=i+1
272 272 else: #beams_number < absbeams_number:
273 273 i = 1
274 274 for absbeam in absbeams:
275 275 if i <= beams_number:
276 276 absbeam.dict_to_parms(beams['beam'+str(i)])
277 277 i=i+1
278 278 else:
279 279 absbeam.delete()
280 280 else:
281 281 for beam in beams:
282 282 new_beam = ABSBeam(
283 283 name =beams[beam]['name'],
284 284 antenna =json.dumps(beams[beam]['antenna']),
285 285 abs_conf = self,
286 286 tx =json.dumps(beams[beam]['tx']),
287 287 rx =json.dumps(beams[beam]['rx']),
288 288 ues =json.dumps(beams[beam]['ues']),
289 289 only_rx =json.dumps(beams[beam]['only_rx'])
290 290 )
291 291 new_beam.save()
292 292
293 293
294 294
295 295 def update_from_file(self, parameters):
296 296
297 297 self.dict_to_parms(parameters)
298 298 self.save()
299 299
300 300
301 301 def get_beams(self, **kwargs):
302 302 '''
303 303 This function returns ABS Configuration beams
304 304 '''
305 305 return ABSBeam.objects.filter(abs_conf=self.pk, **kwargs)
306 306
307 307 def clone(self, **kwargs):
308 308
309 309 beams = self.get_beams()
310 310 self.pk = None
311 311 self.id = None
312 312 for attr, value in kwargs.items():
313 313 setattr(self, attr, value)
314 314 self.save()
315 315
316 316 for beam in beams:
317 317 beam.clone(abs_conf=self)
318 318
319 319 #-----For Active Beam-----
320 320 new_beams = ABSBeam.objects.filter(abs_conf=self)
321 321 self.active_beam = new_beams[0].id
322 322 self.save()
323 323 #-----For Active Beam-----
324 324 #-----For Device Status---
325 325 self.device.status = 3
326 326 self.device.save()
327 327 #-----For Device Status---
328 328
329 329 return self
330 330
331 331
332 332 def start_device(self):
333 333
334 334 if self.device.status == 3:
335 335
336 336 try:
337 337 #self.write_device()
338 338 send_task('task_change_beam', [self.id],)
339 339 self.message = 'ABS running'
340 340
341 341 except Exception as e:
342 342 self.message = str(e)
343 343 return False
344 344
345 345 return True
346 346
347 347 else:
348 348 self.message = 'Please, select Write ABS Device first.'
349 349 return False
350 350
351 351
352 352 def stop_device(self):
353 353
354 354 self.device.status = 2
355 355 self.device.save()
356 356 self.message = 'ABS has been stopped.'
357 357 self.save()
358 358
359 359 return True
360 360
361 361
362 362 def write_device(self):
363 363
364 364 """
365 365 This function sends the beams list to every abs module.
366 366 It needs 'module_conf' function
367 367 """
368 368
369 369 beams = ABSBeam.objects.filter(abs_conf=self)
370 370 nbeams = len(beams)
371 371 if self.connected_modules() == 0 :
372 372 self.message = "No ABS Module detected."
373 373 return False
374 374
375 375 #-------------Write each abs module-----------
376 376
377 377 if beams:
378 378 block_id = 0
379 379 message = 'SNDF{:03d}{:02d}{:02d}'.format(nbeams, nbeams, block_id)
380 380 for i, status in enumerate(self.module_status):
381 381 message += ''.join([fromBinary2Char(beam.module_6bits(i)) for beam in beams])
382 382 status = ['0'] * 64
383 383 n = 0
384 384
385 385 sock = self.send_multicast(message)
386 386
387 387 for i in range(32):
388 388 try:
389 389 data, address = sock.recvfrom(1024)
390 390 print address, data
391 391 if data == '1':
392 392 status[int(address[0][10:])-1] = '3'
393 393 elif data == '0':
394 394 status[int(address[0][10:])-1] = '1'
395 395 except Exception as e:
396 396 print 'Error {}'.format(e)
397 397 n += 1
398 398 sock.close()
399 399 else:
400 400 self.message = "ABS Configuration does not have beams"
401 401 return False
402 402
403 403 if n == 64:
404 404 self.message = "Could not write ABS Modules"
405 405 self.device.status = 0
406 406 self.module_status = ''.join(status)
407 407 self.save()
408 408 return False
409 409 else:
410 410 self.message = "ABS Beams List have been sent to ABS Modules"
411 411 self.active_beam = beams[0].pk
412 412
413 413 self.device.status = 3
414 414 self.module_status = ''.join(status)
415 415 self.save()
416 for u in User.objects.all():
417 u.profile.abs_active = self
418 u.save()
416
419 417 return True
420 418
421 419
422 420 def read_module(self, module):
423 421
424 422 """
425 423 Read out-bits (up-down) of 1 abs module NOT for Configuration
426 424 """
427 425
428 426 ip_address = self.device.ip_address
429 427 ip_address = ip_address.split('.')
430 428 module_seq = (ip_address[0],ip_address[1],ip_address[2])
431 429 dot = '.'
432 430 module_ip = dot.join(module_seq)+'.'+str(module)
433 431 module_port = self.device.port_address
434 432 read_route = 'http://'+module_ip+':'+str(module_port)+'/read'
435 433
436 434 module_status = json.loads(self.module_status)
437 435 print(read_route)
438 436
439 437 module_bits = ''
440 438
441 439 try:
442 440 r_read = requests.get(read_route, timeout=0.5)
443 441 answer = r_read.json()
444 442 module_bits = answer['allbits']
445 443 except:
446 444 return {}
447 445
448 446 return module_bits
449 447
450 448 def read_device(self):
451 449
452 450 parms = {}
453 451 # Reads active modules.
454 452 module_status = json.loads(self.module_status)
455 453 total = 0
456 454 for status in module_status:
457 455 if module_status[status] != 0:
458 456 module_bits = self.read_module(int(status))
459 457 bits={}
460 458 if module_bits:
461 459 bits = (str(module_bits['um2']) + str(module_bits['um1']) + str(module_bits['um0']) +
462 460 str(module_bits['dm2']) + str(module_bits['dm1']) + str(module_bits['dm0']) )
463 461 parms[str(status)] = bits
464 462
465 463 total +=1
466 464
467 465 if total==0:
468 466 self.message = "No ABS Module detected. Please select 'Status'."
469 467 return False
470 468
471 469
472 470
473 471 self.message = "ABS Modules have been read"
474 472 #monitoreo_tx = JROABSClnt_01CeCnMod000000MNTR10
475 473 return parms
476 474
477 475
478 476 def connected_modules(self):
479 477 """
480 478 This function returns the number of connected abs-modules without updating.
481 479 """
482 480 num = 0
483 481 print(self.module_status)
484 482 for i, status in enumerate(self.module_status):
485 483 if status != '0':
486 484 num += 1
487 485 #print('status {}:{}'.format(i+1, status))
488 486 return num
489 487
490 488 def send_multicast(self, message):
491 489
492 490 multicast_group = ('224.3.29.71', 10000)
493 491 # Create the datagram socket
494 492 sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
495 493 sock.settimeout(1)
496 494 local_ip = os.environ.get('LOCAL_IP', '127.0.0.1')
497 495 sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_IF, socket.inet_aton(local_ip))
498 496 sock.sendto(message, multicast_group)
499 497 print('Sending ' + message)
500 498 return sock
501 499
502 500 def status_device(self):
503 501 """
504 502 This function returns the status of all abs-modules as one.
505 503 If at least one module is connected, its answer is "1"
506 504 """
507 505
508 506 sock = self.send_multicast('MNTR')
509 507
510 508 n = 0
511 509 status = ['0'] * 64
512 510 for i in range(32):
513 511 #if True:
514 512 try:
515 513 address = None
516 514 data, address = sock.recvfrom(1024)
517 515 x = int(address[0][10:])-1
518 516 if data[0] == '1':
519 517 remote = fromChar2Binary(data[1])
520 518 local = ABSBeam.objects.get(pk=self.active_beam).module_6bits(x)
521 519 if local == remote:
522 520 status[x] = '3'
523 521 print('Module: {} connected...igual'.format(address))
524 522 else:
525 523 status[x] = '2'
526 524 print('Module: {} connected...diferente'.format(address))
527 525 elif data[0] == '0':
528 526 status[x] = '1'
529 527 n += 1
530 528 except:
531 529 print('Module: {} error'.format(address))
532 530 pass
533 531 sock.close()
534 532
535 533 if n > 0:
536 534 self.message = 'ABS modules Status have been updated.'
537 535 self.device.status = 1
538 536 else:
539 537 self.device.status = 0
540 538 self.message = 'No ABS module is connected.'
541 539 self.module_status = ''.join(status)
542 540 self.save()
543 541
544 542 return self.device.status
545 543
546 544
547 545 def send_beam(self, beam_pos):
548 546 """
549 547 This function connects to a multicast group and sends the beam number
550 548 to all abs modules.
551 549 """
552 550
553 551 # Se manda a cero RC para poder realizar cambio de beam
554 552 if self.experiment is None:
555 553 confs = []
556 554 else:
557 555 confs = Configuration.objects.filter(experiment = self.experiment).filter(type=0)
558 556 confdds = ''
559 557 confjars = ''
560 558 confrc = ''
561 559 #TO STOP DEVICES: DDS-JARS-RC
562 560 for i in range(0,len(confs)):
563 561 if i==0:
564 562 for conf in confs:
565 563 if conf.device.device_type.name == 'dds':
566 564 confdds = conf
567 565 confdds.stop_device()
568 566 break
569 567 if i==1:
570 568 for conf in confs:
571 569 if conf.device.device_type.name == 'jars':
572 570 confjars = conf
573 571 confjars.stop_device()
574 572 break
575 573 if i==2:
576 574 for conf in confs:
577 575 if conf.device.device_type.name == 'rc':
578 576 confrc = conf
579 577 confrc.stop_device()
580 578 break
581 579 if beam_pos > 0:
582 580 beam_pos = beam_pos - 1
583 581 else:
584 582 beam_pos = 0
585 583
586 584 #El indice del apunte debe ser menor que el numero total de apuntes
587 585 #El servidor tcp en el embebido comienza a contar desde 0
588 586 status = ['0'] * 64
589 587 message = 'CHGB{}'.format(beam_pos)
590 588 sock = self.send_multicast(message)
591 589 for i in range(32):
592 590 try:
593 591 data, address = sock.recvfrom(1024)
594 592 print address, data
595 593 if data == '1':
596 594 status[int(address[0][10:])-1] = '3'
597 595 elif data == '0':
598 596 status[int(address[0][10:])-1] = '1'
599 597 except Exception as e:
600 598 print 'Error {}'.format(e)
601 599 pass
602 600
603 601 sock.close()
604 602
605 603 #Start DDS-RC-JARS
606 604 if confdds:
607 605 confdds.start_device()
608 606 if confrc:
609 607 #print confrc
610 608 confrc.start_device()
611 609 if confjars:
612 610 confjars.start_device()
613 611
614 612 self.message = "ABS Beam has been changed"
615 613 self.module_status = ''.join(status)
616 614 self.save()
617 615 return True
618 616
619 617
620 618 def get_absolute_url_import(self):
621 619 return reverse('url_import_abs_conf', args=[str(self.id)])
622 620
623 621
624 622 class ABSBeam(models.Model):
625 623
626 624 name = models.CharField(max_length=60, default='Beam')
627 625 antenna = models.CharField(verbose_name='Antenna', max_length=1000, default=antenna_default)
628 626 abs_conf = models.ForeignKey(ABSConfiguration, null=True, verbose_name='ABS Configuration')
629 627 tx = models.CharField(verbose_name='Tx', max_length=1000, default=tx_default)
630 628 rx = models.CharField(verbose_name='Rx', max_length=1000, default=rx_default)
631 629 s_time = models.TimeField(verbose_name='Star Time', default='00:00:00')
632 630 e_time = models.TimeField(verbose_name='End Time', default='23:59:59')
633 631 ues = models.CharField(verbose_name='Ues', max_length=100, default=ues_default)
634 632 only_rx = models.CharField(verbose_name='Only RX', max_length=40, default=onlyrx_default)
635 633
636 634 class Meta:
637 635 db_table = 'abs_beams'
638 636
639 637 def __unicode__(self):
640 638 return u'%s' % (self.name)
641 639
642 640 def parms_to_dict(self):
643 641
644 642 parameters = {}
645 643 parameters['name'] = self.name
646 644 parameters['antenna'] = ast.literal_eval(self.antenna)
647 645 parameters['abs_conf'] = self.abs_conf.name
648 646 parameters['tx'] = ast.literal_eval(self.tx)
649 647 parameters['rx'] = ast.literal_eval(self.rx)
650 648 parameters['s_time'] = self.s_time.strftime("%H:%M:%S")
651 649 parameters['e_time'] = self.e_time.strftime("%H:%M:%S")
652 650 parameters['ues'] = ast.literal_eval(self.ues)
653 651 parameters['only_rx'] = json.loads(self.only_rx)
654 652
655 653 return parameters
656 654
657 655 def dict_to_parms(self, parameters):
658 656
659 657 self.name = parameters['name']
660 658 self.antenna = json.dumps(parameters['antenna'])
661 659 #self.abs_conf = parameters['abs_conf']
662 660 self.tx = json.dumps(parameters['tx'])
663 661 self.rx = json.dumps(parameters['rx'])
664 662 #self.s_time = parameters['s_time']
665 663 #self.e_time = parameters['e_time']
666 664 self.ues = json.dumps(parameters['ues'])
667 665 self.only_rx = json.dumps(parameters['only_rx'])
668 666 self.save()
669 667
670 668
671 669 def clone(self, **kwargs):
672 670
673 671 self.pk = None
674 672 self.id = None
675 673 for attr, value in kwargs.items():
676 674 setattr(self, attr, value)
677 675
678 676 self.save()
679 677
680 678 return self
681 679
682 680
683 681 def module_6bits(self, module):
684 682 """
685 683 This function reads antenna pattern and choose 6bits (upbits-downbits) for one abs module
686 684 """
687 685 module += 1
688 686 if module > 64:
689 687 beam_bits = ""
690 688 return beam_bits
691 689
692 690 data = ast.literal_eval(self.antenna)
693 691 up_data = data['antenna_up']
694 692 down_data = data['antenna_down']
695 693
696 694 pos = ip2position(module)
697 695 up_value = up_data[pos[0]][pos[1]]
698 696 down_value = down_data[pos[0]][pos[1]]
699 697
700 698 up_bits = up_conv_bits(up_value)
701 699 down_bits = down_conv_bits(down_value)
702 700 beam_bits = up_bits+down_bits
703 701
704 702 return beam_bits
705 703
706 704
707 705 @property
708 706 def get_upvalues(self):
709 707 """
710 708 This function reads antenna pattern and show the up-value of one abs module
711 709 """
712 710
713 711 data = ast.literal_eval(self.antenna)
714 712 up_data = data['antenna_up']
715 713
716 714 up_values = []
717 715 for data in up_data:
718 716 for i in range(0,8):
719 717 up_values.append(data[i])
720 718
721 719 return up_values
722 720
723 721 @property
724 722 def antenna_upvalues(self):
725 723 """
726 724 This function reads antenna pattern and show the up - values of one abs beam
727 725 in a particular order
728 726 """
729 727 data = ast.literal_eval(self.antenna)
730 728 up_data = data['antenna_up']
731 729
732 730 return up_data
733 731
734 732 @property
735 733 def antenna_downvalues(self):
736 734 """
737 735 This function reads antenna pattern and show the down - values of one abs beam
738 736 in a particular order
739 737 """
740 738 data = ast.literal_eval(self.antenna)
741 739 down_data = data['antenna_down']
742 740
743 741 return down_data
744 742
745 743 @property
746 744 def get_downvalues(self):
747 745 """
748 746 This function reads antenna pattern and show the down-value of one abs module
749 747 """
750 748
751 749 data = ast.literal_eval(self.antenna)
752 750 down_data = data['antenna_down']
753 751
754 752 down_values = []
755 753 for data in down_data:
756 754 for i in range(0,8):
757 755 down_values.append(data[i])
758 756
759 757 return down_values
760 758
761 759 @property
762 760 def get_up_ues(self):
763 761 """
764 762 This function shows the up-ues-value of one beam
765 763 """
766 764 data = ast.literal_eval(self.ues)
767 765 up_ues = data['up']
768 766
769 767 return up_ues
770 768
771 769 @property
772 770 def get_down_ues(self):
773 771 """
774 772 This function shows the down-ues-value of one beam
775 773 """
776 774 data = ast.literal_eval(self.ues)
777 775 down_ues = data['down']
778 776
779 777 return down_ues
780 778
781 779 @property
782 780 def get_up_onlyrx(self):
783 781 """
784 782 This function shows the up-onlyrx-value of one beam
785 783 """
786 784 data = json.loads(self.only_rx)
787 785 up_onlyrx = data['up']
788 786
789 787 return up_onlyrx
790 788
791 789 @property
792 790 def get_down_onlyrx(self):
793 791 """
794 792 This function shows the down-onlyrx-value of one beam
795 793 """
796 794 data = json.loads(self.only_rx)
797 795 down_onlyrx = data['down']
798 796
799 797 return down_onlyrx
800 798
801 799 @property
802 800 def get_tx(self):
803 801 """
804 802 This function shows the tx-values of one beam
805 803 """
806 804 data = json.loads(self.tx)
807 805
808 806 return data
809 807
810 808 @property
811 809 def get_uptx(self):
812 810 """
813 811 This function shows the up-tx-values of one beam
814 812 """
815 813 data = json.loads(self.tx)
816 814 up_data = data['up']
817 815
818 816 up_values = []
819 817 for data in up_data:
820 818 for i in range(0,8):
821 819 up_values.append(data[i])
822 820
823 821 return up_values
824 822
825 823 @property
826 824 def get_downtx(self):
827 825 """
828 826 This function shows the down-tx-values of one beam
829 827 """
830 828 data = json.loads(self.tx)
831 829 down_data = data['down']
832 830
833 831 down_values = []
834 832 for data in down_data:
835 833 for i in range(0,8):
836 834 down_values.append(data[i])
837 835
838 836 return down_values
839 837
840 838
841 839
842 840 @property
843 841 def get_rx(self):
844 842 """
845 843 This function shows the rx-values of one beam
846 844 """
847 845 data = json.loads(self.rx)
848 846
849 847 return data
850 848
851 849 @property
852 850 def get_uprx(self):
853 851 """
854 852 This function shows the up-rx-values of one beam
855 853 """
856 854 data = json.loads(self.rx)
857 855 up_data = data['up']
858 856
859 857 up_values = []
860 858 for data in up_data:
861 859 for i in range(0,8):
862 860 up_values.append(data[i])
863 861
864 862 return up_values
865 863
866 864 @property
867 865 def get_downrx(self):
868 866 """
869 867 This function shows the down-rx-values of one beam
870 868 """
871 869 data = json.loads(self.rx)
872 870 down_data = data['down']
873 871
874 872 down_values = []
875 873 for data in down_data:
876 874 for i in range(0,8):
877 875 down_values.append(data[i])
878 876
879 877 return down_values
@@ -1,433 +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 9 from django.utils.safestring import mark_safe
10 10
11 11 from datetime import datetime
12 12 from time import sleep
13 13 import os
14 14 import io
15 15
16 16 from apps.main.models import Device, Configuration, Experiment
17 17 from apps.main.views import sidebar
18 18
19 19 from .models import ABSConfiguration, ABSBeam
20 20 from .forms import ABSConfigurationForm, ABSBeamEditForm, ABSBeamAddForm, ABSImportForm
21 21
22 22 from .utils.overJroShow import overJroShow
23 23 from .utils.OverJRO import OverJRO
24 24 # Create your views here.
25 25 import json, ast
26 26
27 27
28 28 def get_values_from_form(form_data):
29 29
30 30 sublistup = []
31 31 sublistdown = []
32 32 subtxlistup = []
33 33 subtxlistdown = []
34 34 subrxlistup = []
35 35 subrxlistdown = []
36 36
37 37 up_values_list = []
38 38 down_values_list = []
39 39 up_txvalues_list = []
40 40 down_txvalues_list = []
41 41 up_rxvalues_list = []
42 42 down_rxvalues_list = []
43 43
44 44 values_list = {}
45 45 cont = 1
46 46
47 47 for i in range(1,65):
48 48 x = float(form_data['abs_up'+str(i)])
49 49 y = float(form_data['abs_down'+str(i)])
50 50 sublistup.append(x)
51 51 sublistdown.append(y)
52 52
53 53 if str(i) in form_data.getlist('uptx_checks'):
54 54 subtxlistup.append(1)
55 55 else:
56 56 subtxlistup.append(0)
57 57 if str(i) in form_data.getlist('downtx_checks'):
58 58 subtxlistdown.append(1)
59 59 else:
60 60 subtxlistdown.append(0)
61 61
62 62 if str(i) in form_data.getlist('uprx_checks'):
63 63 subrxlistup.append(1)
64 64 else:
65 65 subrxlistup.append(0)
66 66 if str(i) in form_data.getlist('downrx_checks'):
67 67 subrxlistdown.append(1)
68 68 else:
69 69 subrxlistdown.append(0)
70 70
71 71 cont = cont+1
72 72
73 73 if cont == 9:
74 74 up_values_list.append(sublistup)
75 75 down_values_list.append(sublistdown)
76 76 sublistup = []
77 77 sublistdown = []
78 78
79 79 up_txvalues_list.append(subtxlistup)
80 80 down_txvalues_list.append(subtxlistdown)
81 81 subtxlistup = []
82 82 subtxlistdown = []
83 83 up_rxvalues_list.append(subrxlistup)
84 84 down_rxvalues_list.append(subrxlistdown)
85 85 subrxlistup = []
86 86 subrxlistdown = []
87 87 cont = 1
88 88
89 89
90 90 list_uesup = []
91 91 list_uesdown = []
92 92 for i in range(1,5):
93 93 if form_data['ues_up'+str(i)] == '':
94 94 list_uesup.append(0.0)
95 95 else:
96 96 list_uesup.append(float(form_data['ues_up'+str(i)]))
97 97
98 98 if form_data['ues_down'+str(i)] == '':
99 99 list_uesdown.append(0.0)
100 100 else:
101 101 list_uesdown.append(float(form_data['ues_down'+str(i)]))
102 102
103 103 onlyrx_list = form_data.getlist('onlyrx')
104 104 only_rx = {}
105 105 if '1' in onlyrx_list:
106 106 only_rx['up'] = True
107 107 else:
108 108 only_rx['up'] = False
109 109 if '2' in onlyrx_list:
110 110 only_rx['down'] = True
111 111 else:
112 112 only_rx['down'] = False
113 113
114 114 antenna = {'antenna_up': up_values_list, 'antenna_down': down_values_list}
115 115 tx = {'up': up_txvalues_list, 'down': down_txvalues_list}
116 116 rx = {'up': up_rxvalues_list, 'down': down_rxvalues_list}
117 117 ues = {'up': list_uesup, 'down': list_uesdown}
118 118 name = str(form_data['beam_name'])
119 119
120 120 beam_data = {'name': name, 'antenna': antenna, 'tx': tx, 'rx': rx, 'ues': ues, 'only_rx': only_rx}
121 121
122 122 return beam_data
123 123
124 124
125 125 def abs_conf(request, id_conf):
126 126
127 127 conf = get_object_or_404(ABSConfiguration, pk=id_conf)
128 128 beams = ABSBeam.objects.filter(abs_conf=conf)
129 129 #------------Colors for Active Beam:-------------
130 130 all_status = {}
131 131 module_messages = json.loads(conf.module_messages)
132 132
133 133 color_status = {}
134 134 for i, status in enumerate(conf.module_status):
135 135 if status == '3': #Running background-color: #00cc00;
136 136 all_status['{}'.format(i+1)] = 2
137 137 color_status['{}'.format(i+1)] = 'class=text-success'#'bgcolor=#00cc00'
138 138 elif status == '2':
139 139 all_status['{}'.format(i+1)] = 1
140 140 color_status['{}'.format(i+1)] = 'class=text-info'
141 141 elif status == '1': #Connected background-color: #ee902c;
142 142 all_status['{}'.format(i+1)] = 1
143 143 color_status['{}'.format(i+1)] = 'class=text-warning'#'bgcolor=#ee902c'
144 144 else: #Disconnected background-color: #ff0000;
145 145 all_status['{}'.format(i+1)] = 0
146 146 color_status['{}'.format(i+1)] = 'class=text-danger'#'bgcolor=#FF0000'
147 147 #------------------------------------------------
148 148
149 149 kwargs = {}
150 150 kwargs['connected_modules'] = str(conf.connected_modules())+'/64'
151 151 kwargs['dev_conf'] = conf
152 152
153 153 if conf.operation_mode == 0:
154 154 kwargs['dev_conf_keys'] = ['label', 'operation_mode']
155 155 else:
156 156 kwargs['dev_conf_keys'] = ['label', 'operation_mode', 'operation_value']
157 157
158 158 kwargs['title'] = 'ABS Configuration'
159 159 kwargs['suptitle'] = 'Details'
160 160 kwargs['button'] = 'Edit Configuration'
161 161
162 162 if conf.active_beam != 0:
163 163 kwargs['active_beam'] = int(conf.active_beam)
164 164
165 165 kwargs['beams'] = beams
166 166 kwargs['modules_status'] = all_status
167 167 kwargs['color_status'] = color_status
168 168 kwargs['module_messages'] = module_messages
169 169 ###### SIDEBAR ######
170 170 kwargs.update(sidebar(conf=conf))
171 171
172 172 return render(request, 'abs_conf.html', kwargs)
173 173
174 174
175 175 def abs_conf_edit(request, id_conf):
176 176
177 177 conf = get_object_or_404(ABSConfiguration, pk=id_conf)
178 178
179 179 beams = ABSBeam.objects.filter(abs_conf=conf)
180 180
181 181 if request.method=='GET':
182 182 form = ABSConfigurationForm(instance=conf)
183 183
184 184 if request.method=='POST':
185 185 form = ABSConfigurationForm(request.POST, instance=conf)
186 186
187 187 if form.is_valid():
188 188 conf = form.save(commit=False)
189 189 conf.save()
190 190 return redirect('url_abs_conf', id_conf=conf.id)
191 191
192 192 ###### SIDEBAR ######
193 193 kwargs = {}
194 194
195 195 kwargs['dev_conf'] = conf
196 196 #kwargs['id_dev'] = conf.id
197 197 kwargs['id_conf'] = conf.id
198 198 kwargs['form'] = form
199 199 kwargs['abs_beams'] = beams
200 200 kwargs['title'] = 'Device Configuration'
201 201 kwargs['suptitle'] = 'Edit'
202 202 kwargs['button'] = 'Save'
203 203
204 204 kwargs['edit'] = True
205 205
206 206 return render(request, 'abs_conf_edit.html', kwargs)
207 207
208 208 @csrf_exempt
209 209 def abs_conf_alert(request):
210 210
211 211 if request.method == 'POST':
212 212 print request.POST
213 213 return HttpResponse(json.dumps({'result':1}), content_type='application/json')
214 214 else:
215 215 return redirect('index')
216 216
217 217
218 218 def import_file(request, id_conf):
219 219
220 220 conf = get_object_or_404(ABSConfiguration, pk=id_conf)
221 221 if request.method=='POST':
222 222 form = ABSImportForm(request.POST, request.FILES)
223 223 if form.is_valid():
224 224 try:
225 225 parms = conf.import_from_file(request.FILES['file_name'])
226 226
227 227 if parms:
228 228 conf.update_from_file(parms)
229 229 messages.success(request, 'Configuration "%s" loaded succesfully' % request.FILES['file_name'])
230 230 return redirect(conf.get_absolute_url_edit())
231 231
232 232 except Exception as e:
233 233 messages.error(request, 'Error parsing file: "%s" - %s' % (request.FILES['file_name'], e))
234 234
235 235 else:
236 236 messages.warning(request, 'Your current configuration will be replaced')
237 237 form = ABSImportForm()
238 238
239 239 kwargs = {}
240 240 kwargs['form'] = form
241 241 kwargs['title'] = 'ABS Configuration'
242 242 kwargs['suptitle'] = 'Import file'
243 243 kwargs['button'] = 'Upload'
244 244 kwargs['previous'] = conf.get_absolute_url()
245 245
246 246 return render(request, 'abs_import.html', kwargs)
247 247
248 248
249 249 def send_beam(request, id_conf, id_beam):
250 250
251 251 conf = get_object_or_404(ABSConfiguration, pk=id_conf)
252 252
253 abs = request.user.profile.abs_active
253 abs = Configuration.objects.filter(pk=conf.device.conf_active).first()
254 254 if abs<>conf:
255 255 url = '#' if abs is None else abs.get_absolute_url()
256 256 label = 'None' if abs is None else abs.label
257 257 messages.warning(
258 258 request,
259 259 mark_safe('The current configuration has not been written in the modules, the active configuration is <a href="{}">{}</a>'.format(
260 260 url,
261 261 label
262 262 ))
263 263 )
264 264 return redirect(conf.get_absolute_url())
265 265
266 266 beam = get_object_or_404(ABSBeam, pk=id_beam)
267 267 beams_list = ABSBeam.objects.filter(abs_conf=conf)
268 268 conf.active_beam = id_beam
269 269
270 270 i = 0
271 271 for b in beams_list:
272 272 if b.id == int(id_beam):
273 273 break
274 274 else:
275 275 i += 1
276 276 beam_pos = i + 1 #Estandarizar
277 277 print '%s Position: %s' % (beam.name, str(beam_pos))
278 278 conf.send_beam(beam_pos)
279 279
280 280 return redirect('url_abs_conf', conf.id)
281 281
282 282
283 283 def add_beam(request, id_conf):
284 284
285 285 conf = get_object_or_404(ABSConfiguration, pk=id_conf)
286 286 confs = Configuration.objects.all()
287 287
288 288 if request.method=='GET':
289 289 form = ABSBeamAddForm()
290 290
291 291 if request.method=='POST':
292 292 form = ABSBeamAddForm(request.POST)
293 293
294 294 beam_data = get_values_from_form(request.POST)
295 295
296 296 new_beam = ABSBeam(
297 297 name = beam_data['name'],
298 298 antenna = json.dumps(beam_data['antenna']),
299 299 abs_conf = conf,
300 300 tx = json.dumps(beam_data['tx']),
301 301 rx = json.dumps(beam_data['rx']),
302 302 ues = json.dumps(beam_data['ues']),
303 303 only_rx = json.dumps(beam_data['only_rx'])
304 304 )
305 305 new_beam.save()
306 306 messages.success(request, 'Beam: "%s" has been added.' % new_beam.name)
307 307
308 308 return redirect('url_edit_abs_conf', conf.id)
309 309
310 310 ###### SIDEBAR ######
311 311 kwargs = {}
312 312
313 313 #kwargs['dev_conf'] = conf.device
314 314 #kwargs['id_dev'] = conf.device
315 315 kwargs['id_conf'] = conf.id
316 316 kwargs['form'] = form
317 317 kwargs['title'] = 'ABS Beams'
318 318 kwargs['suptitle'] = 'Add Beam'
319 319 kwargs['button'] = 'Add'
320 320 kwargs['no_sidebar'] = True
321 321
322 322 #kwargs['previous'] = conf.get_absolute_url_edit()
323 323 kwargs['edit'] = True
324 324
325 325 return render(request, 'abs_add_beam.html', kwargs)
326 326
327 327
328 328 def edit_beam(request, id_conf, id_beam):
329 329
330 330 conf = get_object_or_404(ABSConfiguration, pk=id_conf)
331 331 beam = get_object_or_404(ABSBeam, pk=id_beam)
332 332
333 333 if request.method=='GET':
334 334 form = ABSBeamEditForm(initial={'beam': beam})
335 335
336 336 if request.method=='POST':
337 337 form = ABSBeamEditForm(request.POST)
338 338
339 339 beam_data = get_values_from_form(request.POST)
340 340
341 341 beam.dict_to_parms(beam_data)
342 342 beam.save()
343 343
344 344 messages.success(request, 'Beam: "%s" has been updated.' % beam.name)
345 345
346 346 return redirect('url_edit_abs_conf', conf.id)
347 347
348 348 ###### SIDEBAR ######
349 349 kwargs = {}
350 350
351 351 kwargs['id_conf'] = conf.id
352 352 kwargs['form'] = form
353 353 kwargs['title'] = 'ABS Beams'
354 354 kwargs['suptitle'] = 'Edit Beam'
355 355 kwargs['button'] = 'Save'
356 356 kwargs['no_sidebar'] = True
357 357
358 358 #kwargs['previous'] = conf.get_absolute_url_edit()
359 359 kwargs['edit'] = True
360 360
361 361 return render(request, 'abs_edit_beam.html', kwargs)
362 362
363 363
364 364
365 365 def remove_beam(request, id_conf, id_beam):
366 366
367 367 conf = get_object_or_404(ABSConfiguration, pk=id_conf)
368 368 beam = get_object_or_404(ABSBeam, pk=id_beam)
369 369
370 370 if request.method=='POST':
371 371 if beam:
372 372 try:
373 373 beam.delete()
374 374 messages.success(request, 'Beam: "%s" has been deleted.' % beam)
375 375 except:
376 376 messages.error(request, 'Unable to delete beam: "%s".' % beam)
377 377
378 378 return redirect('url_edit_abs_conf', conf.id)
379 379
380 380 ###### SIDEBAR ######
381 381 kwargs = {}
382 382
383 383 kwargs['object'] = beam
384 384 kwargs['delete'] = True
385 385 kwargs['title'] = 'Delete'
386 386 kwargs['suptitle'] = 'Beam'
387 387 kwargs['previous'] = conf.get_absolute_url_edit()
388 388 return render(request, 'confirm.html', kwargs)
389 389
390 390
391 391
392 392 def plot_patterns(request, id_conf, id_beam=None):
393 393
394 394 kwargs = {}
395 395 conf = get_object_or_404(ABSConfiguration, pk=id_conf)
396 396 beams = ABSBeam.objects.filter(abs_conf=conf)
397 397
398 398 if id_beam:
399 399 beam = get_object_or_404(ABSBeam, pk=id_beam)
400 400 kwargs['beam'] = beam
401 401
402 402 ###### SIDEBAR ######
403 403
404 404 kwargs['dev_conf'] = conf.device
405 405 kwargs['id_dev'] = conf.device
406 406 kwargs['id_conf'] = conf.id
407 407 kwargs['abs_beams'] = beams
408 408 kwargs['title'] = 'ABS Patterns'
409 409 kwargs['suptitle'] = conf.name
410 410 kwargs['no_sidebar'] = True
411 411
412 412 return render(request, 'abs_patterns.html', kwargs)
413 413
414 414
415 415 def plot_pattern(request, id_conf, id_beam, antenna):
416 416
417 417 if antenna=='down':
418 418 sleep(3)
419 419
420 420 conf = get_object_or_404(ABSConfiguration, pk=id_conf)
421 421 beam = get_object_or_404(ABSBeam, pk=id_beam)
422 422 just_rx = 1 if json.loads(beam.only_rx)[antenna] else 0
423 423 phases = json.loads(beam.antenna)['antenna_{}'.format(antenna)]
424 424 gain_tx = json.loads(beam.tx)[antenna]
425 425 gain_rx = json.loads(beam.rx)[antenna]
426 426 ues = json.loads(beam.ues)[antenna]
427 427 newOverJro = overJroShow(beam.name)
428 428 fig = newOverJro.plotPattern2(datetime.today(), phases, gain_tx, gain_rx, ues, just_rx)
429 429 buf = io.BytesIO()
430 430 fig.savefig(buf, format='png')
431 431 response = HttpResponse(buf.getvalue(), content_type='image/png')
432 432 return response
433 433
@@ -1,811 +1,804
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 (1,'Configured'), #BLUE
78 (1,'Cancelled'), #YELLOW
79 79 (2,'Running'), #GREEN
80 (3,'Scheduled'), #YELLOW
81 (4,'Not Configured'), #WHITE
80 (3,'Scheduled'), #BLUE
81 (4,'Unknown'), #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 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 94 @receiver(post_save, sender=User)
96 95 def create_user_profile(sender, instance, created, **kwargs):
97 96 if created:
98 97 Profile.objects.create(user=instance)
99 98
100 99 @receiver(post_save, sender=User)
101 100 def save_user_profile(sender, instance, **kwargs):
102 101 instance.profile.save()
103 102
104 103
105 104 class Location(models.Model):
106 105
107 106 name = models.CharField(max_length = 30)
108 107 description = models.TextField(blank=True, null=True)
109 108
110 109 class Meta:
111 110 db_table = 'db_location'
112 111
113 112 def __str__(self):
114 113 return u'%s' % self.name
115 114
116 115 def get_absolute_url(self):
117 116 return reverse('url_location', args=[str(self.id)])
118 117
119 118
120 119 class DeviceType(models.Model):
121 120
122 121 name = models.CharField(max_length = 10, choices = DEV_TYPES, default = 'rc')
123 122 sequence = models.PositiveSmallIntegerField(default=1000)
124 123 description = models.TextField(blank=True, null=True)
125 124
126 125 class Meta:
127 126 db_table = 'db_device_types'
128 127
129 128 def __str__(self):
130 129 return u'%s' % self.get_name_display()
131 130
132 131 class Device(models.Model):
133 132
134 133 device_type = models.ForeignKey(DeviceType, on_delete=models.CASCADE)
135 134 location = models.ForeignKey(Location, on_delete=models.CASCADE)
136 135 ip_address = models.GenericIPAddressField(protocol='IPv4', default='0.0.0.0')
137 136 port_address = models.PositiveSmallIntegerField(default=2000)
138 137 description = models.TextField(blank=True, null=True)
139 138 status = models.PositiveSmallIntegerField(default=0, choices=DEV_STATES)
139 conf_active = models.PositiveIntegerField(default=0, verbose_name='Current configuration')
140 140
141 141 class Meta:
142 142 db_table = 'db_devices'
143 143
144 144 def __str__(self):
145 145 ret = u'{} [{}]'.format(self.device_type.name.upper(), self.location.name)
146 146
147 147 return ret
148 148
149 149 @property
150 150 def name(self):
151 151 return str(self)
152 152
153 153 def get_status(self):
154 154 return self.status
155 155
156 156 @property
157 157 def status_color(self):
158 158 color = 'muted'
159 159 if self.status == 0:
160 160 color = "danger"
161 161 elif self.status == 1:
162 162 color = "warning"
163 163 elif self.status == 2:
164 164 color = "info"
165 165 elif self.status == 3:
166 166 color = "success"
167 167
168 168 return color
169 169
170 170 def url(self, path=None):
171 171
172 172 if path:
173 173 return 'http://{}:{}/{}/'.format(self.ip_address, self.port_address, path)
174 174 else:
175 175 return 'http://{}:{}/'.format(self.ip_address, self.port_address)
176 176
177 177 def get_absolute_url(self):
178 178 return reverse('url_device', args=[str(self.id)])
179 179
180 180 def get_absolute_url_edit(self):
181 181 return reverse('url_edit_device', args=[str(self.id)])
182 182
183 183 def get_absolute_url_delete(self):
184 184 return reverse('url_delete_device', args=[str(self.id)])
185 185
186 186 def change_ip(self, ip_address, mask, gateway, dns, **kwargs):
187 187
188 188 if self.device_type.name=='dds':
189 189 try:
190 190 answer = dds_api.change_ip(ip = self.ip_address,
191 191 port = self.port_address,
192 192 new_ip = ip_address,
193 193 mask = mask,
194 194 gateway = gateway)
195 195 if answer[0]=='1':
196 196 self.message = '25|DDS - {}'.format(answer)
197 197 self.ip_address = ip_address
198 198 self.save()
199 199 else:
200 200 self.message = '30|DDS - {}'.format(answer)
201 201 return False
202 202 except Exception as e:
203 203 self.message = '40|{}'.format(str(e))
204 204 return False
205 205
206 206 elif self.device_type.name=='rc':
207 207 headers = {'content-type': "application/json",
208 208 'cache-control': "no-cache"}
209 209
210 210 ip = [int(x) for x in ip_address.split('.')]
211 211 dns = [int(x) for x in dns.split('.')]
212 212 gateway = [int(x) for x in gateway.split('.')]
213 213 subnet = [int(x) for x in mask.split('.')]
214 214
215 215 payload = {
216 216 "ip": ip,
217 217 "dns": dns,
218 218 "gateway": gateway,
219 219 "subnet": subnet
220 220 }
221 221
222 222 req = requests.post(self.url('changeip'), data=json.dumps(payload), headers=headers)
223 223 try:
224 224 answer = req.json()
225 225 if answer['changeip']=='ok':
226 226 self.message = '25|IP succesfully changed'
227 227 self.ip_address = ip_address
228 228 self.save()
229 229 else:
230 230 self.message = '30|An error ocuur when changing IP'
231 231 except Exception as e:
232 232 self.message = '40|{}'.format(str(e))
233 233 else:
234 234 self.message = 'Not implemented'
235 235 return False
236 236
237 237 return True
238 238
239 239
240 240 class Campaign(models.Model):
241 241
242 242 template = models.BooleanField(default=False)
243 243 name = models.CharField(max_length=60, unique=True)
244 244 start_date = models.DateTimeField(blank=True, null=True)
245 245 end_date = models.DateTimeField(blank=True, null=True)
246 246 tags = models.CharField(max_length=40, blank=True, null=True)
247 247 description = models.TextField(blank=True, null=True)
248 248 experiments = models.ManyToManyField('Experiment', blank=True)
249 249 author = models.ForeignKey(User, null=True, blank=True)
250 250
251 251 class Meta:
252 252 db_table = 'db_campaigns'
253 253 ordering = ('name',)
254 254
255 255 def __str__(self):
256 256 if self.template:
257 257 return u'{} (template)'.format(self.name)
258 258 else:
259 259 return u'{}'.format(self.name)
260 260
261 261 def jsonify(self):
262 262
263 263 data = {}
264 264
265 265 ignored = ('template')
266 266
267 267 for field in self._meta.fields:
268 268 if field.name in ignored:
269 269 continue
270 270 data[field.name] = field.value_from_object(self)
271 271
272 272 data['start_date'] = data['start_date'].strftime('%Y-%m-%d')
273 273 data['end_date'] = data['end_date'].strftime('%Y-%m-%d')
274 274
275 275 return data
276 276
277 277 def parms_to_dict(self):
278 278
279 279 params = Params({})
280 280 params.add(self.jsonify(), 'campaigns')
281 281
282 282 for exp in Experiment.objects.filter(campaign = self):
283 283 params.add(exp.jsonify(), 'experiments')
284 284 configurations = Configuration.objects.filter(experiment=exp, type=0)
285 285
286 286 for conf in configurations:
287 287 params.add(conf.jsonify(), 'configurations')
288 288 if conf.device.device_type.name=='rc':
289 289 for line in conf.get_lines():
290 290 params.add(line.jsonify(), 'lines')
291 291
292 292 return params.data
293 293
294 294 def dict_to_parms(self, parms, CONF_MODELS):
295 295
296 296 experiments = Experiment.objects.filter(campaign = self)
297 297
298 298 if experiments:
299 299 for experiment in experiments:
300 300 experiment.delete()
301 301
302 302 for id_exp in parms['experiments']['allIds']:
303 303 exp_parms = parms['experiments']['byId'][id_exp]
304 304 dum = (datetime.now() - datetime(1970, 1, 1)).total_seconds()
305 305 exp = Experiment(name='{}'.format(dum))
306 306 exp.save()
307 307 exp.dict_to_parms(parms, CONF_MODELS, id_exp=id_exp)
308 308 self.experiments.add(exp)
309 309
310 310 camp_parms = parms['campaigns']['byId'][parms['campaigns']['allIds'][0]]
311 311
312 312 self.name = '{}-{}'.format(camp_parms['name'], datetime.now().strftime('%y%m%d'))
313 313 self.start_date = camp_parms['start_date']
314 314 self.end_date = camp_parms['end_date']
315 315 self.tags = camp_parms['tags']
316 316 self.save()
317 317
318 318 return self
319 319
320 320 def get_experiments_by_radar(self, radar=None):
321 321
322 322 ret = []
323 323 if radar:
324 324 locations = Location.objects.filter(pk=radar)
325 325 else:
326 326 locations = set([e.location for e in self.experiments.all()])
327 327
328 328 for loc in locations:
329 329 dum = {}
330 330 dum['name'] = loc.name
331 331 dum['id'] = loc.pk
332 332 dum['experiments'] = [e for e in self.experiments.all() if e.location==loc]
333 333 ret.append(dum)
334 334
335 335 return ret
336 336
337 337 def get_absolute_url(self):
338 338 return reverse('url_campaign', args=[str(self.id)])
339 339
340 340 def get_absolute_url_edit(self):
341 341 return reverse('url_edit_campaign', args=[str(self.id)])
342 342
343 343 def get_absolute_url_delete(self):
344 344 return reverse('url_delete_campaign', args=[str(self.id)])
345 345
346 346 def get_absolute_url_export(self):
347 347 return reverse('url_export_campaign', args=[str(self.id)])
348 348
349 349 def get_absolute_url_import(self):
350 350 return reverse('url_import_campaign', args=[str(self.id)])
351 351
352 352
353 353 class RunningExperiment(models.Model):
354 354 radar = models.OneToOneField('Location', on_delete=models.CASCADE)
355 355 running_experiment = models.ManyToManyField('Experiment', blank = True)
356 356 status = models.PositiveSmallIntegerField(default=0, choices=RADAR_STATES)
357 357
358 358
359 359 class Experiment(models.Model):
360 360
361 361 template = models.BooleanField(default=False)
362 362 name = models.CharField(max_length=40, default='', unique=True)
363 363 location = models.ForeignKey('Location', null=True, blank=True, on_delete=models.CASCADE)
364 364 freq = models.FloatField(verbose_name='Operating Freq. (MHz)', validators=[MinValueValidator(1), MaxValueValidator(10000)], default=49.9200)
365 365 start_time = models.TimeField(default='00:00:00')
366 366 end_time = models.TimeField(default='23:59:59')
367 367 task = models.CharField(max_length=36, default='', blank=True, null=True)
368 368 status = models.PositiveSmallIntegerField(default=4, choices=EXP_STATES)
369 369 author = models.ForeignKey(User, null=True, blank=True)
370 370 hash = models.CharField(default='', max_length=64, null=True, blank=True)
371 371
372 372 class Meta:
373 373 db_table = 'db_experiments'
374 374 ordering = ('template', 'name')
375 375
376 376 def __str__(self):
377 377 if self.template:
378 378 return u'%s (template)' % (self.name)
379 379 else:
380 380 return u'%s' % (self.name)
381 381
382 382 def jsonify(self):
383 383
384 384 data = {}
385 385
386 386 ignored = ('template')
387 387
388 388 for field in self._meta.fields:
389 389 if field.name in ignored:
390 390 continue
391 391 data[field.name] = field.value_from_object(self)
392 392
393 393 data['start_time'] = data['start_time'].strftime('%H:%M:%S')
394 394 data['end_time'] = data['end_time'].strftime('%H:%M:%S')
395 395 data['location'] = self.location.name
396 396 data['configurations'] = ['{}'.format(conf.pk) for
397 397 conf in Configuration.objects.filter(experiment=self, type=0)]
398 398
399 399 return data
400 400
401 401 @property
402 402 def radar_system(self):
403 403 return self.location
404 404
405 405 def clone(self, **kwargs):
406 406
407 407 confs = Configuration.objects.filter(experiment=self, type=0)
408 408 self.pk = None
409 409 self.name = '{}_{:%y%m%d}'.format(self.name, datetime.now())
410 410 for attr, value in kwargs.items():
411 411 setattr(self, attr, value)
412 412
413 413 self.save()
414 414
415 415 for conf in confs:
416 416 conf.clone(experiment=self, template=False)
417 417
418 418 return self
419 419
420 420 def start(self):
421 421 '''
422 422 Configure and start experiments's devices
423 423 ABS-CGS-DDS-RC-JARS
424 424 '''
425 425
426 result = 2
427 426 confs = []
428 427 allconfs = Configuration.objects.filter(experiment=self, type = 0).order_by('-device__device_type__sequence')
429 428 rc_mix = [conf for conf in allconfs if conf.device.device_type.name=='rc' and conf.mix]
430 429 if rc_mix:
431 430 for conf in allconfs:
432 431 if conf.device.device_type.name == 'rc' and not conf.mix:
433 432 continue
434 433 confs.append(conf)
435 434 else:
436 435 confs = allconfs
437 #Only Configured Devices.
438 for conf in confs:
439 if conf.device.status in (0, 4):
440 result = 0
441 return result
442 for conf in confs:
443 conf.stop_device()
444 conf.write_device()
445 conf.start_device()
446 time.sleep(1)
447
448 return result
436
437 try:
438 for conf in confs:
439 conf.stop_device()
440 conf.write_device()
441 conf.start_device()
442 time.sleep(0.1)
443 except:
444 return 0
445 return 2
449 446
450 447
451 448 def stop(self):
452 449 '''
453 450 Stop experiments's devices
454 451 DDS-JARS-RC-CGS-ABS
455 452 '''
456 453
457 result = 1
458
459 454 confs = Configuration.objects.filter(experiment=self, type = 0).order_by('device__device_type__sequence')
460 455 confs=confs.exclude(device__device_type__name='cgs')
461 for conf in confs:
462 if conf.device.status in (0, 4):
463 result = 0
464 continue
465 conf.stop_device()
466
467 return result
468
456 try:
457 for conf in confs:
458 conf.stop_device()
459 except:
460 return 0
461 return 1
469 462
470 463 def get_status(self):
471 464
472 465 if self.status == 3:
473 466 return
474 467
475 468 confs = Configuration.objects.filter(experiment=self, type=0)
476 469
477 470 for conf in confs:
478 471 conf.status_device()
479 472
480 473 total = confs.aggregate(models.Sum('device__status'))['device__status__sum']
481 474
482 475 if total==2*confs.count():
483 476 status = 1
484 477 elif total == 3*confs.count():
485 478 status = 2
486 479 else:
487 480 status = 0
488 481
489 482 self.status = status
490 483 self.save()
491 484
492 485 def status_color(self):
493 486 color = 'muted'
494 487 if self.status == 0:
495 488 color = "danger"
496 489 elif self.status == 1:
497 color = "info"
490 color = "warning"
498 491 elif self.status == 2:
499 492 color = "success"
500 493 elif self.status == 3:
501 color = "warning"
494 color = "info"
502 495
503 496 return color
504 497
505 498 def parms_to_dict(self):
506 499
507 500 params = Params({})
508 501 params.add(self.jsonify(), 'experiments')
509 502
510 503 configurations = Configuration.objects.filter(experiment=self, type=0)
511 504
512 505 for conf in configurations:
513 506 params.add(conf.jsonify(), 'configurations')
514 507 if conf.device.device_type.name=='rc':
515 508 for line in conf.get_lines():
516 509 params.add(line.jsonify(), 'lines')
517 510
518 511 return params.data
519 512
520 513 def dict_to_parms(self, parms, CONF_MODELS, id_exp=None):
521 514
522 515 configurations = Configuration.objects.filter(experiment=self)
523 516
524 517 if id_exp is not None:
525 518 exp_parms = parms['experiments']['byId'][id_exp]
526 519 else:
527 520 exp_parms = parms['experiments']['byId'][parms['experiments']['allIds'][0]]
528 521
529 522 if configurations:
530 523 for configuration in configurations:
531 524 configuration.delete()
532 525
533 526 for id_conf in exp_parms['configurations']:
534 527 conf_parms = parms['configurations']['byId'][id_conf]
535 528 device = Device.objects.filter(device_type__name=conf_parms['device_type'])[0]
536 529 model = CONF_MODELS[conf_parms['device_type']]
537 530 conf = model(
538 531 experiment = self,
539 532 device = device,
540 533 )
541 534 conf.dict_to_parms(parms, id=id_conf)
542 535
543 536
544 537 location, created = Location.objects.get_or_create(name=exp_parms['location'])
545 538 self.name = '{}-{}'.format(exp_parms['name'], datetime.now().strftime('%y%m%d'))
546 539 self.location = location
547 540 self.start_time = exp_parms['start_time']
548 541 self.end_time = exp_parms['end_time']
549 542 self.save()
550 543
551 544 return self
552 545
553 546 def get_absolute_url(self):
554 547 return reverse('url_experiment', args=[str(self.id)])
555 548
556 549 def get_absolute_url_edit(self):
557 550 return reverse('url_edit_experiment', args=[str(self.id)])
558 551
559 552 def get_absolute_url_delete(self):
560 553 return reverse('url_delete_experiment', args=[str(self.id)])
561 554
562 555 def get_absolute_url_import(self):
563 556 return reverse('url_import_experiment', args=[str(self.id)])
564 557
565 558 def get_absolute_url_export(self):
566 559 return reverse('url_export_experiment', args=[str(self.id)])
567 560
568 561 def get_absolute_url_start(self):
569 562 return reverse('url_start_experiment', args=[str(self.id)])
570 563
571 564 def get_absolute_url_stop(self):
572 565 return reverse('url_stop_experiment', args=[str(self.id)])
573 566
574 567
575 568 class Configuration(PolymorphicModel):
576 569
577 570 template = models.BooleanField(default=False)
578 571 # name = models.CharField(verbose_name="Configuration Name", max_length=40, default='')
579 572 label = models.CharField(verbose_name="Label", max_length=40, default='', blank=True, null=True)
580 573 experiment = models.ForeignKey('Experiment', verbose_name='Experiment', null=True, blank=True, on_delete=models.CASCADE)
581 574 device = models.ForeignKey('Device', verbose_name='Device', null=True, on_delete=models.CASCADE)
582 575 type = models.PositiveSmallIntegerField(default=0, choices=CONF_TYPES)
583 576 created_date = models.DateTimeField(auto_now_add=True)
584 577 programmed_date = models.DateTimeField(auto_now=True)
585 578 parameters = models.TextField(default='{}')
586 579 author = models.ForeignKey(User, null=True, blank=True)
587 580 hash = models.CharField(default='', max_length=64, null=True, blank=True)
588 581 message = ""
589 582
590 583 class Meta:
591 584 db_table = 'db_configurations'
592 585 ordering = ('device__device_type__name',)
593 586
594 587 def __str__(self):
595 588
596 589 ret = u'{} '.format(self.device.device_type.name.upper())
597 590
598 591 if 'mix' in [f.name for f in self._meta.get_fields()]:
599 592 if self.mix:
600 593 ret = '{} MIX '.format(self.device.device_type.name.upper())
601 594
602 595 if 'label' in [f.name for f in self._meta.get_fields()]:
603 596 ret += '{}'.format(self.label)
604 597
605 598 if self.template:
606 599 ret += ' (template)'
607 600
608 601 return ret
609 602
610 603 @property
611 604 def name(self):
612 605
613 606 return str(self)
614 607
615 608 def jsonify(self):
616 609
617 610 data = {}
618 611
619 612 ignored = ('type', 'polymorphic_ctype', 'configuration_ptr',
620 613 'created_date', 'programmed_date', 'template', 'device',
621 614 'experiment')
622 615
623 616 for field in self._meta.fields:
624 617 if field.name in ignored:
625 618 continue
626 619 data[field.name] = field.value_from_object(self)
627 620
628 621 data['device_type'] = self.device.device_type.name
629 622
630 623 if self.device.device_type.name == 'rc':
631 624 data['lines'] = ['{}'.format(line.pk) for line in self.get_lines()]
632 625 data['delays'] = self.get_delays()
633 626 data['pulses'] = self.get_pulses()
634 627
635 628 elif self.device.device_type.name == 'jars':
636 629 data['decode_type'] = DECODE_TYPE[self.decode_data][1]
637 630
638 631 elif self.device.device_type.name == 'dds':
639 632 data['frequencyA_Mhz'] = float(data['frequencyA_Mhz'])
640 633 data['frequencyB_Mhz'] = float(data['frequencyB_Mhz'])
641 634 data['phaseA'] = dds_data.phase_to_binary(data['phaseA_degrees'])
642 635 data['phaseB'] = dds_data.phase_to_binary(data['phaseB_degrees'])
643 636
644 637 return data
645 638
646 639 def clone(self, **kwargs):
647 640
648 641 self.pk = None
649 642 self.id = None
650 643 for attr, value in kwargs.items():
651 644 setattr(self, attr, value)
652 645
653 646 self.save()
654 647
655 648 return self
656 649
657 650 def parms_to_dict(self):
658 651
659 652 params = Params({})
660 653 params.add(self.jsonify(), 'configurations')
661 654
662 655 if self.device.device_type.name=='rc':
663 656 for line in self.get_lines():
664 657 params.add(line.jsonify(), 'lines')
665 658
666 659 return params.data
667 660
668 661 def parms_to_text(self):
669 662
670 663 raise NotImplementedError("This method should be implemented in %s Configuration model" %str(self.device.device_type.name).upper())
671 664
672 665
673 666 def parms_to_binary(self):
674 667
675 668 raise NotImplementedError("This method should be implemented in %s Configuration model" %str(self.device.device_type.name).upper())
676 669
677 670
678 671 def dict_to_parms(self, parameters, id=None):
679 672
680 673 params = Params(parameters)
681 674
682 675 if id:
683 676 data = params.get_conf(id_conf=id)
684 677 else:
685 678 data = params.get_conf(dtype=self.device.device_type.name)
686 679
687 680 if data['device_type']=='rc':
688 681 self.clean_lines()
689 682 lines = data.pop('lines', None)
690 683 for line_id in lines:
691 684 pass
692 685
693 686 for key, value in data.items():
694 687 if key not in ('id', 'device_type'):
695 688 setattr(self, key, value)
696 689
697 690 self.save()
698 691
699 692
700 693 def export_to_file(self, format="json"):
701 694
702 695 content_type = ''
703 696
704 697 if format == 'racp':
705 698 content_type = 'text/plain'
706 699 filename = '%s_%s.%s' %(self.device.device_type.name, self.name, 'racp')
707 700 content = self.parms_to_text(file_format = 'racp')
708 701
709 702 if format == 'text':
710 703 content_type = 'text/plain'
711 704 filename = '%s_%s.%s' %(self.device.device_type.name, self.name, self.device.device_type.name)
712 705 content = self.parms_to_text()
713 706
714 707 if format == 'binary':
715 708 content_type = 'application/octet-stream'
716 709 filename = '%s_%s.bin' %(self.device.device_type.name, self.name)
717 710 content = self.parms_to_binary()
718 711
719 712 if not content_type:
720 713 content_type = 'application/json'
721 714 filename = '%s_%s.json' %(self.device.device_type.name, self.name)
722 715 content = json.dumps(self.parms_to_dict(), indent=2)
723 716
724 717 fields = {'content_type':content_type,
725 718 'filename':filename,
726 719 'content':content
727 720 }
728 721
729 722 return fields
730 723
731 724 def import_from_file(self, fp):
732 725
733 726 parms = {}
734 727
735 728 path, ext = os.path.splitext(fp.name)
736 729
737 730 if ext == '.json':
738 731 parms = json.load(fp)
739 732
740 733 if ext == '.dds':
741 734 lines = fp.readlines()
742 735 parms = dds_data.text_to_dict(lines)
743 736
744 737 if ext == '.racp':
745 738 if self.device.device_type.name == 'jars':
746 739 parms = RacpFile(fp).to_dict()
747 740 parms['filter_parms'] = json.loads(self.filter_parms)
748 741 return parms
749 742 parms = RCFile(fp).to_dict()
750 743
751 744 return parms
752 745
753 746 def status_device(self):
754 747
755 748 self.message = 'Function not implemented'
756 749 return False
757 750
758 751
759 752 def stop_device(self):
760 753
761 754 self.message = 'Function not implemented'
762 755 return False
763 756
764 757
765 758 def start_device(self):
766 759
767 760 self.message = 'Function not implemented'
768 761 return False
769 762
770 763
771 764 def write_device(self, parms):
772 765
773 766 self.message = 'Function not implemented'
774 767 return False
775 768
776 769
777 770 def read_device(self):
778 771
779 772 self.message = 'Function not implemented'
780 773 return False
781 774
782 775
783 776 def get_absolute_url(self):
784 777 return reverse('url_%s_conf' % self.device.device_type.name, args=[str(self.id)])
785 778
786 779 def get_absolute_url_edit(self):
787 780 return reverse('url_edit_%s_conf' % self.device.device_type.name, args=[str(self.id)])
788 781
789 782 def get_absolute_url_delete(self):
790 783 return reverse('url_delete_dev_conf', args=[str(self.id)])
791 784
792 785 def get_absolute_url_import(self):
793 786 return reverse('url_import_dev_conf', args=[str(self.id)])
794 787
795 788 def get_absolute_url_export(self):
796 789 return reverse('url_export_dev_conf', args=[str(self.id)])
797 790
798 791 def get_absolute_url_write(self):
799 792 return reverse('url_write_dev_conf', args=[str(self.id)])
800 793
801 794 def get_absolute_url_read(self):
802 795 return reverse('url_read_dev_conf', args=[str(self.id)])
803 796
804 797 def get_absolute_url_start(self):
805 798 return reverse('url_start_dev_conf', args=[str(self.id)])
806 799
807 800 def get_absolute_url_stop(self):
808 801 return reverse('url_stop_dev_conf', args=[str(self.id)])
809 802
810 803 def get_absolute_url_status(self):
811 804 return reverse('url_status_dev_conf', args=[str(self.id)])
@@ -1,81 +1,85
1 1 {% extends "base.html" %}
2 2 {% load bootstrap3 %}
3 3 {% load static %}
4 4 {% load main_tags %}
5 5 {% block content-title %}{{title}}{% endblock %}
6 6 {% block content-suptitle %}{{suptitle}}{% endblock %}
7 7
8 8 {% block content %}
9 9
10 10 {% block menu-actions %}
11 11 <span class=" dropdown pull-right">
12 12 <a href="#" class="dropdown-toggle" data-toggle="dropdown"><span class="glyphicon glyphicon-menu-hamburger gi-2x" aria-hidden="true"></span></a>
13 13 <ul class="dropdown-menu" role="menu">
14 14 <li><a href="{{ dev_conf.get_absolute_url_edit }}"><span class="glyphicon glyphicon-pencil" aria-hidden="true"></span> Edit</a></li>
15 15 <li><a href="{{ dev_conf.get_absolute_url_delete }}"><span class="glyphicon glyphicon-remove" aria-hidden="true"></span> Delete</a></li>
16 16 <li><a href="{{ dev_conf.get_absolute_url_import }}"><span class="glyphicon glyphicon-import" aria-hidden="true"></span> Import </a></li>
17 17 <li><a href="{{ dev_conf.get_absolute_url_export }}"><span class="glyphicon glyphicon-export" aria-hidden="true"></span> Export </a></li>
18 18 {% block extra-menu-actions %}
19 19 {% endblock %}
20 20 <li><a>----------------</a></li>
21 21 <li><a href="{{ dev_conf.get_absolute_url_status }}"><span class="glyphicon glyphicon-refresh" aria-hidden="true"></span> Status</a></li>
22 22 {% if not no_play %}
23 23 {% if not only_stop %}
24 24 <li><a href="{{ dev_conf.get_absolute_url_start}}"><span class="glyphicon glyphicon-play" aria-hidden="true"></span> Start</a></li>
25 25 {% endif %}
26 26 <li><a href="{{ dev_conf.get_absolute_url_stop }}"><span class="glyphicon glyphicon-stop" aria-hidden="true"></span> Stop</a></li>
27 27 {% endif %}
28 28 <li><a href="{{ dev_conf.get_absolute_url_write }}"><span class="glyphicon glyphicon-download" aria-hidden="true"></span> Write</a></li>
29 29 {% if dev_conf.device.device_type.name != 'abs' %}
30 30 <li><a href="{{ dev_conf.get_absolute_url_read }}"><span class="glyphicon glyphicon-upload" aria-hidden="true"></span> Read</a></li>
31 31 {% endif %}
32 32 </ul>
33 33 </span>
34 34 {% endblock %}
35 35
36 36 {% block content-detail %}
37 37 <table class="table table-bordered">
38 38 <tr>
39 <th>Status</th>
40 <td class="text-{{dev_conf.device.status_color}}"><strong> {% if dev_conf.device.device_type.name == 'abs' %} {{connected_modules}} {% else %} {{dev_conf.device.get_status_display}}{% endif %}</strong></td>
41 </tr>
39 <th>Status</th>
40 {% if dev_conf.pk == dev_conf.device.conf_active %}
41 <td class="text-{{dev_conf.device.status_color}}"><strong> {% if dev_conf.device.device_type.name == 'abs' %} {{connected_modules}} {% else %} {{dev_conf.device.get_status_display}}{% endif %}</strong></td>
42 {% else %}
43 <td class="text-info"><strong> Connected </strong></td>
44 {% endif %}
45 </tr>
42 46
43 47 {% for key in dev_conf_keys %}
44 48 <tr>
45 49 <th>{% get_verbose_field_name dev_conf key %}</th>
46 50 <td>{{dev_conf|attr:key}}</td>
47 51 </tr>
48 52 {% endfor %}
49 53 </table>
50 54 {% endblock %}
51 55
52 56 {% block extra-content %}
53 57 {% endblock %}
54 58
55 59 {% endblock %}
56 60
57 61 {% block extra-js%}
58 62 <script type="text/javascript">
59 63
60 64 $("#bt_edit").click(function() {
61 65 document.location = "{{ dev_conf.get_absolute_url_edit }}";
62 66 });
63 67
64 68 $("#bt_read").click(function() {
65 69 document.location = "{{ dev_conf.get_absolute_url_read }}";
66 70 });
67 71
68 72 $("#bt_write").click(function() {
69 73 document.location = "{{ dev_conf.get_absolute_url_write }}";
70 74 });
71 75
72 76 $("#bt_import").click(function() {
73 77 document.location = "{{ dev_conf.get_absolute_url_import }}";
74 78 });
75 79
76 80 $("#bt_export").click(function() {
77 81 document.location = "{{ dev_conf.get_absolute_url_export }}";
78 82 });
79 83
80 84 </script>
81 85 {% endblock %}
@@ -1,105 +1,105
1 1 {% extends "base.html" %}
2 2 {% load bootstrap3 %}
3 3 {% load static %}
4 4 {% load main_tags %}
5 5 {% block extra-head %}
6 6 <link href="{% static 'css/bootstrap-datetimepicker.min.css' %}" media="screen" rel="stylesheet">
7 7 {% endblock %}
8 8 {% block content-title %}{{title}}{% endblock %}
9 9 {% block content-suptitle %}{{suptitle}}{% endblock %}
10 10
11 11 {% block content %}
12 12
13 13 {% block menu-actions %}
14 14 <span class=" dropdown pull-right">
15 15 <a href="#" class="dropdown-toggle" data-toggle="dropdown"><span class="glyphicon glyphicon-menu-hamburger gi-2x" aria-hidden="true"></span></a>
16 16 <ul class="dropdown-menu" role="menu">
17 17 <li><a href="{% url 'url_edit_experiment' experiment.id %}"><span class="glyphicon glyphicon-pencil" aria-hidden="true"></span> Edit</a></li>
18 18 <li><a href="{% url 'url_delete_experiment' experiment.id %}"><span class="glyphicon glyphicon-remove" aria-hidden="true"></span> Delete</a></li>
19 19 <li><a href="{{ experiment.get_absolute_url_import }}"><span class="glyphicon glyphicon-import" aria-hidden="true"></span> Import </a></li>
20 20 <li><a href="{{ experiment.get_absolute_url_export }}"><span class="glyphicon glyphicon-export" aria-hidden="true"></span> Export </a></li>
21 21 <li><a>----------------</a></li>
22 22 <li><a href="{{ experiment.get_absolute_url_start}}"><span class="glyphicon glyphicon-play" aria-hidden="true"></span> Start</a></li>
23 23 <li><a href="{{ experiment.get_absolute_url_stop }}"><span class="glyphicon glyphicon-stop" aria-hidden="true"></span> Stop</a></li>
24 24 <li><a href="{% url 'url_mix_experiment' experiment.id %}"><span class="glyphicon glyphicon-random" aria-hidden="true"></span> Mix RC Configurations </a></li>
25 25 <li><a href="{% url 'url_add_dev_conf' experiment.id %}"><span class="glyphicon glyphicon-plus-sign" aria-hidden="true"></span> Add Configuration</a></li>
26 26 <li><a href="{% url 'url_sum_experiment' experiment.id %}"><span class="glyphicon glyphicon-list-alt" aria-hidden="true"></span> Summary</a></li>
27 27
28 28 </ul>
29 29 </span>
30 30 {% endblock %}
31 31
32 32 <table class="table table-bordered">
33 33 {% for key in experiment_keys %}
34 34 {% if key == 'freq' %}
35 35 <tr><th>Operating Freq. (MHz)</th><td>{{experiment|attr:key}}</td></tr>
36 36 {% else %}
37 37 <tr><th>{{key|title}}</th><td>{{experiment|attr:key}}</td></tr>
38 38 {% endif %}
39 39 {% endfor %}
40 40 </table>
41 41 <br>
42 42
43 43 <div class="panel-group" id="accordion" role="tablist" aria-multiselectable="true">
44 44
45 45 <div class="panel panel-default bootcards-summary">
46 46 <div class="panel-heading" role="tab">
47 47 <h4 class="panel-title">
48 48 Devices
49 49 </h4>
50 50 </div>
51 51 <div class="panel-body">
52 52
53 53 {% for item in configurations %}
54 54 <div class="col-xs-6 col-sm-4" style="padding-top:5px;padding-bottom:5px">
55 55 <a class="bootcards-summary-item" href="{{item.get_absolute_url}}"><br>
56 56 {% if item.device.device_type.name == 'cgs' %}
57 57 <i class="fa fa-2x fa-clock-o"></i>
58 58 {% elif item.device.device_type.name == 'rc' %}
59 59 <i class="fa fa-2x fa-microchip"></i>
60 60 {% elif item.device.device_type.name == 'abs' %}
61 61 <i class="fa fa-2x fa-podcast"></i>
62 62 {% elif item.device.device_type.name == 'jars' %}
63 63 <i class="fa fa-2x fa-desktop"></i>
64 64 {% elif item.device.device_type.name == 'dds' %}
65 65 <i class="fa fa-2x fa-bar-chart"></i>
66 66 {% else %}
67 67 <i class="fa fa-3x fa-puzzle-piece"></i>
68 68 {%endif%}
69 69 <h4>{{item}}<br><small>{{item.device.ip_address}}</small>
70 {%if experiment.status == 3 %}
70 {%if item.pk != item.device.conf_active %}
71 71 <span class="label label-info">Configured</span>
72 72 {%else%}
73 73 <span class="label label-{{item.device.status_color}}">{{item.device.get_status_display}}</span>
74 {%endif%}
74 {%endif%}
75 75 </h4>
76 76 </a>
77 77 </div>
78 78 {% endfor %}
79 79
80 80 </div>
81 81 </div>
82 82 </div>
83 83 {% endblock %}
84 84
85 85 {% block sidebar%}
86 86 {% include "sidebar_devices.html" %}
87 87 {% endblock %}
88 88
89 89 {% block extra-js%}
90 90 <script type="text/javascript">
91 91
92 92 $(".clickable-row").click(function() {
93 93 document.location = $(this).data("href");
94 94 });
95 95
96 96 $("#bt_edit").click(function() {
97 97 document.location = "{% url 'url_edit_experiment' experiment.id%}";
98 98 });
99 99
100 100 $("#bt_add_conf").click(function() {
101 101 document.location = "{% url 'url_add_dev_conf' experiment.id %}";
102 102 });
103 103
104 104 </script>
105 105 {% endblock %}
@@ -1,1868 +1,1881
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, RCClock
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 elif conf.device.device_type.name == 'rc':
1372 1372 clk = RCClock(rc_configuration=conf)
1373 1373 clk.save()
1374 1374
1375 1375 return redirect('url_dev_conf', id_conf=conf.pk)
1376 1376
1377 1377 kwargs['id_exp'] = id_exp
1378 1378 kwargs['form'] = form
1379 1379 kwargs['title'] = 'Configuration'
1380 1380 kwargs['suptitle'] = 'New'
1381 1381 kwargs['menu_configurations'] = 'active'
1382 1382
1383 1383 if id_dev != 0:
1384 1384 device = Device.objects.get(pk=id_dev)
1385 1385 kwargs['device'] = device.device_type.name
1386 1386
1387 1387 return render(request, 'dev_conf_edit.html', kwargs)
1388 1388
1389 1389
1390 1390 @login_required
1391 1391 def dev_conf_edit(request, id_conf):
1392 1392
1393 1393 conf = get_object_or_404(Configuration, pk=id_conf)
1394 1394
1395 1395 DevConfForm = CONF_FORMS[conf.device.device_type.name]
1396 1396
1397 1397 if request.method == 'GET':
1398 1398 form = DevConfForm(instance=conf)
1399 1399
1400 1400 if request.method == 'POST':
1401 1401 form = DevConfForm(request.POST, instance=conf)
1402 1402
1403 1403 if form.is_valid():
1404 1404 form.save()
1405 1405 return redirect('url_dev_conf', id_conf=id_conf)
1406 1406
1407 1407 kwargs = {}
1408 1408 kwargs['form'] = form
1409 1409 kwargs['title'] = 'Device Configuration'
1410 1410 kwargs['suptitle'] = 'Edit'
1411 1411 kwargs['button'] = 'Update'
1412 1412 kwargs['menu_configurations'] = 'active'
1413 1413
1414 1414 ###### SIDEBAR ######
1415 1415 kwargs.update(sidebar(conf=conf))
1416 1416
1417 1417 return render(request, '%s_conf_edit.html' % conf.device.device_type.name, kwargs)
1418 1418
1419 1419
1420 1420 @login_required
1421 1421 def dev_conf_start(request, id_conf):
1422 1422
1423 1423 conf = get_object_or_404(Configuration, pk=id_conf)
1424 1424
1425 1425 if conf.start_device():
1426 1426 messages.success(request, conf.message)
1427 1427 else:
1428 1428 messages.error(request, conf.message)
1429 1429
1430 1430 #conf.status_device()
1431 1431
1432 1432 return redirect(conf.get_absolute_url())
1433 1433
1434 1434
1435 1435 @login_required
1436 1436 def dev_conf_stop(request, id_conf):
1437 1437
1438 1438 conf = get_object_or_404(Configuration, pk=id_conf)
1439 1439
1440 1440 if conf.stop_device():
1441 1441 messages.success(request, conf.message)
1442 1442 else:
1443 1443 messages.error(request, conf.message)
1444 1444
1445 1445 #conf.status_device()
1446 1446
1447 1447 return redirect(conf.get_absolute_url())
1448 1448
1449 1449
1450 1450 @login_required
1451 1451 def dev_conf_status(request, id_conf):
1452 1452
1453 1453 conf = get_object_or_404(Configuration, pk=id_conf)
1454 1454
1455 if conf.device.device_type.name == 'abs':
1456 abs = request.user.profile.abs_active
1457 if abs<>conf:
1458 url = '#' if abs is None else abs.get_absolute_url()
1459 label = 'None' if abs is None else abs.label
1460 messages.warning(
1461 request,
1462 mark_safe('The current configuration has not been written in the modules, the active configuration is <a href="{}">{}</a>'.format(
1463 url,
1464 label
1465 ))
1466 )
1467 return redirect(conf.get_absolute_url())
1455 conf_active = Configuration.objects.filter(pk=conf.device.conf_active).first()
1456 if conf_active<>conf:
1457 url = '#' if conf_active is None else conf_active.get_absolute_url()
1458 label = 'None' if conf_active is None else conf_active.label
1459 messages.warning(
1460 request,
1461 mark_safe('The current configuration has not been written to device, the active configuration is <a href="{}">{}</a>'.format(
1462 url,
1463 label
1464 ))
1465 )
1466
1467 return redirect(conf.get_absolute_url())
1468 1468
1469 1469 if conf.status_device():
1470 1470 messages.success(request, conf.message)
1471 1471 else:
1472 1472 messages.error(request, conf.message)
1473 1473
1474 1474 return redirect(conf.get_absolute_url())
1475 1475
1476 1476
1477 1477 @login_required
1478 1478 def dev_conf_reset(request, id_conf):
1479 1479
1480 1480 conf = get_object_or_404(Configuration, pk=id_conf)
1481 1481
1482 1482 if conf.reset_device():
1483 1483 messages.success(request, conf.message)
1484 1484 else:
1485 1485 messages.error(request, conf.message)
1486 1486
1487 1487 return redirect(conf.get_absolute_url())
1488 1488
1489 1489
1490 1490 @login_required
1491 1491 def dev_conf_write(request, id_conf):
1492 1492
1493 1493 conf = get_object_or_404(Configuration, pk=id_conf)
1494 1494
1495 1495 if conf.write_device():
1496 conf.device.conf_active = conf.pk
1497 conf.device.save()
1496 1498 messages.success(request, conf.message)
1497 1499 if has_been_modified(conf):
1498 1500 conf.clone(type=1, template=False)
1499 1501 else:
1500 1502 messages.error(request, conf.message)
1501 1503
1502 1504 return redirect(get_object_or_404(Configuration, pk=id_conf).get_absolute_url())
1503 1505
1504 1506
1505 1507 @login_required
1506 1508 def dev_conf_read(request, id_conf):
1507 1509
1508 1510 conf = get_object_or_404(Configuration, pk=id_conf)
1509 1511
1510 1512 DevConfForm = CONF_FORMS[conf.device.device_type.name]
1511 1513
1512 1514 if request.method == 'GET':
1513 1515
1514 1516 parms = conf.read_device()
1515 1517 #conf.status_device()
1516 1518
1517 1519 if not parms:
1518 1520 messages.error(request, conf.message)
1519 1521 return redirect(conf.get_absolute_url())
1520 1522
1521 1523 form = DevConfForm(initial=parms, instance=conf)
1522 1524
1523 1525 if request.method == 'POST':
1524 1526 form = DevConfForm(request.POST, instance=conf)
1525 1527
1526 1528 if form.is_valid():
1527 1529 form.save()
1528 1530 return redirect(conf.get_absolute_url())
1529 1531
1530 1532 messages.error(request, "Parameters could not be saved")
1531 1533
1532 1534 kwargs = {}
1533 1535 kwargs['id_dev'] = conf.id
1534 1536 kwargs['form'] = form
1535 1537 kwargs['title'] = 'Device Configuration'
1536 1538 kwargs['suptitle'] = 'Parameters read from device'
1537 1539 kwargs['button'] = 'Save'
1538 1540
1539 1541 ###### SIDEBAR ######
1540 1542 kwargs.update(sidebar(conf=conf))
1541 1543
1542 1544 return render(request, '%s_conf_edit.html' % conf.device.device_type.name, kwargs)
1543 1545
1544 1546
1545 1547 @login_required
1546 1548 def dev_conf_import(request, id_conf):
1547 1549
1548 1550 conf = get_object_or_404(Configuration, pk=id_conf)
1549 1551 DevConfForm = CONF_FORMS[conf.device.device_type.name]
1550 1552
1551 1553 if request.method == 'GET':
1552 1554 file_form = UploadFileForm()
1553 1555
1554 1556 if request.method == 'POST':
1555 1557 file_form = UploadFileForm(request.POST, request.FILES)
1556 1558
1557 1559 if file_form.is_valid():
1558 1560
1559 1561 data = conf.import_from_file(request.FILES['file'])
1560 1562 parms = Params(data=data).get_conf(
1561 1563 dtype=conf.device.device_type.name)
1562 1564
1563 1565 if parms:
1564 1566
1565 1567 form = DevConfForm(initial=parms, instance=conf)
1566 1568
1567 1569 kwargs = {}
1568 1570 kwargs['id_dev'] = conf.id
1569 1571 kwargs['form'] = form
1570 1572 kwargs['title'] = 'Device Configuration'
1571 1573 kwargs['suptitle'] = 'Parameters imported'
1572 1574 kwargs['button'] = 'Save'
1573 1575 kwargs['action'] = conf.get_absolute_url_edit()
1574 1576 kwargs['previous'] = conf.get_absolute_url()
1575 1577
1576 1578 ###### SIDEBAR ######
1577 1579 kwargs.update(sidebar(conf=conf))
1578 1580
1579 1581 messages.success(
1580 1582 request, "Parameters imported from: '%s'." % request.FILES['file'].name)
1581 1583
1582 1584 return render(request, '%s_conf_edit.html' % conf.device.device_type.name, kwargs)
1583 1585
1584 1586 messages.error(request, "Could not import parameters from file")
1585 1587
1586 1588 kwargs = {}
1587 1589 kwargs['id_dev'] = conf.id
1588 1590 kwargs['title'] = 'Device Configuration'
1589 1591 kwargs['form'] = file_form
1590 1592 kwargs['suptitle'] = 'Importing file'
1591 1593 kwargs['button'] = 'Import'
1592 1594 kwargs['menu_configurations'] = 'active'
1593 1595
1594 1596 kwargs.update(sidebar(conf=conf))
1595 1597
1596 1598 return render(request, 'dev_conf_import.html', kwargs)
1597 1599
1598 1600
1599 1601 @login_required
1600 1602 def dev_conf_export(request, id_conf):
1601 1603
1602 1604 conf = get_object_or_404(Configuration, pk=id_conf)
1603 1605
1604 1606 if request.method == 'GET':
1605 1607 file_form = DownloadFileForm(conf.device.device_type.name)
1606 1608
1607 1609 if request.method == 'POST':
1608 1610 file_form = DownloadFileForm(
1609 1611 conf.device.device_type.name, request.POST)
1610 1612
1611 1613 if file_form.is_valid():
1612 1614 fields = conf.export_to_file(
1613 1615 format=file_form.cleaned_data['format'])
1614 1616 if not fields['content']:
1615 1617 messages.error(request, conf.message)
1616 1618 return redirect(conf.get_absolute_url_export())
1617 1619 response = HttpResponse(content_type=fields['content_type'])
1618 1620 response['Content-Disposition'] = 'attachment; filename="%s"' % fields['filename']
1619 1621 response.write(fields['content'])
1620 1622
1621 1623 return response
1622 1624
1623 1625 messages.error(request, "Could not export parameters")
1624 1626
1625 1627 kwargs = {}
1626 1628 kwargs['id_dev'] = conf.id
1627 1629 kwargs['title'] = 'Device Configuration'
1628 1630 kwargs['form'] = file_form
1629 1631 kwargs['suptitle'] = 'Exporting file'
1630 1632 kwargs['button'] = 'Export'
1631 1633 kwargs['menu_configurations'] = 'active'
1632 1634
1633 1635 return render(request, 'dev_conf_export.html', kwargs)
1634 1636
1635 1637
1636 1638 @login_required
1637 1639 def dev_conf_delete(request, id_conf):
1638 1640
1639 1641 conf = get_object_or_404(Configuration, pk=id_conf)
1640 1642
1641 1643 if request.method == 'POST':
1642 1644 if is_developer(request.user):
1643 1645 conf.delete()
1644 1646 return redirect('url_dev_confs')
1645 1647
1646 1648 messages.error(request, 'Not enough permission to delete this object')
1647 1649 return redirect(conf.get_absolute_url())
1648 1650
1649 1651 kwargs = {
1650 1652 'title': 'Delete',
1651 1653 'suptitle': 'Configuration',
1652 1654 'object': conf,
1653 1655 'delete': True
1654 1656 }
1655 1657 kwargs['menu_configurations'] = 'active'
1656 1658
1657 1659 return render(request, 'confirm.html', kwargs)
1658 1660
1659 1661
1660 1662 def sidebar(**kwargs):
1661 1663
1662 1664 side_data = {}
1663 1665
1664 1666 conf = kwargs.get('conf', None)
1665 1667 experiment = kwargs.get('experiment', None)
1666 1668
1667 1669 if not experiment:
1668 1670 experiment = conf.experiment
1669 1671
1670 1672 if experiment:
1671 1673 side_data['experiment'] = experiment
1672 1674 campaign = experiment.campaign_set.all()
1673 1675 if campaign:
1674 1676 side_data['campaign'] = campaign[0]
1675 1677 experiments = campaign[0].experiments.all().order_by('name')
1676 1678 else:
1677 1679 experiments = [experiment]
1678 1680 configurations = experiment.configuration_set.filter(type=0)
1679 1681 side_data['side_experiments'] = experiments
1680 1682 side_data['side_configurations'] = configurations.order_by(
1681 1683 'device__device_type__name')
1682 1684
1683 1685 return side_data
1684 1686
1685 1687
1686 1688 def get_paginator(model, page, order, filters={}, n=8):
1687 1689
1688 1690 kwargs = {}
1689 1691 query = Q()
1690 1692 if isinstance(filters, QueryDict):
1691 1693 filters = filters.dict()
1692 1694 [filters.pop(key) for key in filters.keys() if filters[key] in ('', ' ')]
1693 1695 filters.pop('page', None)
1694 1696
1695 1697 fields = [f.name for f in model._meta.get_fields()]
1696 1698
1697 1699 if 'template' in filters:
1698 1700 filters['template'] = True
1699 1701 if 'historical' in filters:
1700 1702 filters.pop('historical')
1701 1703 filters['type'] = 1
1702 1704 elif 'type' in fields:
1703 1705 filters['type'] = 0
1704 1706 if 'start_date' in filters:
1705 1707 filters['start_date__gte'] = filters.pop('start_date')
1706 1708 if 'end_date' in filters:
1707 1709 filters['start_date__lte'] = filters.pop('end_date')
1708 1710 if 'tags' in filters:
1709 1711 tags = filters.pop('tags')
1710 1712 if 'tags' in fields:
1711 1713 query = query | Q(tags__icontains=tags)
1712 1714 if 'label' in fields:
1713 1715 query = query | Q(label__icontains=tags)
1714 1716 if 'location' in fields:
1715 1717 query = query | Q(location__name__icontains=tags)
1716 1718 if 'device' in fields:
1717 1719 query = query | Q(device__device_type__name__icontains=tags)
1718 1720 query = query | Q(device__location__name__icontains=tags)
1719 1721 if 'device_type' in fields:
1720 1722 query = query | Q(device_type__name__icontains=tags)
1721 1723
1722 1724 if 'mine' in filters:
1723 1725 filters['author_id'] = filters['mine']
1724 1726 filters.pop('mine')
1725 1727 object_list = model.objects.filter(query, **filters).order_by(*order)
1726 1728 paginator = Paginator(object_list, n)
1727 1729
1728 1730 try:
1729 1731 objects = paginator.page(page)
1730 1732 except PageNotAnInteger:
1731 1733 objects = paginator.page(1)
1732 1734 except EmptyPage:
1733 1735 objects = paginator.page(paginator.num_pages)
1734 1736
1735 1737 kwargs['objects'] = objects
1736 1738 kwargs['offset'] = (int(page)-1)*n if page else 0
1737 1739
1738 1740 return kwargs
1739 1741
1740 1742
1741 1743 def operation(request, id_camp=None):
1742 1744
1743 1745 kwargs = {}
1744 1746 kwargs['title'] = 'Radars Operation'
1745 1747 kwargs['no_sidebar'] = True
1746 1748 kwargs['menu_operation'] = 'active'
1747 1749 campaigns = Campaign.objects.filter(start_date__lte=datetime.now(),
1748 1750 end_date__gte=datetime.now()).order_by('-start_date')
1749 1751
1750 1752 if id_camp:
1751 1753 campaign = get_object_or_404(Campaign, pk=id_camp)
1752 1754 form = OperationForm(
1753 1755 initial={'campaign': campaign.id}, campaigns=campaigns)
1754 1756 kwargs['campaign'] = campaign
1755 1757 else:
1756 1758 # form = OperationForm(campaigns=campaigns)
1757 1759 kwargs['campaigns'] = campaigns
1758 1760 return render(request, 'operation.html', kwargs)
1759 1761
1760 1762 #---Experiment
1761 1763 keys = ['id', 'name', 'start_time', 'end_time', 'status']
1762 1764 kwargs['experiment_keys'] = keys[1:]
1763 1765 kwargs['experiments'] = experiments
1764 1766 #---Radar
1765 1767 kwargs['locations'] = campaign.get_experiments_by_radar()
1766 1768 kwargs['form'] = form
1767 1769
1768 1770 return render(request, 'operation.html', kwargs)
1769 1771
1770 1772
1771 1773 @login_required
1772 1774 def radar_start(request, id_camp, id_radar):
1773 1775
1774 1776 campaign = get_object_or_404(Campaign, pk=id_camp)
1775 1777 experiments = campaign.get_experiments_by_radar(id_radar)[0]['experiments']
1776 1778 now = datetime.now()
1777 1779 for exp in experiments:
1778 1780 start = datetime.combine(datetime.now().date(), exp.start_time)
1779 1781 end = datetime.combine(datetime.now().date(), exp.end_time)
1780 1782 if end < start:
1781 1783 end += timedelta(1)
1782 1784
1783 1785 if exp.status == 2:
1784 1786 messages.warning(
1785 1787 request, 'Experiment {} already running'.format(exp))
1786 1788 continue
1787 1789
1788 1790 if exp.status == 3:
1789 1791 messages.warning(
1790 1792 request, 'Experiment {} already programmed'.format(exp))
1791 1793 continue
1792 1794
1793 1795 if start > campaign.end_date or start < campaign.start_date:
1794 1796 messages.warning(request, 'Experiment {} out of date'.format(exp))
1795 1797 continue
1796 1798
1797 1799 if now > start and now <= end:
1798 1800 exp.status = 3
1799 1801 exp.save()
1800 1802 task = task_start.delay(exp.id)
1801 1803 exp.status = task.wait()
1802 1804 if exp.status == 0:
1803 1805 messages.error(request, 'Experiment {} not start'.format(exp))
1804 1806 if exp.status == 2:
1805 1807 messages.success(request, 'Experiment {} started'.format(exp))
1806 1808 else:
1807 1809 task = task_start.apply_async(
1808 1810 (exp.pk, ), eta=start+timedelta(hours=5))
1809 1811 exp.task = task.id
1810 1812 exp.status = 3
1811 1813 messages.success(
1812 1814 request, 'Experiment {} programmed to start at {}'.format(exp, start))
1813 1815
1814 1816 exp.save()
1815 1817
1816 1818 return HttpResponseRedirect(reverse('url_operation', args=[id_camp]))
1817 1819
1818 1820
1819 1821 @login_required
1820 1822 def radar_stop(request, id_camp, id_radar):
1821 1823
1822 1824 campaign = get_object_or_404(Campaign, pk=id_camp)
1823 1825 experiments = campaign.get_experiments_by_radar(id_radar)[0]['experiments']
1824 1826
1825 1827 for exp in experiments:
1826 1828
1827 1829 if exp.task:
1828 1830 app.control.revoke(exp.task)
1829 1831 if exp.status == 2:
1830 1832 exp.stop()
1831 1833 messages.warning(request, 'Experiment {} stopped'.format(exp))
1832 1834 exp.status = 1
1833 1835 exp.save()
1834 1836
1835 1837 return HttpResponseRedirect(reverse('url_operation', args=[id_camp]))
1836 1838
1837 1839
1838 1840 @login_required
1839 1841 def radar_refresh(request, id_camp, id_radar):
1840 1842
1841 1843 campaign = get_object_or_404(Campaign, pk=id_camp)
1842 1844 experiments = campaign.get_experiments_by_radar(id_radar)[0]['experiments']
1843 1845
1844 for exp in experiments:
1845 exp.get_status()
1846 i = app.control.inspect()
1847 scheduled = i.scheduled().values[0]
1848 revoked = i.revoked().values[0]
1846 1849
1850 for exp in experiments:
1851 if exp.task in revoked:
1852 exp.status = 1
1853 elif exp.task in [t['request']['id'] for t in scheduled if 'task_start' in t['request']['name']]:
1854 exp.status = 2
1855 elif exp.task in [t['request']['id'] for t in scheduled if 'task_stop' in t['request']['name']]:
1856 exp.status = 3
1857 else:
1858 exp.status = 4
1859 exp.save()
1847 1860 return HttpResponseRedirect(reverse('url_operation', args=[id_camp]))
1848 1861
1849 1862
1850 1863 def real_time(request):
1851 1864
1852 1865 graphic_path = "/home/fiorella/Pictures/catwbeanie.jpg"
1853 1866
1854 1867 kwargs = {}
1855 1868 kwargs['title'] = 'CLAIRE'
1856 1869 kwargs['suptitle'] = 'Real Time'
1857 1870 kwargs['no_sidebar'] = True
1858 1871 kwargs['graphic_path'] = graphic_path
1859 1872 kwargs['graphic1_path'] = 'http://www.bluemaize.net/im/girls-accessories/shark-beanie-11.jpg'
1860 1873
1861 1874 return render(request, 'real_time.html', kwargs)
1862 1875
1863 1876 def theme(request, theme):
1864 1877
1865 1878 user = request.user
1866 1879 user.profile.theme = theme
1867 1880 user.save()
1868 1881 return redirect('index') No newline at end of file
General Comments 0
You need to be logged in to leave comments. Login now