##// END OF EJS Templates
jespinoza -
r314:8d83194b6bd7 merge
parent child
Show More
@@ -0,0 +1,2
1 @echo off
2 cmd /k "cd /d E:\jars_api & python jars_server.py" No newline at end of file
This diff has been collapsed as it changes many lines, (773 lines changed) Show them Hide them
@@ -0,0 +1,773
1 '''
2 Created on Jan 5, 2016
3
4 @author: Juan C. Espinoza
5
6 '''
7
8 import os
9 import math
10 import json
11 import requests
12 import time
13
14 from threading import Thread
15 from subprocess import Popen, PIPE
16 from collections import deque
17 from datetime import datetime, timedelta
18
19 from flask import Flask, jsonify, request, send_file
20
21 PATH = 'F:\SIR_DATA'
22 EXE = 'C:\JROAdquisicion\src\JROAcquisitionSoftware\Release\JROAcquisitionSoftware.exe'
23 IPHOST='10.10.10.165'
24 OPT = '--jars' #'--cbsim'
25 PROC = False
26 OUT = None
27 LOGGING = False
28 global EXPNAME
29
30 DECODE_TYPE = {1:'DECODING_TIME_DOMAIN',2:'DECODING_FREQ_DOMAIN',3:'DECODING_INV_FREQ_DOMAIN'}
31
32 app = Flask(__name__)
33
34 class StdoutReader(object):
35 '''
36 Class to manage stdout of JARS acquisition program
37 '''
38
39 def __init__(self, stream, name):
40 '''
41 stream: the stream to read from.
42 Usually a process' stdout or stderr.
43 '''
44
45 self._s = stream
46 self._q = deque()
47 self._f = open(os.path.join(PATH, name, 'Restarting Report.txt'), 'ab')
48 if LOGGING:
49 self._l = open(os.path.join(PATH, name, '{}.log'.format(name)), 'ab')
50
51 def update_queue(stream, queue):
52 '''
53 Collect lines from 'stream' and put them in 'queue'.
54 '''
55
56 restart_dict = {}
57 restart_num = 0
58 str_format = '%Y-%m-%d %H:%M:%S'
59 delta_time = timedelta(0,120,0)
60 while True:
61 raw = stream.readline()
62 line = raw.rstrip()
63 now = datetime.now()
64 now_str = now.strftime(str_format)
65 restart_dict[str(restart_num)] = now_str
66 max_num = 13
67 if line:
68 queue.append(line)
69 if LOGGING:
70 self._l.write('{}'.format(raw))
71 print line
72 if 'Block' not in line:
73 self._f.write('{} at {}\n'.format(line,
74 datetime.now().ctime()))
75
76 restart_num = restart_num + 1
77 if restart_num > max_num:
78 date1 = datetime.strptime(restart_dict['1'], str_format)
79 date2 = datetime.strptime(restart_dict[str(max_num-1)], str_format)
80 if (date2 - date1) < delta_time:
81 print str(max_num)+' restarts en menos de 2min'#RESTART
82 restart_num = 0
83 restart_dict = {}
84 restart()
85 else:
86 restart_num = 0
87 restart_dict = {}
88 print 'NO'
89
90
91 self._t = Thread(target=update_queue, args=(self._s, self._q))
92 self._t.daemon = True
93 self._t.start()
94
95 def readline(self):
96 '''
97 Return last line output
98 '''
99 try:
100 line = self._q.pop()
101 self._q.clear()
102 return line
103 except IndexError:
104 return None
105
106 def save(self):
107 '''
108 Save logging files
109 '''
110 self._f.close()
111 if LOGGING:
112 self._l.close()
113
114 def parse_line(n, data, lines):
115
116 line_text = ''
117 line_type = data['lines']['byId'][lines[n]]['line_type']
118 num = n+1
119 if line_type == 'windows':
120 if num == 7:
121 reference = data['lines']['byId'][lines[n]]['params']['TX_ref']
122 windows = data['lines']['byId'][lines[n]]['params']['params']
123 if windows:
124 dh = str(float(windows[0]['resolution']))
125 else:
126 dh = ''
127
128 line_text = 'Sampling Windows={}\n'.format(len(windows))
129
130 cnt = 0
131 for window in windows:
132 line_text += ('H0({cnt})={first_height}\n'
133 'NSA({cnt})={number_of_samples}\n'
134 'DH({cnt})={dh}\n'.format(
135 cnt=cnt,
136 first_height=window['first_height'],
137 number_of_samples=int(window['number_of_samples']),
138 dh=dh
139 )
140 )
141 cnt += 1
142
143 else:
144 reference = data['lines']['byId'][lines[n]]['params']['TX_ref']
145 windows = data['lines']['byId'][lines[n]]['params']['params']
146 if windows:
147 dh = str(float(windows[0]['resolution']))
148 else:
149 dh = ''
150
151 line_text = 'Sampling Windows (Line {})={}\n'.format(num, len(windows))
152
153 cnt = 0
154 for window in windows:
155 line_text += ('L{num}_H0({cnt})={first_height}\n'
156 'L{num}_NSA({cnt})={number_of_samples}\n'
157 'L{num}_DH({cnt})={dh}\n'.format(
158 num=num,
159 cnt=cnt,
160 first_height=window['first_height'],
161 number_of_samples=int(window['number_of_samples']),
162 dh=dh
163 )
164 )
165 cnt += 1
166
167 line_text += 'L{}_REFERENCE={}\n'.format(
168 num,
169 data['lines']['byId'][reference]['name']
170 )
171
172 elif line_type == 'sync':
173 line_text = 'Line{}=Synchro\n'.format(num)
174
175 elif line_type == 'flip':
176 line_text = 'L{}_FLIP={}\n'.format(
177 num,
178 data['lines']['byId'][lines[n]]['params']['number_of_flips']
179 )
180
181 elif line_type == 'prog_pulses':
182 periodic = data['lines']['byId'][lines[n]]['params']['periodic']
183 if periodic == '0':
184 periodic = 'NO'
185 else:
186 periodic = 'YES'
187
188 portions = data['lines']['byId'][lines[n]]['params']['params']
189 line_text = 'L{} Number Of Portions={}\n'.format(num, len(portions))
190
191 for i, portion in enumerate(portions):
192 line_text += 'PORTION_BEGIN({cnt})={begin}\nPORTION_END({cnt})={end}\n'.format(
193 cnt=i,
194 begin=int(portion['begin']),
195 end=int(portion['end']),
196 )
197
198 line_text += 'L{} Portions IPP Periodic={}\n'.format(num, periodic)
199
200 elif line_type == 'none':
201 line_text = ''
202
203 else:
204 reference = data['lines']['byId'][lines[n]]['params']['TX_ref']
205 code_type = data['lines']['byId'][lines[n]]['params']['code']
206 codes = data['lines']['byId'][lines[n]]['params']['codes']
207
208 if num == 4:
209 line_text = 'Code Type={}\n'.format(code_type)
210 line_text += 'Number of Codes={}\nCode Width={}\n'.format(
211 len(codes),
212 len(codes[0])
213 )
214 cnt = 0
215 for code in codes:
216 line_text += 'COD({})={}\n'.format(cnt, code)
217 cnt += 1
218 else:
219 line_text = 'Code Type (Line {})={}\n'.format(num, code_type)
220 line_text += 'Number of Codes (Line {})={}\nCode Width (Line {})={}\n'.format(
221 num,
222 len(codes),
223 num,
224 len(codes[0])
225 )
226 cnt = 0
227 for code in codes:
228 line_text += 'L{}_COD({})={}\n'.format(num,cnt, code)
229 cnt += 1
230
231 line_text += 'L{}_REFERENCE={}\n'.format(
232 num,
233 data['lines']['byId'][reference]['name']
234 )
235
236 return line_text
237
238 def create_jarsfiles(json_data):
239 """
240 Function to create *.racp and *.jars files with json_data
241 """
242 global EXPNAME
243
244 data = json.loads(json_data)
245 exp_id = data['experiments']['allIds'][0]
246 experiment = data['experiments']['byId'][exp_id]
247 name = experiment['name']
248 EXPNAME = name
249 folder_name = os.path.join(PATH, name)
250 print 'Experiment: ' + name + ' received...'
251 if not os.path.exists(folder_name):
252 os.makedirs(folder_name)
253 if not os.path.exists(folder_name+'/DATA'):
254 os.mkdir(folder_name+'/DATA')
255
256 try:
257 json_file = open(folder_name+'/'+name+'_jars.json', 'w')
258 except:
259 return 0, 'Error creating .json file'
260
261 json_file.write(json_data)
262 json_file.close()
263
264 try:
265 racp_file = open(folder_name+'/'+name+'_jars.racp', 'w')
266 except:
267 return 0, 'Error creating .racp file'
268
269 conf_ids = data['configurations']['allIds']
270
271 rcs = [pk for pk in conf_ids \
272 if data['configurations']['byId'][pk]['device_type'] == 'rc']
273 if len(rcs) == 1:
274 rc_id = rcs[0]
275 rc_mix_id = 0
276 else:
277 rcs = [pk for pk in conf_ids \
278 if data['configurations']['byId'][pk]['device_type'] == 'rc' and data['configurations']['byId'][pk]['mix'] == True]
279 rc_mix_id = rcs[0]
280 mix_parameters = data['configurations']['byId'][rc_mix_id]['parameters'].split('-')
281 rc_id = mix_parameters[0].split('|')[0]
282
283 jars_id = [pk for pk in conf_ids \
284 if data['configurations']['byId'][pk]['device_type'] == 'jars'][0]
285
286 rc = data['configurations']['byId'][rc_id]
287 jars = data['configurations']['byId'][jars_id]
288
289 if rc_mix_id <> 0:
290 rc_mix = data['configurations']['byId'][rc_mix_id]
291 mix_text = '*******Mixed Experiment*******************\n'
292 mix_text += 'Number of Experiments={}\n'.format(len(mix_parameters))
293 for i,param in enumerate(mix_parameters):
294 pk, mode, op, delay, mask = param.split('|')
295 mix_text += 'EXP({})={}\n'.format(i, data['configurations']['byId'][pk]['name'])
296 mix_text += 'DELAY({})={}\n'.format(i, delay)
297 mix_text += 'RELOJ={}\n'.format(int(data['configurations']['byId'][pk]['clock']))
298 mix_text += 'MIXER MODE={}_FLAG\n'.format(op)
299 mix_text += 'MIXER MASK={}\n'.format(mask)
300 mix_text += '*******System parameters******************\n'
301 else:
302 mix_text = ''
303
304 exp_type = jars['exp_type']
305 if exp_type == 0:
306 exp_type = 'EXP_RAW_DATA'
307 else:
308 exp_type = 'EXP_PROCESS_SPECTRA'
309
310 racp_text = 'EXPERIMENT TYPE={}\nEXPERIMENT NAME={}\nHEADER VERSION=1103\n'.format(
311 exp_type,
312 name
313 )
314
315 racp_text += '*****Radar Controller Parameters**********\n{}'.format(mix_text)
316 if rc_mix_id == 0:
317 racp_text += 'IPP={}\n'.format(float(rc['ipp']))
318 racp_text += 'NTX={}\n'.format(rc['ntx'])
319 else:
320 racp_text += 'IPP={}\n'.format(float(rc_mix['ipp']))
321 racp_text += 'NTX={}\n'.format(rc_mix['ntx'])
322
323 racp_text += 'TXA={}\n'.format(
324 data['lines']['byId'][rc['lines'][1]]['params']['pulse_width']
325 )
326 if data['lines']['byId'][rc['lines'][2]]['line_type'] == 'tx':
327 racp_text += 'TXB={}\n'.format(
328 data['lines']['byId'][rc['lines'][2]]['params']['pulse_width']
329 )
330 idTR = data['lines']['byId'][rc['lines'][0]]['params']['TX_ref']
331 rangeTR = data['lines']['byId'][rc['lines'][0]]['params']['range']
332
333 if rangeTR != '0':
334 racp_text += 'Pulse selection_TR={}\n'.format(rangeTR)
335 elif idTR != '0':
336 racp_text += 'Pulse selection_TR={}\n'.format(
337 data['lines']['byId'][idTR]['name'][-1]
338 )
339 rangeTXA = data['lines']['byId'][rc['lines'][1]]['params']['range']
340 if rangeTXA != '0':
341 racp_text += 'Pulse selection_TXA={}\n'.format(rangeTXA)
342 if data['lines']['byId'][rc['lines'][2]]['line_type'] == 'tx':
343 rangeTXB = data['lines']['byId'][rc['lines'][2]]['params']['range']
344 if rangeTXB != '0':
345 racp_text += 'Pulse selection_TXB={}\n'.format(rangeTXB)
346 for n in range(3, 6):
347 racp_text += parse_line(n, data, rc['lines'])
348
349 if data['lines']['byId'][rc['lines'][2]]['line_type'] == 'tx':
350 taus = data['lines']['byId'][rc['lines'][2]]['params']['delays'].split(',')
351 if taus != '0':
352 racp_text += 'Number of Taus={}\n'.format(len(taus))
353 for n, tau in enumerate(taus):
354 racp_text += 'TAU({})={}\n'.format(n, tau)
355
356 racp_text += parse_line(6, data, rc['lines'])
357 racp_text += 'SAMPLING REFERENCE=MIDDLE OF FIRST SUB-BAUD\n'
358 racp_text += 'RELOJ={}\n'.format(int(rc['clock']))
359 racp_text += 'CLOCK DIVIDER={}\n'.format(int(rc['clock_divider']))
360 racp_text += 'TR_BEFORE={}\n'.format(rc['time_before'])
361 racp_text += 'TR_AFTER={}\n'.format(rc['time_after'])
362 racp_text += 'WINDOW IN LINE 5&6=NO\n'
363 racp_text += '******System Parameters*******************\n'
364 racp_text += 'Number of Cards={}\n'.format(jars['cards_number'])
365
366 for i in range(jars['cards_number']):
367 racp_text += 'Card({})={}\n'.format(i, i)
368
369 channels = jars['channels'].split(',')
370
371 if channels:
372 racp_text += 'Number of Channels={}\n'.format(len(channels))
373 for i, channel in enumerate(channels):
374 racp_text += 'Channel({})={}\n'.format(i, channel)
375
376 if exp_type == 'EXP_RAW_DATA':
377 racp_text += 'RAW DATA DIRECTORY={}\n'.format(os.path.join(folder_name, 'DATA'))
378 else:
379 racp_text += 'PROCESS DATA DIRECTORY={}\n'.format(os.path.join(folder_name, 'DATA'))
380
381 if jars['create_directory']:
382 racp_text += 'CREATE DIRECTORY PER DAY=YES'+'\n'
383 else:
384 racp_text += 'CREATE DIRECTORY PER DAY=NO'+'\n'
385
386 if jars['include_expname']:
387 racp_text += 'INCLUDE EXPNAME IN DIRECTORY=YES'+'\n'
388 else:
389 racp_text += 'INCLUDE EXPNAME IN DIRECTORY=NO'+'\n'
390
391 racp_text += '******System Parameters*******************\n'
392 racp_text += 'ADC Resolution=8\n'
393 racp_text += 'PCI DIO BusWidth=32\n'
394
395 if exp_type == 'EXP_RAW_DATA':
396 racp_text += 'RAW DATA BLOCKS={}\n'.format(jars['raw_data_blocks'])
397 spectra_text = ''
398 else:
399 racp_text += 'PROCESS DATA BLOCKS=100\n'
400 spectra_text = '------------------------------------------\n'
401
402 if jars['fftpoints'] > 1:
403 spectra_text += 'FFTPOINTS={}\n'.format(jars['fftpoints'])
404
405 if jars['incohe_integr']:
406 spectra_text += 'INCOHERENT INTEGRATIONS={}\n'.format(jars['incohe_integr'])
407
408 if jars['save_ch_dc']:
409 spectra_text += 'SAVE CHANNELS DC=YES\n'
410
411 dum = jars['spectral']
412
413 if dum.endswith(','):
414 dum = dum[:-1]
415 spectral = json.loads('[{}]'.format(dum))
416
417 if spectral:
418 spectra_text += '------------------------------------------\n'
419 spectra_text += 'TOTAL SPECTRAL COMBINATIONS={}\n'.format(len(spectral))
420 for i, spc in enumerate(spectral):
421 spectra_text += 'SPEC_COMB({})={},{}\n'.format(i, *spc)
422
423 racp_text += '******Process Parameters******************\n'
424
425 data_type = jars['data_type']
426
427 if data_type == 0:
428 racp_text += 'DATATYPE=SHORT\n'
429 elif data_type == 1:
430 racp_text += 'DATATYPE=FLOAT\n'
431
432 racp_text += 'DATA ARRANGE=CONTIGUOUS_CH\n'
433
434 if jars['cohe_integr'] > 1:
435 racp_text += 'COHERENT INTEGRATIONS={}\n'.format(jars['cohe_integr'])
436
437 decode_text = ''
438 decode_data = jars['decode_data']
439 if decode_data !=0:
440 decode_text = 'DECODE DATA=YES\n'
441 decode_text += 'DECODING TYPE={}\n'.format(DECODE_TYPE[decode_data])
442 if jars['post_coh_int'] == True:
443 decode_text += 'POST COHERENT INTEGRATIONS=YES\n'
444 decode_text += '------------------------------------------\n'
445
446 racp_text += 'COHERENT INTEGRATION STRIDE={}\n'.format(jars['cohe_integr_str'])
447 racp_text += '------------------------------------------\n'
448 racp_text += 'ACQUIRED PROFILES={}\n'.format(jars['acq_profiles'])
449 racp_text += 'PROFILES PER BLOCK={}\n'.format(jars['profiles_block'])
450 racp_text += spectra_text
451 racp_text += '------------------------------------------\n'
452 racp_text += decode_text
453 racp_text += 'BEGIN ON START=NO\n'
454 racp_text += 'BEGIN_TIME={}\n'.format(experiment['start_time'][:-3])
455 racp_text += 'END_TIME={}\n'.format(experiment['end_time'][:-3])
456 racp_text += 'GENERATE ACQUISITION LINK=YES\n'
457 racp_text += 'VIEW RAW DATA=YES\n'
458 racp_text += 'REFRESH RATE=1\n'
459 racp_text += '------------------------------------------\n'
460 racp_text += 'SEND STATUS TO FTP=YES\n'
461 racp_text += 'FTP SERVER=jro.igp.gob.pe\n'
462 racp_text += 'FTP USER=wmaster\n'
463 racp_text += 'FTP PASSWD=PKQLX20\n'
464 racp_text += 'FTP DIR=/users/database/on-line/\n'
465 racp_text += 'FTP FILE=status.txt\n'
466 racp_text += 'FTP INTERVAL={}\n'.format(jars['ftp_interval'])
467 racp_text += 'SAVE STATUS AND BLOCK=YES\n'
468 racp_text += 'GENERATE RTI=YES\n'
469 racp_text += 'RTI Inc.Int.=1\n'
470 racp_text += 'SEND RTI AND BLOCK=YES\n'
471 racp_text += '------------------------------------------\n'
472 racp_text += 'COMPORT CONFIG=Com1 CBR_9600 TWOSTOPBITS NOPARITY\n'
473 racp_text += 'JAM CONFIGURE FILE=dmasg_pprofiles_pch_64_pdigi_6clk.jam\n'
474 racp_text += 'ACQUISITION SYSTEM=JARS\n'
475 racp_text += '************JARS CONFIGURATION PARAMETERS************\n'
476
477 #-------------------------JARS FILTER---------------------------------------
478 filter_parms = jars['filter_parms']
479 if filter_parms.__class__.__name__ == 'unicode':
480 filter_parms = eval(filter_parms)
481 elif filter_parms.__class__.__name__ == 'str':
482 filter_parms = eval(filter_parms)
483 if filter_parms.__class__.__name__ == 'str':
484 filter_parms = eval(filter_parms)
485 try:
486 fclock = float(filter_parms['clock'])
487 fch = float(filter_parms['fch'])
488 m_dds = float(filter_parms['mult'])
489 M_CIC2 = float(filter_parms['filter_2'])
490 M_CIC5 = float(filter_parms['filter_5'])
491 M_RCF = float(filter_parms['filter_fir'])
492 except:
493 fclock = eval(filter_parms['clock'])
494 fch = eval(filter_parms['fch'])
495 m_dds = eval(filter_parms['mult'])
496 M_CIC2 = eval(filter_parms['filter_2'])
497 M_CIC5 = eval(filter_parms['filter_5'])
498 M_RCF = eval(filter_parms['filter_fir'])
499
500 filter_text = 'Loading\n'
501 filter_text += 'Impulse file found -> C:\jars\F1MHZ_8_MATCH.imp\n'
502 filter_text += 'Autoscale off\n'
503 filter_text += 'Initialize Printer Port\n'
504 filter_text += 'Chip Hardware Reset\n'
505 filter_text += '300h -> 1\n'
506 filter_text += '301h -> 6\n'
507 filter_text += '302h -> 11111111111111111111111111111111\n'
508
509 if abs(fch) < (fclock/2):
510 nco = (2**32)*((fch/fclock))#%1)
511 nco_i = long(nco)
512 else:
513 nco = (2**32)*(fclock-fch)/(fclock)
514 nco_i = long(nco)
515
516 filter_text += '303h -> {}\n'.format(nco_i)
517 filter_text += '304h -> 0\n'
518
519 input_level = 1
520 S_CIC2 = math.ceil(math.log((M_CIC2**2)*input_level)/math.log(2))
521 if S_CIC2 < 0:
522 S_CIC2 = 0
523 if S_CIC2 > 7:
524 S_CIC2 = 7
525
526 filter_text += '305h -> {}\n'.format(int(S_CIC2))
527 filter_text += '306h -> {}\n'.format(int(M_CIC2-1))
528
529 OL_CIC2 = input_level/(2.0**S_CIC2)
530
531 S_CIC5 = math.ceil(math.log((M_CIC5**5)*OL_CIC2)/math.log(2))-5
532 if S_CIC5 < 0:
533 S_CIC5 = 0
534 if S_CIC5 > 7:
535 S_CIC5 = 7
536
537 OL_CIC5 = ((M_CIC5**5)/(2**(S_CIC5+5)))*OL_CIC2
538
539 filter_text += '307h -> {}\n'.format(int(S_CIC5))
540 filter_text += '308h -> {}\n'.format(int(M_CIC5-1))
541
542 Gain = 1
543 S_RCF = int(4.0-math.log(Gain)/math.log(2))
544 if S_RCF < 0:
545 S_RCF = 0
546 if S_RCF > 7:
547 S_RCF = 7
548
549 filter_text += '309h -> {}\n'.format(S_RCF)
550 filter_text += '30Ah -> {}\n'.format(int(M_RCF-1))
551
552 Offset = 0
553 filter_text += '30Bh -> {}\n'.format(Offset)
554
555 ntaps = int(M_RCF)
556 filter_text += '30Ch -> {}\n'.format(ntaps-1)
557 filter_text += '30Dh -> 0\n'
558
559 fsamp = fclock/(M_CIC2*M_CIC5*M_RCF)
560
561 tap = int(2.0*((2**19)-1)/(ntaps*OL_CIC5))
562 for p in range(0, ntaps):
563 filter_text += ' {} -> {}\n'.format(p, int(math.ceil(tap)))#filter_text += ' {} -> {}\n'.format(p, int(math.ceil(hn)))
564
565 filter_text += 'RCF Gain -> .999996185302734\n'
566 filter_text += 'Chip Restarted:\n'
567 filter_text += '300h -> 1\n'
568 filter_text += '300h -> 0'
569
570 filter_name = '{}_{}MHz_clock{}MHz_F{}MHz_{}_{}_{}.jars'.format(
571 abs(fch),
572 int((abs(fch)-abs(int(fch)))*1000),
573 fclock,
574 round(fsamp,3),
575 M_CIC2,
576 M_CIC5,
577 M_RCF
578 )
579
580 jars_file = open(os.path.join(folder_name, filter_name), 'wb')
581 jars_file.write(filter_text)
582 jars_file.close()
583 racp_text += 'JARS_FILTER={}\n'.format(os.path.join(folder_name, filter_name))
584 racp_text += 'MARK WIDTH=2\n'
585 racp_text += 'GENERATE OWN SAMPLING WINDOW=NO\n'
586
587 if jars['save_data']:
588 racp_text += 'SAVE DATA=YES\n'
589 else:
590 racp_text += 'SAVE DATA=NO\n'
591
592 racp_text += 'RC_STOP_SEQUENCE=255,0\n'
593 racp_text += 'RC_START_SEQUENCE=255,24\n'
594
595 racp_file.write(racp_text)
596 racp_file.close()
597
598 return 1, racp_file.name
599
600 @app.route('/status/')
601 def status():
602 '''
603 0 : Not configured/running
604 3 : Running and acquiring data
605 2 : Configured
606 1 : Connected
607 '''
608
609 name = request.args.get('name', None)
610 global EXPNAME
611 EXPNAME = name
612
613 if name is None:
614 return jsonify({
615 'status': 1,
616 'message': 'JARS Connected, missing experiment'
617 })
618 else:
619 racp_file = os.path.join(PATH, name, '{}_jars.racp'.format(name))
620
621 if name and not os.path.exists(racp_file):
622 return jsonify({
623 'status': 1,
624 'message': 'JARS not configured'
625 })
626 elif os.path.exists(racp_file) and hasattr(PROC, 'pid'):
627 if PROC.poll() is None:
628 status = 3
629 msg = 'Process: PID={}, OUT={}'.format(
630 PROC.pid,
631 OUT.readline()
632 )
633 else:
634 status = 2
635 msg = 'JARS Configured'
636 else:
637 status = 2
638 msg = 'JARS Configured'
639
640 return jsonify({
641 'status': status,
642 'message': msg
643 })
644
645 @app.route('/start/', methods=['POST'])
646 def start():
647 '''
648 '''
649
650 global PROC
651 global OUT
652 global EXPNAME
653
654 name = request.json['name']
655 EXPNAME = name
656 racp_file = os.path.join(PATH, name, '{}_jars.racp'.format(name))
657 if hasattr(PROC, 'pid') and PROC.poll() is None:
658 status = 3
659 msg = 'JARS already running'
660 elif os.path.exists(racp_file):
661 PROC = Popen([EXE, '-rf', racp_file, OPT], stdout=PIPE)
662 OUT = StdoutReader(PROC.stdout, name)
663 status = 3
664 msg = 'JARS starting ok'
665 elif not os.path.exists(racp_file):
666 status = 1
667 msg = 'Experiment: {} not configured'.format(name)
668
669 return jsonify({
670 'status': status,
671 'message': msg
672 })
673
674 @app.route('/stop/', methods=['POST'])
675 def stop():
676 '''
677 '''
678
679 global PROC
680
681 if hasattr(PROC, 'pid'):
682 if PROC.poll() is None:
683 OUT.save()
684 PROC.kill()
685 status = 2
686 msg = 'JARS stopped OK'
687 else:
688 status = 1
689 msg = 'JARS not running'
690 else:
691 status = 1
692 msg = 'JARS not running'
693
694 return jsonify({
695 'status': status,
696 'message': msg
697 })
698
699 @app.route('/write/', methods=['POST'])
700 def write():
701 '''
702 '''
703 status = 1
704 json_data = json.loads(request.json)
705 conf_ids = json_data['configurations']['allIds']
706 for pk in conf_ids:
707 if json_data['configurations']['byId'][pk]['device_type'] == 'jars':
708 data = json_data['configurations']['byId'][pk]['filter_parms']
709
710 if request.json:
711 try:
712 ret, racp = create_jarsfiles(request.json)
713 except Exception as e:
714 ret = 0
715 msg = str(e)
716 else:
717 msg = 'Missing POST data'
718
719 if ret == 1:
720 status = 2
721 msg = 'JARS configured OK'
722 else:
723 msg = ret
724
725 return jsonify({
726 'status': status,
727 'message': msg
728 })
729
730
731 def restart():
732 '''
733 '''
734
735 global EXPNAME
736 #ip_host = '10.10.10.99'
737 port = 5000
738 route_stop = 'http://'+IPHOST+':'+str(port)+'/stop/'
739 stop = requests.post(route_stop, data={})
740 print 'Restarting...'
741 time.sleep(3)
742 route_start = 'http://'+IPHOST+':'+str(port)+'/start/'
743 start = requests.post(route_start, json={'name':EXPNAME})
744
745 return
746
747 @app.route('/get_log/')
748 def get_log():
749 '''
750 This function sends Restarting Report.txt of the Experiment.
751 '''
752
753 name = request.args.get('name', None)
754 global EXPNAME
755 EXPNAME = name
756
757 if name is None:
758 return jsonify({
759 'status': 1,
760 'message': 'JARS Connected, missing experiment'
761 })
762 else:
763 try:
764 rr_file = os.path.join(PATH, name, 'Restarting Report.txt')
765 return send_file(rr_file, attachment_filename='Restarting Report.txt')
766 except Exception as e:
767 return jsonify({
768 'status': 1,
769 'message': str(e)
770 })
771
772 if __name__ == '__main__':
773 app.run(debug=True, host='0.0.0.0')
@@ -1,11 +1,12
1 1 REDIS_HOST=radarsys-redis
2 2 REDIS_PORT=6379
3 3 POSTGRES_DB_NAME=radarsys
4 4 POSTGRES_PORT_5432_TCP_ADDR=radarsys-postgres
5 5 POSTGRES_PORT_5432_TCP_PORT=5432
6 6 POSTGRES_USER=docker
7 7 POSTGRES_PASSWORD=docker
8 8 PGDATA=/var/lib/postgresql/data
9 9 LC_ALL=C.UTF-8
10 10 TZ=America/Lima
11 DOCKER_DATA=/Volumes/dockers/radarsys/
11 DOCKER_DATA=/data/dockers/radarsys/
12 LOCAL_IP=192.168.1.128
@@ -1,4 +1,6
1 1 migrations/
2 .DS_Store
3 *.sqlite
2 4 .vscode/
3 5 *.pyc
4 6 .env
@@ -1,878 +1,878
1 1 from django.db import models
2 2 from apps.main.models import Configuration
3 3 from django.core.urlresolvers import reverse
4 4 # Create your models here.
5 5 from celery.execute import send_task
6 6 from datetime import datetime
7 7 import ast
8 8 import socket
9 9 import json
10 10 import requests
11 11 import struct
12 import sys, time
12 import os, sys, time
13 13
14 14 import multiprocessing
15 15
16 16
17 17 antenna_default = json.dumps({
18 18 "antenna_up": [[0.0,0.0,0.0,0.0,0.5,0.5,0.5,0.5],
19 19 [0.0,0.0,0.0,0.0,0.5,0.5,0.5,0.5],
20 20 [0.0,0.0,0.0,0.0,0.5,0.5,0.5,0.5],
21 21 [0.0,0.0,0.0,0.0,0.5,0.5,0.5,0.5],
22 22 [0.5,0.5,0.5,0.5,1.0,1.0,1.0,1.0],
23 23 [0.5,0.5,0.5,0.5,1.0,1.0,1.0,1.0],
24 24 [0.5,0.5,0.5,0.5,1.0,1.0,1.0,1.0],
25 25 [0.5,0.5,0.5,0.5,1.0,1.0,1.0,1.0]
26 26 ]
27 27 ,
28 28 "antenna_down": [[0.0,0.0,0.0,0.0,0.5,0.5,0.5,0.5],
29 29 [0.0,0.0,0.0,0.0,0.5,0.5,0.5,0.5],
30 30 [0.0,0.0,0.0,0.0,0.5,0.5,0.5,0.5],
31 31 [0.0,0.0,0.0,0.0,0.5,0.5,0.5,0.5],
32 32 [0.5,0.5,0.5,0.5,3.0,3.0,3.0,3.0],
33 33 [0.5,0.5,0.5,0.5,3.0,3.0,3.0,3.0],
34 34 [0.5,0.5,0.5,0.5,3.0,3.0,3.0,3.0],
35 35 [0.5,0.5,0.5,0.5,3.0,3.0,3.0,3.0]],
36 36 })
37 37
38 38
39 39 tx_default = json.dumps({
40 40 "up": [[1,1,1,1,0,0,0,0],
41 41 [1,1,1,1,0,0,0,0],
42 42 [1,1,1,1,0,0,0,0],
43 43 [1,1,1,1,0,0,0,0],
44 44 [0,0,0,0,1,1,1,1],
45 45 [0,0,0,0,1,1,1,1],
46 46 [0,0,0,0,1,1,1,1],
47 47 [0,0,0,0,1,1,1,1]],
48 48
49 49 "down": [[1,1,1,1,0,0,0,0],
50 50 [1,1,1,1,0,0,0,0],
51 51 [1,1,1,1,0,0,0,0],
52 52 [1,1,1,1,0,0,0,0],
53 53 [0,0,0,0,1,1,1,1],
54 54 [0,0,0,0,1,1,1,1],
55 55 [0,0,0,0,1,1,1,1],
56 56 [0,0,0,0,1,1,1,1]],
57 57 })
58 58
59 59 rx_default = json.dumps({
60 60 "up": [[1,1,1,1,0,0,0,0],
61 61 [1,1,1,1,0,0,0,0],
62 62 [1,1,1,1,0,0,0,0],
63 63 [1,1,1,1,0,0,0,0],
64 64 [0,0,0,0,1,1,1,1],
65 65 [0,0,0,0,1,1,1,1],
66 66 [0,0,0,0,1,1,1,1],
67 67 [0,0,0,0,1,1,1,1]],
68 68
69 69 "down": [[1,1,1,1,0,0,0,0],
70 70 [1,1,1,1,0,0,0,0],
71 71 [1,1,1,1,0,0,0,0],
72 72 [1,1,1,1,0,0,0,0],
73 73 [0,0,0,0,1,1,1,1],
74 74 [0,0,0,0,1,1,1,1],
75 75 [0,0,0,0,1,1,1,1],
76 76 [0,0,0,0,1,1,1,1]],
77 77 })
78 78
79 79 status_default = '0000000000000000000000000000000000000000000000000000000000000000'
80 80 default_messages = {}
81 81
82 82 for i in range(1,65):
83 83 default_messages[str(i)] = "Module "+str(i)
84 84
85 85
86 86 ues_default = json.dumps({
87 87 "up": [0.533333,0.00000,1.06667,0.00000],
88 88 "down": [0.533333,0.00000,1.06667,0.00000]
89 89 })
90 90
91 91 onlyrx_default = json.dumps({
92 92 "up": False,
93 93 "down": False
94 94 })
95 95
96 96 def up_convertion(cadena):
97 97 valores = []
98 98 for c in cadena:
99 99 if c == 1.0: valores=valores+['000']
100 100 if c == 2.0: valores=valores+['001']
101 101 if c == 3.0: valores=valores+['010']
102 102 if c == 0.0: valores=valores+['011']
103 103 if c == 0.5: valores=valores+['100']
104 104 if c == 1.5: valores=valores+['101']
105 105 if c == 2.5: valores=valores+['110']
106 106 if c == 3.5: valores=valores+['111']
107 107
108 108 return valores
109 109
110 110 def up_conv_bits(value):
111 111
112 112 if value == 1.0: bits="000"
113 113 if value == 2.0: bits="001"
114 114 if value == 3.0: bits="010"
115 115 if value == 0.0: bits="011"
116 116 if value == 0.5: bits="100"
117 117 if value == 1.5: bits="101"
118 118 if value == 2.5: bits="110"
119 119 if value == 3.5: bits="111"
120 120
121 121 return bits
122 122
123 123 def down_convertion(cadena):
124 124 valores = []
125 125 for c in cadena:
126 126 if c == 1.0: valores=valores+['000']
127 127 if c == 2.0: valores=valores+['001']
128 128 if c == 3.0: valores=valores+['010']
129 129 if c == 0.0: valores=valores+['011']
130 130 if c == 0.5: valores=valores+['100']
131 131 if c == 1.5: valores=valores+['101']
132 132 if c == 2.5: valores=valores+['110']
133 133 if c == 3.5: valores=valores+['111']
134 134
135 135 return valores
136 136
137 137 def down_conv_bits(value):
138 138
139 139 if value == 1.0: bits="000"
140 140 if value == 2.0: bits="001"
141 141 if value == 3.0: bits="010"
142 142 if value == 0.0: bits="011"
143 143 if value == 0.5: bits="100"
144 144 if value == 1.5: bits="101"
145 145 if value == 2.5: bits="110"
146 146 if value == 3.5: bits="111"
147 147
148 148 return bits
149 149
150 150 def up_conv_value(bits):
151 151
152 152 if bits == "000": value=1.0
153 153 if bits == "001": value=2.0
154 154 if bits == "010": value=3.0
155 155 if bits == "011": value=0.0
156 156 if bits == "100": value=0.5
157 157 if bits == "101": value=1.5
158 158 if bits == "110": value=2.5
159 159 if bits == "111": value=3.5
160 160
161 161 return value
162 162
163 163 def down_conv_value(bits):
164 164
165 165 if bits == "000": value=1.0
166 166 if bits == "001": value=2.0
167 167 if bits == "010": value=3.0
168 168 if bits == "011": value=0.0
169 169 if bits == "100": value=0.5
170 170 if bits == "101": value=1.5
171 171 if bits == "110": value=2.5
172 172 if bits == "111": value=3.5
173 173
174 174 return value
175 175
176 176 def ip2position(module_number):
177 177 j=0
178 178 i=0
179 179 for x in range(0,module_number-1):
180 180 j=j+1
181 181 if j==8:
182 182 i=i+1
183 183 j=0
184 184
185 185 pos = [i,j]
186 186 return pos
187 187
188 188
189 189 def fromBinary2Char(binary_string):
190 190 number = int(binary_string, 2)
191 191 #Plus 33 to avoid more than 1 characters values such as: '\x01'-'\x1f'
192 192 number = number + 33
193 193 char = chr(number)
194 194 return char
195 195
196 196 def fromChar2Binary(char):
197 197 number = ord(char) - 33
198 198 #Minus 33 to get the real value
199 199 bits = bin(number)[2:]
200 200 #To ensure we have a string with 6bits
201 201 if len(bits) < 6:
202 202 bits = bits.zfill(6)
203 203 return bits
204 204
205 205 OPERATION_MODES = (
206 206 (0, 'Manual'),
207 207 (1, 'Automatic'),
208 208 )
209 209
210 210
211 211 class ABSConfiguration(Configuration):
212 212 active_beam = models.PositiveSmallIntegerField(verbose_name='Active Beam', default=0)
213 213 module_status = models.CharField(verbose_name='Module Status', max_length=10000, default=json.dumps(status_default))
214 214 operation_mode = models.PositiveSmallIntegerField(verbose_name='Operation Mode', choices=OPERATION_MODES, default = 0)
215 215 operation_value = models.FloatField(verbose_name='Periodic (seconds)', default="10", null=True, blank=True)
216 216 module_messages = models.CharField(verbose_name='Modules Messages', max_length=10000, default=json.dumps(default_messages))
217 217
218 218 class Meta:
219 219 db_table = 'abs_configurations'
220 220
221 221 def get_absolute_url_plot(self):
222 222 return reverse('url_plot_abs_patterns', args=[str(self.id)])
223 223
224 224
225 225 def parms_to_dict(self):
226 226
227 227 parameters = {}
228 228
229 229 parameters['device_id'] = self.device.id
230 230 parameters['name'] = self.name
231 231 parameters['device_type'] = self.device.device_type.name
232 232 parameters['beams'] = {}
233 233
234 234 beams = ABSBeam.objects.filter(abs_conf=self)
235 235 b=1
236 236 for beam in beams:
237 237 #absbeam = ABSBeam.objects.get(pk=beams[beam])
238 238 parameters['beams']['beam'+str(b)] = beam.parms_to_dict()#absbeam.parms_to_dict()
239 239 b+=1
240 240
241 241 return parameters
242 242
243 243
244 244 def dict_to_parms(self, parameters):
245 245
246 246 self.name = parameters['name']
247 247
248 248 absbeams = ABSBeam.objects.filter(abs_conf=self)
249 249 beams = parameters['beams']
250 250
251 251 if absbeams:
252 252 beams_number = len(beams)
253 253 absbeams_number = len(absbeams)
254 254 if beams_number==absbeams_number:
255 255 i = 1
256 256 for absbeam in absbeams:
257 257 absbeam.dict_to_parms(beams['beam'+str(i)])
258 258 i = i+1
259 259 elif beams_number > absbeams_number:
260 260 i = 1
261 261 for absbeam in absbeams:
262 262 absbeam.dict_to_parms(beams['beam'+str(i)])
263 263 i=i+1
264 264 for x in range(i,beams_number+1):
265 265 new_beam = ABSBeam(
266 266 name =beams['beam'+str(i)]['name'],
267 267 antenna =json.dumps(beams['beam'+str(i)]['antenna']),
268 268 abs_conf = self,
269 269 tx =json.dumps(beams['beam'+str(i)]['tx']),
270 270 rx =json.dumps(beams['beam'+str(i)]['rx']),
271 271 ues =json.dumps(beams['beam'+str(i)]['ues']),
272 272 only_rx =json.dumps(beams['beam'+str(i)]['only_rx'])
273 273 )
274 274 new_beam.save()
275 275 i=i+1
276 276 else: #beams_number < absbeams_number:
277 277 i = 1
278 278 for absbeam in absbeams:
279 279 if i <= beams_number:
280 280 absbeam.dict_to_parms(beams['beam'+str(i)])
281 281 i=i+1
282 282 else:
283 283 absbeam.delete()
284 284 else:
285 285 for beam in beams:
286 286 new_beam = ABSBeam(
287 287 name =beams[beam]['name'],
288 288 antenna =json.dumps(beams[beam]['antenna']),
289 289 abs_conf = self,
290 290 tx =json.dumps(beams[beam]['tx']),
291 291 rx =json.dumps(beams[beam]['rx']),
292 292 ues =json.dumps(beams[beam]['ues']),
293 293 only_rx =json.dumps(beams[beam]['only_rx'])
294 294 )
295 295 new_beam.save()
296 296
297 297
298 298
299 299 def update_from_file(self, parameters):
300 300
301 301 self.dict_to_parms(parameters)
302 302 self.save()
303 303
304 304
305 305 def get_beams(self, **kwargs):
306 306 '''
307 307 This function returns ABS Configuration beams
308 308 '''
309 309 return ABSBeam.objects.filter(abs_conf=self.pk, **kwargs)
310 310
311 311 def clone(self, **kwargs):
312 312
313 313 beams = self.get_beams()
314 314 self.pk = None
315 315 self.id = None
316 316 for attr, value in kwargs.items():
317 317 setattr(self, attr, value)
318 318 self.save()
319 319
320 320 for beam in beams:
321 321 beam.clone(abs_conf=self)
322 322
323 323 #-----For Active Beam-----
324 324 new_beams = ABSBeam.objects.filter(abs_conf=self)
325 325 self.active_beam = new_beams[0].id
326 326 self.save()
327 327 #-----For Active Beam-----
328 328 #-----For Device Status---
329 329 self.device.status = 3
330 330 self.device.save()
331 331 #-----For Device Status---
332 332
333 333 return self
334 334
335 335
336 336 def start_device(self):
337 337
338 338 if self.device.status == 3:
339 339
340 340 try:
341 341 #self.write_device()
342 342 send_task('task_change_beam', [self.id],)
343 343 self.message = 'ABS running'
344 344
345 345 except Exception as e:
346 346 self.message = str(e)
347 347 return False
348 348
349 349 return True
350 350
351 351 else:
352 352 self.message = 'Please, select Write ABS Device first.'
353 353 return False
354 354
355 355
356 356 def stop_device(self):
357 357
358 358 self.device.status = 2
359 359 self.device.save()
360 360 self.message = 'ABS has been stopped.'
361 361 self.save()
362 362
363 363 return True
364 364
365 365
366 366 def write_device(self):
367 367
368 368 """
369 369 This function sends the beams list to every abs module.
370 370 It needs 'module_conf' function
371 371 """
372 372
373 373 beams = ABSBeam.objects.filter(abs_conf=self)
374 374 nbeams = len(beams)
375 375 if self.connected_modules() == 0 :
376 376 self.message = "No ABS Module detected."
377 377 return False
378 378
379 379 #-------------Write each abs module-----------
380 380
381 381 if beams:
382 382 block_id = 0
383 383 message = 'SNDF{:03d}{:02d}{:02d}'.format(nbeams, nbeams, block_id)
384 384 for i, status in enumerate(self.module_status):
385 385 message += ''.join([fromBinary2Char(beam.module_6bits(i)) for beam in beams])
386 386 status = ['0'] * 64
387 387 n = 0
388 388
389 389 sock = self.send_multicast(message)
390 390
391 391 for i in range(32):
392 392 try:
393 393 data, address = sock.recvfrom(1024)
394 394 print address, data
395 395 if data == '1':
396 396 status[int(address[0][10:])-1] = '3'
397 397 elif data == '0':
398 398 status[int(address[0][10:])-1] = '1'
399 399 except:
400 400 n += 1
401 401 sock.close()
402 402 else:
403 403 self.message = "ABS Configuration does not have beams"
404 404 return False
405 405
406 406 if n == 64:
407 407 self.message = "Could not write ABS Modules"
408 408 self.device.status = 0
409 409 self.module_status = ''.join(status)
410 410 self.save()
411 411 return False
412 412 else:
413 413 self.message = "ABS Beams List have been sent to ABS Modules"
414 414 self.active_beam = beams[0].pk
415 415
416 416 self.device.status = 3
417 417 self.module_status = ''.join(status)
418 418 self.save()
419 419 return True
420 420
421 421
422 422 def read_module(self, module):
423 423
424 424 """
425 425 Read out-bits (up-down) of 1 abs module NOT for Configuration
426 426 """
427 427
428 428 ip_address = self.device.ip_address
429 429 ip_address = ip_address.split('.')
430 430 module_seq = (ip_address[0],ip_address[1],ip_address[2])
431 431 dot = '.'
432 432 module_ip = dot.join(module_seq)+'.'+str(module)
433 433 module_port = self.device.port_address
434 434 read_route = 'http://'+module_ip+':'+str(module_port)+'/read'
435 435
436 436 module_status = json.loads(self.module_status)
437 437 print(read_route)
438 438
439 439 module_bits = ''
440 440
441 441 try:
442 442 r_read = requests.get(read_route, timeout=0.5)
443 443 answer = r_read.json()
444 444 module_bits = answer['allbits']
445 445 except:
446 446 return {}
447 447
448 448 return module_bits
449 449
450 450 def read_device(self):
451 451
452 452 parms = {}
453 453 # Reads active modules.
454 454 module_status = json.loads(self.module_status)
455 455 total = 0
456 456 for status in module_status:
457 457 if module_status[status] != 0:
458 458 module_bits = self.read_module(int(status))
459 459 bits={}
460 460 if module_bits:
461 461 bits = (str(module_bits['um2']) + str(module_bits['um1']) + str(module_bits['um0']) +
462 462 str(module_bits['dm2']) + str(module_bits['dm1']) + str(module_bits['dm0']) )
463 463 parms[str(status)] = bits
464 464
465 465 total +=1
466 466
467 467 if total==0:
468 468 self.message = "No ABS Module detected. Please select 'Status'."
469 469 return False
470 470
471 471
472 472
473 473 self.message = "ABS Modules have been read"
474 474 #monitoreo_tx = JROABSClnt_01CeCnMod000000MNTR10
475 475 return parms
476 476
477 477
478 478 def connected_modules(self):
479 479 """
480 480 This function returns the number of connected abs-modules without updating.
481 481 """
482 482 num = 0
483 483 print(self.module_status)
484 484 for i, status in enumerate(self.module_status):
485 485 if status != '0':
486 486 num += 1
487 487 #print('status {}:{}'.format(i+1, status))
488 488 return num
489 489
490 490 def send_multicast(self, message):
491 491
492 492 multicast_group = ('224.3.29.71', 10000)
493 493 # Create the datagram socket
494 494 sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
495 495 sock.settimeout(0.5)
496 local_ip = "192.168.1.128"
497 sock.bind((local_ip, 10000))
496 # sock.bind((local_ip, 10000))
497 local_ip = os.environ.get('LOCAL_IP', '127.0.0.1')
498 498 sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_IF, socket.inet_aton(local_ip))
499 499 sent = sock.sendto(message, multicast_group)
500 500 print('Sending ' + message)
501 501 return sock
502 502
503 503 def status_device(self):
504 504 """
505 505 This function returns the status of all abs-modules as one.
506 506 If at least one module is connected, its answer is "1"
507 507 """
508 508
509 509 sock = self.send_multicast('MNTR')
510 510
511 511 n = 0
512 512 status = ['0'] * 64
513 513 for i in range(32):
514 514 #if True:
515 515 try:
516 516 data, address = sock.recvfrom(1024)
517 517 print address, data
518 518 if data == '1':
519 519 status[int(address[0][10:])-1] = '3'
520 520 elif data == '0':
521 521 status[int(address[0][10:])-1] = '1'
522 522 n += 1
523 523 print('Module: {} connected'.format(address))
524 524 except:
525 525 print('Module: {} error'.format(address))
526 526 pass
527 527 sock.close()
528 528
529 529 if n > 0:
530 530 self.message = 'ABS modules Status have been updated.'
531 531 self.device.status = 1
532 532 else:
533 533 self.device.status = 0
534 534 self.message = 'No ABS module is connected.'
535 535 self.module_status = ''.join(status)
536 536 self.save()
537 537
538 538 return self.device.status
539 539
540 540
541 541 def send_beam(self, beam_pos):
542 542 """
543 543 This function connects to a multicast group and sends the beam number
544 544 to all abs modules.
545 545 """
546 546
547 547 # Se manda a cero RC para poder realizar cambio de beam
548 548 if self.experiment is None:
549 549 confs = []
550 550 else:
551 551 confs = Configuration.objects.filter(experiment = self.experiment).filter(type=0)
552 552 confdds = ''
553 553 confjars = ''
554 554 confrc = ''
555 555 print 'Starting...', self.experiment
556 556 #TO STOP DEVICES: DDS-JARS-RC
557 557 for i in range(0,len(confs)):
558 558 print i
559 559 if i==0:
560 560 for conf in confs:
561 561 if conf.device.device_type.name == 'dds':
562 562 confdds = conf
563 563 confdds.stop_device()
564 564 break
565 565 if i==1:
566 566 for conf in confs:
567 567 if conf.device.device_type.name == 'jars':
568 568 confjars = conf
569 569 confjars.stop_device()
570 570 break
571 571 if i==2:
572 572 for conf in confs:
573 573 print conf
574 574 if conf.device.device_type.name == 'rc':
575 575 confrc = conf
576 576 confrc.stop_device()
577 577 break
578 578 print 'Stop devices'
579 579 if beam_pos > 0:
580 580 beam_pos = beam_pos - 1
581 581 else:
582 582 beam_pos = 0
583 583
584 584 #El indice del apunte debe ser menor que el numero total de apuntes
585 585 #El servidor tcp en el embebido comienza a contar desde 0
586 586 status = ['0'] * 64
587 587 message = 'CHGB{}'.format(beam_pos)
588 588 print 'Before send'
589 589 sock = self.send_multicast(message)
590 590 print 'Waiting'
591 591 for i in range(32):
592 592 try:
593 593 data, address = sock.recvfrom(1024)
594 594 print address, data
595 595 if data == '1':
596 596 status[int(address[0][10:])-1] = '3'
597 597 elif data == '0':
598 598 status[int(address[0][10:])-1] = '1'
599 599 except:
600 600 pass
601 601
602 602 sock.close()
603 603
604 604 #Start DDS-RC-JARS
605 605 if confdds:
606 606 confdds.start_device()
607 607 if confrc:
608 608 #print confrc
609 609 confrc.start_device()
610 610 if confjars:
611 611 confjars.start_device()
612 612
613 613 self.message = "ABS Beam has been changed"
614 614 self.module_status = ''.join(status)
615 615 self.save()
616 616 return True
617 617
618 618
619 619 def get_absolute_url_import(self):
620 620 return reverse('url_import_abs_conf', args=[str(self.id)])
621 621
622 622
623 623 class ABSBeam(models.Model):
624 624
625 625 name = models.CharField(max_length=60, default='Beam')
626 626 antenna = models.CharField(verbose_name='Antenna', max_length=1000, default=antenna_default)
627 627 abs_conf = models.ForeignKey(ABSConfiguration, null=True, verbose_name='ABS Configuration')
628 628 tx = models.CharField(verbose_name='Tx', max_length=1000, default=tx_default)
629 629 rx = models.CharField(verbose_name='Rx', max_length=1000, default=rx_default)
630 630 s_time = models.TimeField(verbose_name='Star Time', default='00:00:00')
631 631 e_time = models.TimeField(verbose_name='End Time', default='23:59:59')
632 632 ues = models.CharField(verbose_name='Ues', max_length=100, default=ues_default)
633 633 only_rx = models.CharField(verbose_name='Only RX', max_length=40, default=onlyrx_default)
634 634
635 635 class Meta:
636 636 db_table = 'abs_beams'
637 637
638 638 def __unicode__(self):
639 639 return u'%s' % (self.name)
640 640
641 641 def parms_to_dict(self):
642 642
643 643 parameters = {}
644 644 parameters['name'] = self.name
645 645 parameters['antenna'] = ast.literal_eval(self.antenna)
646 646 parameters['abs_conf'] = self.abs_conf.name
647 647 parameters['tx'] = ast.literal_eval(self.tx)
648 648 parameters['rx'] = ast.literal_eval(self.rx)
649 649 parameters['s_time'] = self.s_time.strftime("%H:%M:%S")
650 650 parameters['e_time'] = self.e_time.strftime("%H:%M:%S")
651 651 parameters['ues'] = ast.literal_eval(self.ues)
652 652 parameters['only_rx'] = json.loads(self.only_rx)
653 653
654 654 return parameters
655 655
656 656 def dict_to_parms(self, parameters):
657 657
658 658 self.name = parameters['name']
659 659 self.antenna = json.dumps(parameters['antenna'])
660 660 #self.abs_conf = parameters['abs_conf']
661 661 self.tx = json.dumps(parameters['tx'])
662 662 self.rx = json.dumps(parameters['rx'])
663 663 #self.s_time = parameters['s_time']
664 664 #self.e_time = parameters['e_time']
665 665 self.ues = json.dumps(parameters['ues'])
666 666 self.only_rx = json.dumps(parameters['only_rx'])
667 667 self.save()
668 668
669 669
670 670 def clone(self, **kwargs):
671 671
672 672 self.pk = None
673 673 self.id = None
674 674 for attr, value in kwargs.items():
675 675 setattr(self, attr, value)
676 676
677 677 self.save()
678 678
679 679 return self
680 680
681 681
682 682 def module_6bits(self, module):
683 683 """
684 684 This function reads antenna pattern and choose 6bits (upbits-downbits) for one abs module
685 685 """
686 686 module += 1
687 687 if module > 64:
688 688 beam_bits = ""
689 689 return beam_bits
690 690
691 691 data = ast.literal_eval(self.antenna)
692 692 up_data = data['antenna_up']
693 693 down_data = data['antenna_down']
694 694
695 695 pos = ip2position(module)
696 696 up_value = up_data[pos[0]][pos[1]]
697 697 down_value = down_data[pos[0]][pos[1]]
698 698
699 699 up_bits = up_conv_bits(up_value)
700 700 down_bits = down_conv_bits(down_value)
701 701 beam_bits = up_bits+down_bits
702 702
703 703 return beam_bits
704 704
705 705
706 706 @property
707 707 def get_upvalues(self):
708 708 """
709 709 This function reads antenna pattern and show the up-value of one abs module
710 710 """
711 711
712 712 data = ast.literal_eval(self.antenna)
713 713 up_data = data['antenna_up']
714 714
715 715 up_values = []
716 716 for data in up_data:
717 717 for i in range(0,8):
718 718 up_values.append(data[i])
719 719
720 720 return up_values
721 721
722 722 @property
723 723 def antenna_upvalues(self):
724 724 """
725 725 This function reads antenna pattern and show the up - values of one abs beam
726 726 in a particular order
727 727 """
728 728 data = ast.literal_eval(self.antenna)
729 729 up_data = data['antenna_up']
730 730
731 731 return up_data
732 732
733 733 @property
734 734 def antenna_downvalues(self):
735 735 """
736 736 This function reads antenna pattern and show the down - values of one abs beam
737 737 in a particular order
738 738 """
739 739 data = ast.literal_eval(self.antenna)
740 740 down_data = data['antenna_down']
741 741
742 742 return down_data
743 743
744 744 @property
745 745 def get_downvalues(self):
746 746 """
747 747 This function reads antenna pattern and show the down-value of one abs module
748 748 """
749 749
750 750 data = ast.literal_eval(self.antenna)
751 751 down_data = data['antenna_down']
752 752
753 753 down_values = []
754 754 for data in down_data:
755 755 for i in range(0,8):
756 756 down_values.append(data[i])
757 757
758 758 return down_values
759 759
760 760 @property
761 761 def get_up_ues(self):
762 762 """
763 763 This function shows the up-ues-value of one beam
764 764 """
765 765 data = ast.literal_eval(self.ues)
766 766 up_ues = data['up']
767 767
768 768 return up_ues
769 769
770 770 @property
771 771 def get_down_ues(self):
772 772 """
773 773 This function shows the down-ues-value of one beam
774 774 """
775 775 data = ast.literal_eval(self.ues)
776 776 down_ues = data['down']
777 777
778 778 return down_ues
779 779
780 780 @property
781 781 def get_up_onlyrx(self):
782 782 """
783 783 This function shows the up-onlyrx-value of one beam
784 784 """
785 785 data = json.loads(self.only_rx)
786 786 up_onlyrx = data['up']
787 787
788 788 return up_onlyrx
789 789
790 790 @property
791 791 def get_down_onlyrx(self):
792 792 """
793 793 This function shows the down-onlyrx-value of one beam
794 794 """
795 795 data = json.loads(self.only_rx)
796 796 down_onlyrx = data['down']
797 797
798 798 return down_onlyrx
799 799
800 800 @property
801 801 def get_tx(self):
802 802 """
803 803 This function shows the tx-values of one beam
804 804 """
805 805 data = json.loads(self.tx)
806 806
807 807 return data
808 808
809 809 @property
810 810 def get_uptx(self):
811 811 """
812 812 This function shows the up-tx-values of one beam
813 813 """
814 814 data = json.loads(self.tx)
815 815 up_data = data['up']
816 816
817 817 up_values = []
818 818 for data in up_data:
819 819 for i in range(0,8):
820 820 up_values.append(data[i])
821 821
822 822 return up_values
823 823
824 824 @property
825 825 def get_downtx(self):
826 826 """
827 827 This function shows the down-tx-values of one beam
828 828 """
829 829 data = json.loads(self.tx)
830 830 down_data = data['down']
831 831
832 832 down_values = []
833 833 for data in down_data:
834 834 for i in range(0,8):
835 835 down_values.append(data[i])
836 836
837 837 return down_values
838 838
839 839
840 840
841 841 @property
842 842 def get_rx(self):
843 843 """
844 844 This function shows the rx-values of one beam
845 845 """
846 846 data = json.loads(self.rx)
847 847
848 848 return data
849 849
850 850 @property
851 851 def get_uprx(self):
852 852 """
853 853 This function shows the up-rx-values of one beam
854 854 """
855 855 data = json.loads(self.rx)
856 856 up_data = data['up']
857 857
858 858 up_values = []
859 859 for data in up_data:
860 860 for i in range(0,8):
861 861 up_values.append(data[i])
862 862
863 863 return up_values
864 864
865 865 @property
866 866 def get_downrx(self):
867 867 """
868 868 This function shows the down-rx-values of one beam
869 869 """
870 870 data = json.loads(self.rx)
871 871 down_data = data['down']
872 872
873 873 down_values = []
874 874 for data in down_data:
875 875 for i in range(0,8):
876 876 down_values.append(data[i])
877 877
878 878 return down_values
@@ -1,343 +1,335
1 1 import json
2 2 import requests
3 3
4 4 from django.db import models
5 5 from django.core.validators import MinValueValidator, MaxValueValidator
6 6 from django.core.urlresolvers import reverse
7 7
8 8 from apps.main.models import Configuration
9 9 from apps.main.utils import Params
10 10 from .utils import create_jarsfiles
11 11
12 12 # Create your models here.
13 13
14 14 EXPERIMENT_TYPE = (
15 15 (0, 'RAW_DATA'),
16 16 (1, 'PDATA'),
17 17 )
18 18
19 19 DATA_TYPE = (
20 20 (0, 'SHORT'),
21 21 (1, 'FLOAT'),
22 22 )
23 23
24 24 DECODE_TYPE = (
25 25 (0, 'None'),
26 26 (1, 'TimeDomain'),
27 27 (2, 'FreqDomain'),
28 28 (3, 'InvFreqDomain'),
29 29 )
30 30
31 31 class JARSfilter(models.Model):
32 32
33 33 JARS_NBITS = 32
34 34
35 35 name = models.CharField(max_length=60, unique=True, default='')
36 36 clock = models.FloatField(verbose_name='Clock In (MHz)',validators=[MinValueValidator(5), MaxValueValidator(75)], null=True, default=60)
37 37 mult = models.PositiveIntegerField(verbose_name='Multiplier',validators=[MinValueValidator(1), MaxValueValidator(20)], default=5)
38 38 fch = models.FloatField(verbose_name='Frequency (MHz)', validators=[MaxValueValidator(150)], null=True, default=49.9200)
39 39 fch_decimal = models.BigIntegerField(verbose_name='Frequency (Decimal)',validators=[MinValueValidator(-9223372036854775808), MaxValueValidator(2**JARS_NBITS-1)], null=True, default=721554505)
40 40 filter_2 = models.PositiveIntegerField(verbose_name='Filter 2',validators=[MinValueValidator(2), MaxValueValidator(100)], default = 10)
41 41 filter_5 = models.PositiveIntegerField(verbose_name='Filter 5',validators=[MinValueValidator(1), MaxValueValidator(100)], default = 1)
42 42 filter_fir = models.PositiveIntegerField(verbose_name='FIR Filter',validators=[MinValueValidator(1), MaxValueValidator(100)], default = 6)
43 43
44 44 class Meta:
45 45 db_table = 'jars_filters'
46 46
47 47 def __unicode__(self):
48 48 return u'%s' % (self.name)
49 49
50 50 def parms_to_dict(self):
51 51
52 52 parameters = {}
53 53
54 54 #parameters['name'] = self.name
55 55 parameters['clock'] = float(self.clock)
56 56 parameters['mult'] = int(self.mult)
57 57 parameters['fch'] = float(self.fch)
58 58 parameters['fch_decimal'] = int(self.fch)
59 59 parameters['filter_fir'] = int(self.filter_fir)
60 60 parameters['filter_2'] = int(self.filter_2)
61 61 parameters['filter_5'] = int(self.filter_5)
62 62
63 63 return parameters
64 64
65 65 def dict_to_parms(self, parameters):
66 66
67 67 #self.name = parameters['name']
68 68 self.clock = parameters['clock']
69 69 self.mult = parameters['mult']
70 70 self.fch = parameters['fch']
71 71 self.fch_decimal = parameters['fch_decimal']
72 72 self.filter_fir = parameters['filter_fir']
73 73 self.filter_2 = parameters['filter_2']
74 74 self.filter_5 = parameters['filter_5']
75 75
76 76
77 77 class JARSConfiguration(Configuration):
78 78
79 79 ADC_RESOLUTION = 8
80 80 PCI_DIO_BUSWIDTH = 32
81 81 HEADER_VERSION = 1103
82 82 BEGIN_ON_START = True
83 83 REFRESH_RATE = 1
84 84
85 85 exp_type = models.PositiveIntegerField(verbose_name='Experiment Type', choices=EXPERIMENT_TYPE, default=0)
86 86 cards_number = models.PositiveIntegerField(verbose_name='Number of Cards', validators=[MinValueValidator(1), MaxValueValidator(4)], default = 1)
87 87 channels_number = models.PositiveIntegerField(verbose_name='Number of Channels', validators=[MinValueValidator(1), MaxValueValidator(8)], default = 5)
88 88 channels = models.CharField(verbose_name='Channels', max_length=15, default = '1,2,3,4,5')
89 89 data_type = models.PositiveIntegerField(verbose_name='Data Type', choices=DATA_TYPE, default=0)
90 90 raw_data_blocks = models.PositiveIntegerField(verbose_name='Raw Data Blocks', validators=[MaxValueValidator(5000)], default=60)
91 91 profiles_block = models.PositiveIntegerField(verbose_name='Profiles Per Block', default=400)
92 92 acq_profiles = models.PositiveIntegerField(verbose_name='Acquired Profiles', default=400)
93 93 ftp_interval = models.PositiveIntegerField(verbose_name='FTP Interval', default=60)
94 94 fftpoints = models.PositiveIntegerField(verbose_name='FFT Points',default=16)
95 95 cohe_integr_str = models.PositiveIntegerField(verbose_name='Coh. Int. Stride',validators=[MinValueValidator(1)], default=30)
96 96 cohe_integr = models.PositiveIntegerField(verbose_name='Coherent Integrations',validators=[MinValueValidator(1)], default=30)
97 97 incohe_integr = models.PositiveIntegerField(verbose_name='Incoherent Integrations',validators=[MinValueValidator(1)], default=30)
98 98 decode_data = models.PositiveIntegerField(verbose_name='Decode Data', choices=DECODE_TYPE, default=0)
99 99 post_coh_int = models.BooleanField(verbose_name='Post Coherent Integration', default=False)
100 100 spectral_number = models.PositiveIntegerField(verbose_name='# Spectral Combinations',validators=[MinValueValidator(1)], default=1)
101 101 spectral = models.CharField(verbose_name='Combinations', max_length=5000, default = '[0, 0],')
102 102 create_directory = models.BooleanField(verbose_name='Create Directory Per Day', default=True)
103 103 include_expname = models.BooleanField(verbose_name='Experiment Name in Directory', default=False)
104 104 #view_raw_data = models.BooleanField(verbose_name='View Raw Data', default=True)
105 105 save_ch_dc = models.BooleanField(verbose_name='Save Channels DC', default=True)
106 106 save_data = models.BooleanField(verbose_name='Save Data', default=True)
107 107 filter_parms = models.CharField(max_length=10000, default='{"clock": 60, "mult": 5, "fch": 49.92, "fch_decimal": 721554506, "filter_fir": 2, "filter_2": 12, "filter_5": 25}')
108 108
109 109 class Meta:
110 110 db_table = 'jars_configurations'
111 111
112 112 def filter_resolution(self):
113 113 filter_parms = eval(self.filter_parms)
114 114 if filter_parms.__class__.__name__=='str':
115 115 filter_parms = eval(filter_parms)
116 116
117 117 filter_clock = float(filter_parms['clock'])
118 118 filter_2 = filter_parms['filter_2']
119 119 filter_5 = filter_parms['filter_5']
120 120 filter_fir = filter_parms['filter_fir']
121 121
122 122 resolution = round((filter_clock/(filter_2*filter_5*filter_fir)),2)
123 123 return resolution
124 124
125 125 def dict_to_parms(self, params, id=None):
126 126
127 127 if id is not None:
128 128 data = Params(params).get_conf(id_conf=id)
129 129 else:
130 130 data = Params(params).get_conf(dtype='jars')
131 131 data['filter_parms'] = params['filter_parms']
132 132
133 133 self.name = data['name']
134 134 self.exp_type = data['exp_type']
135 135 #----PDATA----
136 136 if self.exp_type == 1:
137 137 self.incohe_integr = data['incohe_integr']
138 138 self.spectral_number = data['spectral_number']
139 139 self.spectral = data['spectral']
140 140 self.fftpoints = data['fftpoints']
141 141 self.save_ch_dc = data['save_ch_dc']
142 142 else:
143 143 self.raw_data_blocks = data['raw_data_blocks']
144 144 #----PDATA----
145 145 self.cards_number = data['cards_number']
146 146 self.channels_number = data['channels_number']
147 147 self.channels = data['channels']
148 148 self.data_type = data['data_type']
149 149 self.profiles_block = data['profiles_block']
150 150 self.acq_profiles = data['acq_profiles']
151 151 self.ftp_interval = data['ftp_interval']
152 152 self.cohe_integr_str = data['cohe_integr_str']
153 153 self.cohe_integr = data['cohe_integr']
154 154 #----DECODE----
155 155 self.decode_data = data['decode_data']
156 156 self.post_coh_int = data['post_coh_int']
157 157 #----DECODE----
158 158 self.create_directory = data['create_directory']
159 159 self.include_expname = data['include_expname']
160 160 self.save_data = data['save_data']
161 161 self.filter_parms = json.dumps(data['filter_parms'])
162 162
163 163 self.save()
164 164
165 165 def parms_to_text(self, file_format='jars'):
166 166
167 167 data = self.experiment.parms_to_dict()
168 168
169 169 for key in data['configurations']['allIds']:
170 170 if data['configurations']['byId'][key]['device_type'] in ('dds', 'cgs'):
171 171 data['configurations']['allIds'].remove(key)
172 172 data['configurations']['byId'].pop(key)
173 173 elif data['configurations']['byId'][key]['device_type'] == 'jars':
174 174 data['configurations']['byId'][key] = self.parms_to_dict()['configurations']['byId'][str(self.pk)]
175 175 elif data['configurations']['byId'][key]['device_type'] == 'rc':
176 176 data['configurations']['byId'][key]['pulses'] = ''
177 177 data['configurations']['byId'][key]['delays'] = ''
178 178 rc_ids = [pk for pk in data['configurations']['allIds'] if data['configurations']['byId'][pk]['device_type']=='rc']
179 179 mix_ids = [pk for pk in rc_ids if data['configurations']['byId'][pk]['mix']]
180 180
181 181 if mix_ids:
182 182 params = data['configurations']['byId'][mix_ids[0]]['parameters']
183 183 rc = data['configurations']['byId'][params.split('-')[0].split('|')[0]]
184 184 rc['mix'] = True
185 185 data['configurations']['byId'][rc['id']] = rc
186 186 elif len(rc_ids)==0:
187 187 self.message = 'File needs RC configuration'
188 188 return ''
189 189
190 190 json_data = json.dumps(data)
191 191 racp_file, filter_file = create_jarsfiles(json_data)
192 192 if file_format=='racp':
193 193 return racp_file
194 194
195 195 return filter_file
196 196
197 197 def request(self, cmd, method='get', **kwargs):
198 198
199 199 req = getattr(requests, method)(self.device.url(cmd), **kwargs)
200 200 payload = req.json()
201 201 return payload
202 202
203 203 def status_device(self):
204 204
205 205 try:
206 206 payload = self.request('status',
207 207 params={'name': self.experiment.name})
208 208 self.device.status = payload['status']
209 209 self.device.save()
210 210 self.message = payload['message']
211 211 except Exception as e:
212 212 self.device.status = 0
213 213 self.message = str(e)
214 214 self.device.save()
215 215 return False
216 216
217 217 return True
218 218
219 219 def stop_device(self):
220 220
221 221 try:
222 222 payload = self.request('stop', 'post')
223 223 self.device.status = payload['status']
224 224 self.device.save()
225 225 self.message = payload['message']
226 226 except Exception as e:
227 227 self.device.status = 0
228 228 self.message = str(e)
229 229 self.device.save()
230 230 return False
231 231
232 232 return True
233 233
234 234 def read_device(self):
235 235
236 236 try:
237 237 payload = self.request('read', params={'name': self.experiment.name})
238 238 self.message = 'Configuration loaded'
239 239 except:
240 240 self.device.status = 0
241 241 self.device.save()
242 242 self.message = 'Could not read JARS configuration.'
243 243 return False
244 244
245 245 return payload
246 246
247 247 def write_device(self):
248 248
249 249 if self.device.status == 3:
250 250 self.message = 'Could not configure device. Software Acquisition is running'
251 251 return False
252 252
253 253 data = self.experiment.parms_to_dict()
254 254
255 255 for key in data['configurations']['allIds']:
256 256 if data['configurations']['byId'][key]['device_type'] in ('dds', 'cgs'):
257 257 data['configurations']['allIds'].remove(key)
258 258 data['configurations']['byId'].pop(key)
259 elif data['configurations']['byId'][key]['device_type'] == 'jars':
260 data['configurations']['byId'][key] = self.parms_to_dict()['configurations']['byId'][str(self.pk)]
261 259 elif data['configurations']['byId'][key]['device_type'] == 'rc':
262 260 data['configurations']['byId'][key]['pulses'] = ''
263 261 data['configurations']['byId'][key]['delays'] = ''
264 262 rc_ids = [pk for pk in data['configurations']['allIds'] if data['configurations']['byId'][pk]['device_type']=='rc']
265 mix_ids = [pk for pk in rc_ids if data['configurations']['byId'][pk]['mix']]
266 if mix_ids:
267 params = data['configurations']['byId'][mix_ids[0]]['parameters']
268 rc = data['configurations']['byId'][params.split('-')[0].split('|')[0]]
269 rc['mix'] = True
270 data['configurations']['byId'][rc['id']] = rc
271 elif len(rc_ids)==0:
263 if len(rc_ids)==0:
272 264 self.message = 'Missing RC configuration'
273 265 return False
274 266
275 267 json_data = json.dumps(data)
276
268
277 269 try:
278 270 payload = self.request('write', 'post', json=json_data)
279 271 self.device.status = payload['status']
280 272 self.message = payload['message']
281 273 self.device.save()
282 274 if self.device.status == 1:
283 275 return False
284 276
285 277 except Exception as e:
286 278 self.device.status = 0
287 279 self.message = str(e)
288 280 self.device.save()
289 281 return False
290 282
291 283 return True
292 284
293 285 def start_device(self):
294 286
295 287 try:
296 288 payload = self.request('start', 'post',
297 289 json={'name': self.experiment.name})
298 290 self.device.status = payload['status']
299 291 self.message = payload['message']
300 292 self.device.save()
301 293 if self.device.status == 1:
302 294 return False
303 295
304 296 except Exception as e:
305 297 self.device.status = 0
306 298 self.message = str(e)
307 299 self.device.save()
308 300 return False
309 301
310 302 return True
311 303
312 304
313 305 def get_log(self):
314 306
315 307 payload = None
316 308
317 309 try:
318 310 payload = requests.get(self.device.url('get_log'), params={'name':self.experiment.name})
319 311 except:
320 312 self.device.status = 0
321 313 self.device.save()
322 314 self.message = 'Jars API is not running.'
323 315 return False
324 316
325 317 self.message = 'Jars API is running'
326 318
327 319 return payload
328 320
329 321
330 322 def update_from_file(self, filename):
331 323
332 324 f = JARSFile(filename)
333 325 self.dict_to_parms(f.data)
334 326 self.save()
335 327
336 328 def get_absolute_url_import(self):
337 329 return reverse('url_import_jars_conf', args=[str(self.id)])
338 330
339 331 def get_absolute_url_read(self):
340 332 return reverse('url_read_jars_conf', args=[str(self.id)])
341 333
342 334 def get_absolute_url_log(self):
343 335 return reverse('url_get_jars_log', args=[str(self.id)])
@@ -1,202 +1,202
1 1 from django import forms
2 2 from django.utils.safestring import mark_safe
3 3 from apps.main.models import Device, Experiment, Campaign, Location, Configuration
4 4 from django.template.defaultfilters import default
5 5
6 6 FILE_FORMAT = (
7 7 ('json', 'json'),
8 8 )
9 9
10 10 DDS_FILE_FORMAT = (
11 11 ('json', 'json'),
12 12 ('text', 'dds')
13 13 )
14 14
15 15 RC_FILE_FORMAT = (
16 16 ('json', 'json'),
17 17 ('text', 'racp'),
18 18 ('binary', 'dat'),
19 19 )
20 20
21 21 JARS_FILE_FORMAT = (
22 22 ('json', 'json'),
23 23 ('racp', 'racp'),
24 24 ('text', 'jars'),
25 25 )
26 26
27 27 def add_empty_choice(choices, pos=0, label='-----'):
28 28 if len(choices)>0:
29 29 choices = list(choices)
30 30 choices.insert(0, (0, label))
31 31 return choices
32 32 else:
33 33 return [(0, label)]
34 34
35 35 class DatepickerWidget(forms.widgets.TextInput):
36 36 def render(self, name, value, attrs=None):
37 37 input_html = super(DatepickerWidget, self).render(name, value, attrs)
38 38 html = '<div class="input-group date">'+input_html+'<span class="input-group-addon"><i class="glyphicon glyphicon-calendar"></i></span></div>'
39 39 return mark_safe(html)
40 40
41 41 class DateRangepickerWidget(forms.widgets.TextInput):
42 42 def render(self, name, value, attrs=None):
43 43 start = attrs['start_date']
44 44 end = attrs['end_date']
45 45 html = '''<div class="col-md-6 input-group date" style="float:inherit">
46 46 <input class="form-control" id="id_start_date" name="start_date" placeholder="Start" title="" type="text" value="{}">
47 47 <span class="input-group-addon"><i class="glyphicon glyphicon-calendar"></i></span>
48 48 </div>
49 49 <div class="col-md-6 input-group date" style="float:inherit">
50 50 <input class="form-control" id="id_end_date" name="end_date" placeholder="End" title="" type="text" value="{}">
51 51 <span class="input-group-addon"><i class="glyphicon glyphicon-calendar"></i></span>
52 52 </div>'''.format(start, end)
53 53 return mark_safe(html)
54 54
55 55 class TimepickerWidget(forms.widgets.TextInput):
56 56 def render(self, name, value, attrs=None):
57 57 input_html = super(TimepickerWidget, self).render(name, value, attrs)
58 58 html = '<div class="input-group time">'+input_html+'<span class="input-group-addon"><i class="glyphicon glyphicon-time"></i></span></div>'
59 59 return mark_safe(html)
60 60
61 61 class CampaignForm(forms.ModelForm):
62 62
63 63 experiments = forms.ModelMultipleChoiceField(widget=forms.CheckboxSelectMultiple(),
64 64 queryset=Experiment.objects.filter(template=True),
65 65 required=False)
66 66
67 67 def __init__(self, *args, **kwargs):
68 68 super(CampaignForm, self).__init__(*args, **kwargs)
69 69 self.fields['start_date'].widget = DatepickerWidget(self.fields['start_date'].widget.attrs)
70 70 self.fields['end_date'].widget = DatepickerWidget(self.fields['end_date'].widget.attrs)
71 71 self.fields['description'].widget.attrs = {'rows': 2}
72 72
73 73 if self.instance.pk:
74 74 self.fields['experiments'].queryset |= self.instance.experiments.all()
75 75
76 76 class Meta:
77 77 model = Campaign
78 78 exclude = ['']
79 79
80 80
81 81 class ExperimentForm(forms.ModelForm):
82 82
83 83 def __init__(self, *args, **kwargs):
84 84 super(ExperimentForm, self).__init__(*args, **kwargs)
85 85 self.fields['start_time'].widget = TimepickerWidget(self.fields['start_time'].widget.attrs)
86 86 self.fields['end_time'].widget = TimepickerWidget(self.fields['end_time'].widget.attrs)
87 87
88 88 def save(self):
89 89 exp = super(ExperimentForm, self).save()
90 90 exp.name = exp.name.replace(' ', '')
91 91 exp.save()
92 92 return exp
93 93
94 94 class Meta:
95 95 model = Experiment
96 exclude = ['status']
96 exclude = ['task', 'status']
97 97
98 98 class LocationForm(forms.ModelForm):
99 99 class Meta:
100 100 model = Location
101 101 exclude = ['']
102 102
103 103 class DeviceForm(forms.ModelForm):
104 104 class Meta:
105 105 model = Device
106 106 exclude = ['status']
107 107
108 108 class ConfigurationForm(forms.ModelForm):
109 109
110 110 def __init__(self, *args, **kwargs):
111 111 super(ConfigurationForm, self).__init__(*args, **kwargs)
112 112
113 113 if 'initial' in kwargs and 'experiment' in kwargs['initial'] and kwargs['initial']['experiment'] not in (0, '0'):
114 114 self.fields['experiment'].widget.attrs['disabled'] = 'disabled'
115 115
116 116 class Meta:
117 117 model = Configuration
118 118 exclude = ['type', 'created_date', 'programmed_date', 'parameters']
119 119
120 120 class UploadFileForm(forms.Form):
121 121
122 122 file = forms.FileField()
123 123
124 124 class DownloadFileForm(forms.Form):
125 125
126 126 format = forms.ChoiceField(choices= ((0, 'json'),) )
127 127
128 128 def __init__(self, device_type, *args, **kwargs):
129 129
130 130 super(DownloadFileForm, self).__init__(*args, **kwargs)
131 131
132 132 self.fields['format'].choices = FILE_FORMAT
133 133
134 134 if device_type == 'dds':
135 135 self.fields['format'].choices = DDS_FILE_FORMAT
136 136
137 137 if device_type == 'rc':
138 138 self.fields['format'].choices = RC_FILE_FORMAT
139 139
140 140 if device_type == 'jars':
141 141 self.fields['format'].choices = JARS_FILE_FORMAT
142 142
143 143 class OperationForm(forms.Form):
144 144
145 145 campaign = forms.ChoiceField(label="Campaign")
146 146
147 147 def __init__(self, *args, **kwargs):
148 148
149 149 campaigns = kwargs.pop('campaigns')
150 150 super(OperationForm, self).__init__(*args, **kwargs)
151 151 self.fields['campaign'].label = 'Current Campaigns'
152 152 self.fields['campaign'].choices = add_empty_choice(campaigns.values_list('id', 'name'))
153 153
154 154
155 155 class OperationSearchForm(forms.Form):
156 156 # -----ALL Campaigns------
157 157 campaign = forms.ChoiceField(label="Campaign")
158 158
159 159 def __init__(self, *args, **kwargs):
160 160 super(OperationSearchForm, self).__init__(*args, **kwargs)
161 161 self.fields['campaign'].choices=Campaign.objects.all().order_by('-start_date').values_list('id', 'name')
162 162
163 163
164 164 class NewForm(forms.Form):
165 165
166 166 create_from = forms.ChoiceField(choices=((0, '-----'),
167 167 (1, 'Empty (blank)'),
168 168 (2, 'Template')))
169 169 choose_template = forms.ChoiceField()
170 170
171 171 def __init__(self, *args, **kwargs):
172 172
173 173 template_choices = kwargs.pop('template_choices', [])
174 174 super(NewForm, self).__init__(*args, **kwargs)
175 175 self.fields['choose_template'].choices = add_empty_choice(template_choices)
176 176
177 177
178 178 class FilterForm(forms.Form):
179 179
180 180 def __init__(self, *args, **kwargs):
181 181 extra_fields = kwargs.pop('extra_fields', [])
182 182 super(FilterForm, self).__init__(*args, **kwargs)
183 183
184 184 for field in extra_fields:
185 185 if 'range_date' in field:
186 186 self.fields[field] = forms.CharField(required=False)
187 187 self.fields[field].widget = DateRangepickerWidget()
188 188 if 'initial' in kwargs:
189 189 self.fields[field].widget.attrs = {'start_date':kwargs['initial'].get('start_date', ''),
190 190 'end_date':kwargs['initial'].get('end_date', '')}
191 191 elif field in ('template', 'historical'):
192 192 self.fields[field] = forms.BooleanField(required=False)
193 193 else:
194 194 self.fields[field] = forms.CharField(required=False)
195 195
196 196 class ChangeIpForm(forms.Form):
197 197
198 198 ip_address = forms.GenericIPAddressField()
199 199 mask = forms.GenericIPAddressField(initial='255.255.255.0')
200 200 gateway = forms.GenericIPAddressField(initial='0.0.0.0')
201 201 dns = forms.GenericIPAddressField(initial='0.0.0.0')
202 202
@@ -1,759 +1,761
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
19 19 from apps.main.utils import Params
20 20 from apps.rc.utils import RCFile
21 21 from apps.jars.utils import RacpFile
22 22 from devices.dds import api as dds_api
23 23 from devices.dds import data as dds_data
24 24
25 25
26 26 DEV_PORTS = {
27 27 'rc' : 2000,
28 28 'dds' : 2000,
29 29 'jars' : 2000,
30 30 'usrp' : 2000,
31 31 'cgs' : 8080,
32 32 'abs' : 8080
33 33 }
34 34
35 35 RADAR_STATES = (
36 36 (0, 'No connected'),
37 37 (1, 'Connected'),
38 38 (2, 'Configured'),
39 39 (3, 'Running'),
40 40 (4, 'Scheduled'),
41 41 )
42 42
43 43 EXPERIMENT_TYPE = (
44 44 (0, 'RAW_DATA'),
45 45 (1, 'PDATA'),
46 46 )
47 47
48 48 DECODE_TYPE = (
49 49 (0, 'None'),
50 50 (1, 'TimeDomain'),
51 51 (2, 'FreqDomain'),
52 52 (3, 'InvFreqDomain'),
53 53 )
54 54
55 55 DEV_STATES = (
56 56 (0, 'No connected'),
57 57 (1, 'Connected'),
58 58 (2, 'Configured'),
59 59 (3, 'Running'),
60 60 (4, 'Unknown'),
61 61 )
62 62
63 63 DEV_TYPES = (
64 64 ('', 'Select a device type'),
65 65 ('rc', 'Radar Controller'),
66 66 ('dds', 'Direct Digital Synthesizer'),
67 67 ('jars', 'Jicamarca Radar Acquisition System'),
68 68 ('usrp', 'Universal Software Radio Peripheral'),
69 69 ('cgs', 'Clock Generator System'),
70 70 ('abs', 'Automatic Beam Switching'),
71 71 )
72 72
73 73 EXP_STATES = (
74 74 (0,'Error'), #RED
75 75 (1,'Configured'), #BLUE
76 76 (2,'Running'), #GREEN
77 77 (3,'Scheduled'), #YELLOW
78 78 (4,'Not Configured'), #WHITE
79 79 )
80 80
81 81 CONF_TYPES = (
82 82 (0, 'Active'),
83 83 (1, 'Historical'),
84 84 )
85 85
86 86 class Location(models.Model):
87 87
88 88 name = models.CharField(max_length = 30)
89 89 description = models.TextField(blank=True, null=True)
90 90
91 91 class Meta:
92 92 db_table = 'db_location'
93 93
94 94 def __str__(self):
95 95 return u'%s' % self.name
96 96
97 97 def get_absolute_url(self):
98 98 return reverse('url_location', args=[str(self.id)])
99 99
100 100
101 101 class DeviceType(models.Model):
102 102
103 103 name = models.CharField(max_length = 10, choices = DEV_TYPES, default = 'rc')
104 104 sequence = models.PositiveSmallIntegerField(default=1000)
105 105 description = models.TextField(blank=True, null=True)
106 106
107 107 class Meta:
108 108 db_table = 'db_device_types'
109 109
110 110 def __str__(self):
111 111 return u'%s' % self.get_name_display()
112 112
113 113 class Device(models.Model):
114 114
115 115 device_type = models.ForeignKey(DeviceType, on_delete=models.CASCADE)
116 116 location = models.ForeignKey(Location, on_delete=models.CASCADE)
117 117
118 118 name = models.CharField(max_length=40, default='')
119 119 ip_address = models.GenericIPAddressField(protocol='IPv4', default='0.0.0.0')
120 120 port_address = models.PositiveSmallIntegerField(default=2000)
121 121 description = models.TextField(blank=True, null=True)
122 122 status = models.PositiveSmallIntegerField(default=0, choices=DEV_STATES)
123 123
124 124 class Meta:
125 125 db_table = 'db_devices'
126 126
127 127 def __str__(self):
128 128 return u'[{}]: {}'.format(self.device_type.name.upper(),
129 129 self.name)
130 130
131 131 def get_status(self):
132 132 return self.status
133 133
134 134 @property
135 135 def status_color(self):
136 136 color = 'muted'
137 137 if self.status == 0:
138 138 color = "danger"
139 139 elif self.status == 1:
140 140 color = "warning"
141 141 elif self.status == 2:
142 142 color = "info"
143 143 elif self.status == 3:
144 144 color = "success"
145 145
146 146 return color
147 147
148 148 def url(self, path=None):
149 149
150 150 if path:
151 151 return 'http://{}:{}/{}/'.format(self.ip_address, self.port_address, path)
152 152 else:
153 153 return 'http://{}:{}/'.format(self.ip_address, self.port_address)
154 154
155 155 def get_absolute_url(self):
156 156
157 157 return reverse('url_device', args=[str(self.id)])
158 158
159 159 def change_ip(self, ip_address, mask, gateway, dns, **kwargs):
160 160
161 161 if self.device_type.name=='dds':
162 162 try:
163 163 answer = dds_api.change_ip(ip = self.ip_address,
164 164 port = self.port_address,
165 165 new_ip = ip_address,
166 166 mask = mask,
167 167 gateway = gateway)
168 168 if answer[0]=='1':
169 169 self.message = '25|DDS - {}'.format(answer)
170 170 self.ip_address = ip_address
171 171 self.save()
172 172 else:
173 173 self.message = '30|DDS - {}'.format(answer)
174 174 return False
175 175 except Exception as e:
176 176 self.message = '40|{}'.format(str(e))
177 177 return False
178 178
179 179 elif self.device_type.name=='rc':
180 180 headers = {'content-type': "application/json",
181 181 'cache-control': "no-cache"}
182 182
183 183 ip = [int(x) for x in ip_address.split('.')]
184 184 dns = [int(x) for x in dns.split('.')]
185 185 gateway = [int(x) for x in gateway.split('.')]
186 186 subnet = [int(x) for x in mask.split('.')]
187 187
188 188 payload = {
189 189 "ip": ip,
190 190 "dns": dns,
191 191 "gateway": gateway,
192 192 "subnet": subnet
193 193 }
194 194
195 195 req = requests.post(self.url('changeip'), data=json.dumps(payload), headers=headers)
196 196 try:
197 197 answer = req.json()
198 198 if answer['changeip']=='ok':
199 199 self.message = '25|IP succesfully changed'
200 200 self.ip_address = ip_address
201 201 self.save()
202 202 else:
203 203 self.message = '30|An error ocuur when changing IP'
204 204 except Exception as e:
205 205 self.message = '40|{}'.format(str(e))
206 206 else:
207 207 self.message = 'Not implemented'
208 208 return False
209 209
210 210 return True
211 211
212 212
213 213 class Campaign(models.Model):
214 214
215 215 template = models.BooleanField(default=False)
216 216 name = models.CharField(max_length=60, unique=True)
217 217 start_date = models.DateTimeField(blank=True, null=True)
218 218 end_date = models.DateTimeField(blank=True, null=True)
219 219 tags = models.CharField(max_length=40)
220 220 description = models.TextField(blank=True, null=True)
221 221 experiments = models.ManyToManyField('Experiment', blank=True)
222 222
223 223 class Meta:
224 224 db_table = 'db_campaigns'
225 225 ordering = ('name',)
226 226
227 227 def __str__(self):
228 228 if self.template:
229 229 return u'{} (template)'.format(self.name)
230 230 else:
231 231 return u'{}'.format(self.name)
232 232
233 233 def jsonify(self):
234 234
235 235 data = {}
236 236
237 237 ignored = ('template')
238 238
239 239 for field in self._meta.fields:
240 240 if field.name in ignored:
241 241 continue
242 242 data[field.name] = field.value_from_object(self)
243 243
244 244 data['start_date'] = data['start_date'].strftime('%Y-%m-%d')
245 245 data['end_date'] = data['end_date'].strftime('%Y-%m-%d')
246 246
247 247 return data
248 248
249 249 def parms_to_dict(self):
250 250
251 params = Params()
251 params = Params({})
252 252 params.add(self.jsonify(), 'campaigns')
253 253
254 254 for exp in Experiment.objects.filter(campaign = self):
255 255 params.add(exp.jsonify(), 'experiments')
256 256 configurations = Configuration.objects.filter(experiment=exp, type=0)
257 257
258 258 for conf in configurations:
259 259 params.add(conf.jsonify(), 'configurations')
260 260 if conf.device.device_type.name=='rc':
261 261 for line in conf.get_lines():
262 262 params.add(line.jsonify(), 'lines')
263 263
264 264 return params.data
265 265
266 266 def dict_to_parms(self, parms, CONF_MODELS):
267 267
268 268 experiments = Experiment.objects.filter(campaign = self)
269 269
270 270 if experiments:
271 271 for experiment in experiments:
272 272 experiment.delete()
273 273
274 274 for id_exp in parms['experiments']['allIds']:
275 275 exp_parms = parms['experiments']['byId'][id_exp]
276 276 dum = (datetime.now() - datetime(1970, 1, 1)).total_seconds()
277 277 exp = Experiment(name='{}'.format(dum))
278 278 exp.save()
279 279 exp.dict_to_parms(parms, CONF_MODELS, id_exp=id_exp)
280 280 self.experiments.add(exp)
281 281
282 282 camp_parms = parms['campaigns']['byId'][parms['campaigns']['allIds'][0]]
283 283
284 284 self.name = '{}-{}'.format(camp_parms['name'], datetime.now().strftime('%y%m%d'))
285 285 self.start_date = camp_parms['start_date']
286 286 self.end_date = camp_parms['end_date']
287 287 self.tags = camp_parms['tags']
288 288 self.save()
289 289
290 290 return self
291 291
292 292 def get_experiments_by_radar(self, radar=None):
293 293
294 294 ret = []
295 295 if radar:
296 296 locations = Location.objects.filter(pk=radar)
297 297 else:
298 298 locations = set([e.location for e in self.experiments.all()])
299 299
300 300 for loc in locations:
301 301 dum = {}
302 302 dum['name'] = loc.name
303 303 dum['id'] = loc.pk
304 304 dum['experiments'] = [e for e in self.experiments.all() if e.location==loc]
305 305 ret.append(dum)
306 306
307 307 return ret
308 308
309 309 def get_absolute_url(self):
310 310 return reverse('url_campaign', args=[str(self.id)])
311 311
312 312 def get_absolute_url_edit(self):
313 313 return reverse('url_edit_campaign', args=[str(self.id)])
314 314
315 315 def get_absolute_url_export(self):
316 316 return reverse('url_export_campaign', args=[str(self.id)])
317 317
318 318 def get_absolute_url_import(self):
319 319 return reverse('url_import_campaign', args=[str(self.id)])
320 320
321 321
322 322
323 323 class RunningExperiment(models.Model):
324 324 radar = models.OneToOneField('Location', on_delete=models.CASCADE)
325 325 running_experiment = models.ManyToManyField('Experiment', blank = True)
326 326 status = models.PositiveSmallIntegerField(default=0, choices=RADAR_STATES)
327 327
328 328
329 329 class Experiment(models.Model):
330 330
331 331 template = models.BooleanField(default=False)
332 332 name = models.CharField(max_length=40, default='', unique=True)
333 333 location = models.ForeignKey('Location', null=True, blank=True, on_delete=models.CASCADE)
334 334 freq = models.FloatField(verbose_name='Operating Freq. (MHz)', validators=[MinValueValidator(1), MaxValueValidator(10000)], default=49.9200)
335 335 start_time = models.TimeField(default='00:00:00')
336 336 end_time = models.TimeField(default='23:59:59')
337 task = models.CharField(max_length=36, default='', blank=True, null=True)
337 338 status = models.PositiveSmallIntegerField(default=4, choices=EXP_STATES)
338 339
339 340 class Meta:
340 341 db_table = 'db_experiments'
341 342 ordering = ('template', 'name')
342 343
343 344 def __str__(self):
344 345 if self.template:
345 346 return u'%s (template)' % (self.name)
346 347 else:
347 348 return u'%s' % (self.name)
348 349
349 350 def jsonify(self):
350 351
351 352 data = {}
352 353
353 354 ignored = ('template')
354 355
355 356 for field in self._meta.fields:
356 357 if field.name in ignored:
357 358 continue
358 359 data[field.name] = field.value_from_object(self)
359 360
360 361 data['start_time'] = data['start_time'].strftime('%H:%M:%S')
361 362 data['end_time'] = data['end_time'].strftime('%H:%M:%S')
362 363 data['location'] = self.location.name
363 364 data['configurations'] = ['{}'.format(conf.pk) for
364 365 conf in Configuration.objects.filter(experiment=self, type=0)]
365 366
366 367 return data
367 368
368 369 @property
369 370 def radar_system(self):
370 371 return self.location
371 372
372 373 def clone(self, **kwargs):
373 374
374 375 confs = Configuration.objects.filter(experiment=self, type=0)
375 376 self.pk = None
376 self.name = '{} [{:%Y/%m/%d}]'.format(self.name, datetime.now())
377 self.name = '{} [{:%Y-%m-%d}]'.format(self.name, datetime.now())
377 378 for attr, value in kwargs.items():
378 379 setattr(self, attr, value)
379 380
380 381 self.save()
381 382
382 383 for conf in confs:
383 384 conf.clone(experiment=self, template=False)
384 385
385 386 return self
386 387
387 388 def start(self):
388 389 '''
389 390 Configure and start experiments's devices
390 391 ABS-CGS-DDS-RC-JARS
391 392 '''
392 393
393 394 result = 2
394
395 confs = Configuration.objects.filter(experiment=self, type = 0).order_by('-device__device_type__sequence')
395 confs = []
396 allconfs = Configuration.objects.filter(experiment=self, type = 0).order_by('-device__device_type__sequence')
397 rc_mix = [conf for conf in allconfs if conf.device.device_type.name=='rc' and conf.mix]
398 if rc_mix:
399 for conf in allconfs:
400 if conf.device.device_type.name == 'rc' and not conf.mix:
401 continue
402 confs.append(conf)
403 else:
404 confs = allconfs
396 405 #Only Configured Devices.
397 406 for conf in confs:
398 407 if conf.device.status in (0, 4):
399 408 result = 0
400 409 return result
401 410 for conf in confs:
402 411 conf.stop_device()
403 #conf.write_device()
412 conf.write_device()
404 413 conf.start_device()
405 print conf.device.name+' has started...'
414 time.sleep(1)
406 415
407 416 return result
408 417
409 418
410 419 def stop(self):
411 420 '''
412 421 Stop experiments's devices
413 422 DDS-JARS-RC-CGS-ABS
414 423 '''
415 424
416 425 result = 1
417 426
418 427 confs = Configuration.objects.filter(experiment=self, type = 0).order_by('device__device_type__sequence')
419 428 confs=confs.exclude(device__device_type__name='cgs')
420 429 for conf in confs:
421 430 if conf.device.status in (0, 4):
422 431 result = 0
423 432 continue
424 433 conf.stop_device()
425 print conf.device.name+' has stopped...'
426 434
427 435 return result
428 436
429 437
430 438 def get_status(self):
431 439
432 440 if self.status == 3:
433 441 return
434 442
435 443 confs = Configuration.objects.filter(experiment=self, type=0)
436 444
437 445 for conf in confs:
438 446 conf.status_device()
439 447
440 448 total = confs.aggregate(models.Sum('device__status'))['device__status__sum']
441 449
442 450 if total==2*confs.count():
443 451 status = 1
444 452 elif total == 3*confs.count():
445 453 status = 2
446 454 else:
447 455 status = 0
448 456
449 457 self.status = status
450 458 self.save()
451 459
452 460 def status_color(self):
453 461 color = 'muted'
454 462 if self.status == 0:
455 463 color = "danger"
456 464 elif self.status == 1:
457 465 color = "info"
458 466 elif self.status == 2:
459 467 color = "success"
460 468 elif self.status == 3:
461 469 color = "warning"
462 470
463 471 return color
464 472
465 473 def parms_to_dict(self):
466 474
467 params = Params()
475 params = Params({})
468 476 params.add(self.jsonify(), 'experiments')
469 477
470 478 configurations = Configuration.objects.filter(experiment=self, type=0)
471 479
472 480 for conf in configurations:
473 481 params.add(conf.jsonify(), 'configurations')
474 482 if conf.device.device_type.name=='rc':
475 483 for line in conf.get_lines():
476 484 params.add(line.jsonify(), 'lines')
477 485
478 486 return params.data
479 487
480 488 def dict_to_parms(self, parms, CONF_MODELS, id_exp=None):
481 489
482 490 configurations = Configuration.objects.filter(experiment=self)
483 491
484 492 if id_exp is not None:
485 493 exp_parms = parms['experiments']['byId'][id_exp]
486 494 else:
487 495 exp_parms = parms['experiments']['byId'][parms['experiments']['allIds'][0]]
488 496
489 497 if configurations:
490 498 for configuration in configurations:
491 499 configuration.delete()
492 500
493 501 for id_conf in exp_parms['configurations']:
494 502 conf_parms = parms['configurations']['byId'][id_conf]
495 503 device = Device.objects.filter(device_type__name=conf_parms['device_type'])[0]
496 504 model = CONF_MODELS[conf_parms['device_type']]
497 505 conf = model(
498 506 experiment = self,
499 507 device = device,
500 508 )
501 509 conf.dict_to_parms(parms, id=id_conf)
502 510
503 511
504 512 location, created = Location.objects.get_or_create(name=exp_parms['location'])
505 513 self.name = '{}-{}'.format(exp_parms['name'], datetime.now().strftime('%y%m%d'))
506 514 self.location = location
507 515 self.start_time = exp_parms['start_time']
508 516 self.end_time = exp_parms['end_time']
509 517 self.save()
510 518
511 519 return self
512 520
513 521 def get_absolute_url(self):
514 522 return reverse('url_experiment', args=[str(self.id)])
515 523
516 524 def get_absolute_url_edit(self):
517 525 return reverse('url_edit_experiment', args=[str(self.id)])
518 526
519 527 def get_absolute_url_import(self):
520 528 return reverse('url_import_experiment', args=[str(self.id)])
521 529
522 530 def get_absolute_url_export(self):
523 531 return reverse('url_export_experiment', args=[str(self.id)])
524 532
525 533 def get_absolute_url_start(self):
526 534 return reverse('url_start_experiment', args=[str(self.id)])
527 535
528 536 def get_absolute_url_stop(self):
529 537 return reverse('url_stop_experiment', args=[str(self.id)])
530 538
531 539
532 540 class Configuration(PolymorphicModel):
533 541
534 542 template = models.BooleanField(default=False)
535
536 543 name = models.CharField(verbose_name="Configuration Name", max_length=40, default='')
537
538 544 experiment = models.ForeignKey('Experiment', verbose_name='Experiment', null=True, blank=True, on_delete=models.CASCADE)
539 545 device = models.ForeignKey('Device', verbose_name='Device', null=True, on_delete=models.CASCADE)
540
541 546 type = models.PositiveSmallIntegerField(default=0, choices=CONF_TYPES)
542
543 547 created_date = models.DateTimeField(auto_now_add=True)
544 548 programmed_date = models.DateTimeField(auto_now=True)
545
546 549 parameters = models.TextField(default='{}')
547
548 550 message = ""
549 551
550 552 class Meta:
551 553 db_table = 'db_configurations'
552 554
553 555 def __str__(self):
554 556
555 557 device = '{}:'.format(self.device.device_type.name.upper())
556 558
557 559 if 'mix' in [f.name for f in self._meta.get_fields()]:
558 560 if self.mix:
559 561 device = '{} MIXED:'.format(self.device.device_type.name.upper())
560 562
561 563 if self.template:
562 564 return u'{} {} (template)'.format(device, self.name)
563 565 else:
564 566 return u'{} {}'.format(device, self.name)
565 567
566 568 def jsonify(self):
567 569
568 570 data = {}
569 571
570 572 ignored = ('type', 'polymorphic_ctype', 'configuration_ptr',
571 573 'created_date', 'programmed_date', 'template', 'device',
572 574 'experiment')
573 575
574 576 for field in self._meta.fields:
575 577 if field.name in ignored:
576 578 continue
577 579 data[field.name] = field.value_from_object(self)
578 580
579 581 data['device_type'] = self.device.device_type.name
580 582
581 583 if self.device.device_type.name == 'rc':
582 584 data['lines'] = ['{}'.format(line.pk) for line in self.get_lines()]
583 585 data['delays'] = self.get_delays()
584 586 data['pulses'] = self.get_pulses()
585 587
586 588 elif self.device.device_type.name == 'jars':
587 589 data['decode_type'] = DECODE_TYPE[self.decode_data][1]
588 590
589 591 elif self.device.device_type.name == 'dds':
590 592 data['frequencyA_Mhz'] = float(data['frequencyA_Mhz'])
591 593 data['frequencyB_Mhz'] = float(data['frequencyB_Mhz'])
592 594 data['phaseA'] = dds_data.phase_to_binary(data['phaseA_degrees'])
593 595 data['phaseB'] = dds_data.phase_to_binary(data['phaseB_degrees'])
594 596
595 597 return data
596 598
597 599 def clone(self, **kwargs):
598 600
599 601 self.pk = None
600 602 self.id = None
601 603 for attr, value in kwargs.items():
602 604 setattr(self, attr, value)
603 605
604 606 self.save()
605 607
606 608 return self
607 609
608 610 def parms_to_dict(self):
609 611
610 params = Params()
612 params = Params({})
611 613 params.add(self.jsonify(), 'configurations')
612 614
613 615 if self.device.device_type.name=='rc':
614 616 for line in self.get_lines():
615 617 params.add(line.jsonify(), 'lines')
616 618
617 619 return params.data
618 620
619 621 def parms_to_text(self):
620 622
621 623 raise NotImplementedError("This method should be implemented in %s Configuration model" %str(self.device.device_type.name).upper())
622 624
623 625
624 626 def parms_to_binary(self):
625 627
626 628 raise NotImplementedError("This method should be implemented in %s Configuration model" %str(self.device.device_type.name).upper())
627 629
628 630
629 631 def dict_to_parms(self, parameters, id=None):
630 632
631 633 params = Params(parameters)
632 634
633 635 if id:
634 636 data = params.get_conf(id_conf=id)
635 637 else:
636 638 data = params.get_conf(dtype=self.device.device_type.name)
637 639
638 640 if data['device_type']=='rc':
639 641 self.clean_lines()
640 642 lines = data.pop('lines', None)
641 643 for line_id in lines:
642 644 pass
643 645
644 646 for key, value in data.items():
645 647 if key not in ('id', 'device_type'):
646 648 setattr(self, key, value)
647 649
648 650 self.save()
649 651
650 652
651 653 def export_to_file(self, format="json"):
652 654
653 655 content_type = ''
654 656
655 657 if format == 'racp':
656 658 content_type = 'text/plain'
657 659 filename = '%s_%s.%s' %(self.device.device_type.name, self.name, 'racp')
658 660 content = self.parms_to_text(file_format = 'racp')
659 661
660 662 if format == 'text':
661 663 content_type = 'text/plain'
662 664 filename = '%s_%s.%s' %(self.device.device_type.name, self.name, self.device.device_type.name)
663 665 content = self.parms_to_text()
664 666
665 667 if format == 'binary':
666 668 content_type = 'application/octet-stream'
667 669 filename = '%s_%s.bin' %(self.device.device_type.name, self.name)
668 670 content = self.parms_to_binary()
669 671
670 672 if not content_type:
671 673 content_type = 'application/json'
672 674 filename = '%s_%s.json' %(self.device.device_type.name, self.name)
673 675 content = json.dumps(self.parms_to_dict(), indent=2)
674 676
675 677 fields = {'content_type':content_type,
676 678 'filename':filename,
677 679 'content':content
678 680 }
679 681
680 682 return fields
681 683
682 684 def import_from_file(self, fp):
683 685
684 686 parms = {}
685 687
686 688 path, ext = os.path.splitext(fp.name)
687 689
688 690 if ext == '.json':
689 691 parms = json.load(fp)
690 692
691 693 if ext == '.dds':
692 694 lines = fp.readlines()
693 695 parms = dds_data.text_to_dict(lines)
694 696
695 697 if ext == '.racp':
696 698 if self.device.device_type.name == 'jars':
697 699 parms = RacpFile(fp).to_dict()
698 700 parms['filter_parms'] = json.loads(self.filter_parms)
699 701 return parms
700 702 parms = RCFile(fp).to_dict()
701 703
702 704 return parms
703 705
704 706 def status_device(self):
705 707
706 708 self.message = 'Function not implemented'
707 709 return False
708 710
709 711
710 712 def stop_device(self):
711 713
712 714 self.message = 'Function not implemented'
713 715 return False
714 716
715 717
716 718 def start_device(self):
717 719
718 720 self.message = 'Function not implemented'
719 721 return False
720 722
721 723
722 724 def write_device(self, parms):
723 725
724 726 self.message = 'Function not implemented'
725 727 return False
726 728
727 729
728 730 def read_device(self):
729 731
730 732 self.message = 'Function not implemented'
731 733 return False
732 734
733 735
734 736 def get_absolute_url(self):
735 737 return reverse('url_%s_conf' % self.device.device_type.name, args=[str(self.id)])
736 738
737 739 def get_absolute_url_edit(self):
738 740 return reverse('url_edit_%s_conf' % self.device.device_type.name, args=[str(self.id)])
739 741
740 742 def get_absolute_url_import(self):
741 743 return reverse('url_import_dev_conf', args=[str(self.id)])
742 744
743 745 def get_absolute_url_export(self):
744 746 return reverse('url_export_dev_conf', args=[str(self.id)])
745 747
746 748 def get_absolute_url_write(self):
747 749 return reverse('url_write_dev_conf', args=[str(self.id)])
748 750
749 751 def get_absolute_url_read(self):
750 752 return reverse('url_read_dev_conf', args=[str(self.id)])
751 753
752 754 def get_absolute_url_start(self):
753 755 return reverse('url_start_dev_conf', args=[str(self.id)])
754 756
755 757 def get_absolute_url_stop(self):
756 758 return reverse('url_stop_dev_conf', args=[str(self.id)])
757 759
758 760 def get_absolute_url_status(self):
759 761 return reverse('url_status_dev_conf', args=[str(self.id)])
@@ -1,45 +1,68
1 1 from __future__ import absolute_import
2 2
3 from radarsys.celery import app
3 4 from celery import task
4 5 from datetime import timedelta, datetime
5 6
6 7 from .models import Experiment
7 8
8 9 @task
9 10 def task_start(id_exp):
10
11 11 exp = Experiment.objects.get(pk=id_exp)
12
13 return exp.start()
12 status = exp.status
13 if exp.status == 2:
14 print('Experiment {} already running start task not executed'.format(exp))
15 return 2
16 if status == 3:
17 now = datetime.now()
18 start = datetime.combine(now.date(), exp.start_time)
19 end = datetime.combine(now.date(), exp.end_time)
20 if end < start:
21 end += timedelta(1)
22 try:
23 print('Starting exp:{}'.format(exp))
24 exp.status = exp.start()
25 except:
26 print('Error')
27 exp.status = 0
28 if exp.status == 2:
29 task = task_stop.apply_async((id_exp,), eta=end+timedelta(hours=5))
30 exp.task = task.id
31 exp.save()
32 return exp.status
14 33
15 34 @task
16 35 def task_stop(id_exp):
17
18 36 exp = Experiment.objects.get(pk=id_exp)
37 if exp.status == 2:
38 try:
39 print('Stopping exp:{}'.format(exp))
40 exp.status = exp.stop()
41 except:
42 print('Error')
43 exp.status = 0
19 44
20 return exp.stop()
21
22 def kill_tasks():
23
24 i = task.control.inspect()
25 tasks = i.scheduled()
26 print tasks
27 #if tasks:
28 # print dir(tasks[0])
45 now = datetime.now()
46 start = datetime.combine(now.date()+timedelta(1), exp.start_time)
47 task = task_start.apply_async((id_exp, ), eta=start+timedelta(hours=5))
48 exp.task = task.id
49 exp.status = 3
50 exp.save()
51 return exp.status
29 52
30 53 #Task to get status
31 54 @task
32 55 def task_status(id_exp):
33 56
34 57 exp = Experiment.objects.get(pk=id_exp)
35 58 if exp.status==2:
36 59 run_every = timedelta(minutes=1)
37 60 now = datetime.utcnow()
38 61 date = now + run_every
39 62 task_status.apply_async((id_exp,), eta=date)
40 63 print "Monitoring..."
41 64 exp.get_status()
42 65 return exp.status
43 66
44 67 else:
45 68 return exp.status
@@ -1,104 +1,108
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
9 9 {% block exp-active %}active{% endblock %}
10 10
11 11 {% block content-title %}{{title}}{% endblock %}
12 12 {% block content-suptitle %}{{suptitle}}{% endblock %}
13 13
14 14 {% block content %}
15 15
16 16 {% block menu-actions %}
17 17 <span class=" dropdown pull-right">
18 18 <a href="#" class="dropdown-toggle" data-toggle="dropdown"><span class="glyphicon glyphicon-menu-hamburger gi-2x" aria-hidden="true"></span></a>
19 19 <ul class="dropdown-menu" role="menu">
20 20 <li><a href="{% url 'url_edit_experiment' experiment.id %}"><span class="glyphicon glyphicon-pencil" aria-hidden="true"></span> Edit</a></li>
21 21 <li><a href="{% url 'url_delete_experiment' experiment.id %}"><span class="glyphicon glyphicon-remove" aria-hidden="true"></span> Delete</a></li>
22 22 <li><a href="{{ experiment.get_absolute_url_import }}"><span class="glyphicon glyphicon-import" aria-hidden="true"></span> Import </a></li>
23 23 <li><a href="{{ experiment.get_absolute_url_export }}"><span class="glyphicon glyphicon-export" aria-hidden="true"></span> Export </a></li>
24 24 <li><a>----------------</a></li>
25 25 <li><a href="{{ experiment.get_absolute_url_start}}"><span class="glyphicon glyphicon-play" aria-hidden="true"></span> Start</a></li>
26 26 <li><a href="{{ experiment.get_absolute_url_stop }}"><span class="glyphicon glyphicon-stop" aria-hidden="true"></span> Stop</a></li>
27 27 <li><a href="{% url 'url_mix_experiment' experiment.id %}"><span class="glyphicon glyphicon-random" aria-hidden="true"></span> Mix RC Configurations </a></li>
28 28 <li><a href="{% url 'url_add_dev_conf' experiment.id %}"><span class="glyphicon glyphicon-plus-sign" aria-hidden="true"></span> Add Configuration</a></li>
29 29 <li><a href="{% url 'url_sum_experiment' experiment.id %}"><span class="glyphicon glyphicon-list-alt" aria-hidden="true"></span> Summary</a></li>
30 30
31 31 </ul>
32 32 </span>
33 33 {% endblock %}
34 34
35 35 <table class="table table-bordered">
36 36 {% for key in experiment_keys %}
37 37 {% if key == 'freq' %}
38 38 <tr><th>Operating Freq. (MHz)</th><td>{{experiment|attr:key}}</td></tr>
39 39 {% else %}
40 40 <tr><th>{{key|title}}</th><td>{{experiment|attr:key}}</td></tr>
41 41 {% endif %}
42 42 {% endfor %}
43 43 </table>
44 44 <br>
45 45
46 46 <div class="panel-group" id="accordion" role="tablist" aria-multiselectable="true">
47 47
48 48 <div class="panel panel-default bootcards-summary">
49 49 <div class="panel-heading" role="tab">
50 50 <h4 class="panel-title">
51 51 Devices
52 52 </h4>
53 53 </div>
54 54 <div class="panel-body">
55 55
56 56 {% for item in configurations %}
57 57 <div class="col-xs-6 col-sm-4" style="padding-top:5px;padding-bottom:5px">
58 58 <a class="bootcards-summary-item" href="{{item.get_absolute_url}}"><br>
59 59 {% if item.device.device_type.name == 'cgs' %}
60 60 <i class="fa fa-2x fa-clock-o"></i>
61 61 {% elif item.device.device_type.name == 'rc' %}
62 62 <i class="fa fa-2x fa-microchip"></i>
63 63 {% elif item.device.device_type.name == 'abs' %}
64 64 <i class="fa fa-2x fa-podcast"></i>
65 65 {% elif item.device.device_type.name == 'jars' %}
66 66 <i class="fa fa-2x fa-desktop"></i>
67 67 {% elif item.device.device_type.name == 'dds' %}
68 68 <i class="fa fa-2x fa-bar-chart"></i>
69 69 {% else %}
70 70 <i class="fa fa-3x fa-puzzle-piece"></i>
71 71 {%endif%}
72 72 <h4>{{item}}<br><small>{{item.device.ip_address}}</small>
73 <span class="label label-{{item.device.status_color}}">{{item.device.get_status_display}}</span>
74 </h4>
73 {%if experiment.status == 3 %}
74 <span class="label label-info">Configured</span>
75 {%else%}
76 <span class="label label-{{item.device.status_color}}">{{item.device.get_status_display}}</span>
77 {%endif%}
78 </h4>
75 79 </a>
76 80 </div>
77 81 {% endfor %}
78 82
79 83 </div>
80 84 </div>
81 85 </div>
82 86 {% endblock %}
83 87
84 88 {% block sidebar%}
85 89 {% include "sidebar_devices.html" %}
86 90 {% endblock %}
87 91
88 92 {% block extra-js%}
89 93 <script type="text/javascript">
90 94
91 95 $(".clickable-row").click(function() {
92 96 document.location = $(this).data("href");
93 97 });
94 98
95 99 $("#bt_edit").click(function() {
96 100 document.location = "{% url 'url_edit_experiment' experiment.id%}";
97 101 });
98 102
99 103 $("#bt_add_conf").click(function() {
100 104 document.location = "{% url 'url_add_dev_conf' experiment.id %}";
101 105 });
102 106
103 107 </script>
104 108 {% endblock %}
@@ -1,126 +1,124
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
9 9 {% block operation-active %}active{% endblock %}
10 10
11 11 {% block content-title %}{{title}}{% endblock %}
12 12
13 13 {% block content %}
14 14
15 15 <div class="clearfix"></div>
16 16
17 17 {% if campaigns %}
18 18
19 19 <h3>Current Campaigns</h3>
20 20 <br>
21
22 <div class="bootcards-list">
23 <div class="panel panel-default">
24 <div class="list-group">
25 {% for item in campaigns %}
26 <a class="list-group-item" href="{{item.pk}}">
27 <div class="row">
28 <div class="col-sm-6">
29 <i class="fa fa-3x fa-calendar pull-left"></i>
30 <h4 class="list-group-item-heading">{{item.name}}</h4>
31 <p class="list-group-item-text">Radar: {% for radar in item.get_experiments_by_radar %}{{radar.name}},{% endfor %}</p>
32 </div>
33 <div class="col-sm-6">
34 <p class="list-group-item-text">From: {{item.start_date}}</p>
35 <p class="list-group-item-text">To: {{item.end_date}}</p>
36 </div>
37 </div>
38 </a>
39 {% endfor %}
40 </div>
41 </div>
21 <div class="bootcards-list">
22 <div class="panel panel-default">
23 <div class="list-group">
24 {% for item in campaigns %}
25 <a class="list-group-item" href="{{item.pk}}">
26 <div class="row">
27 <div class="col-sm-6">
28 <i class="fa fa-3x fa-calendar pull-left"></i>
29 <h4 class="list-group-item-heading">{{item.name}}</h4>
30 <p class="list-group-item-text">Radar: {% for radar in item.get_experiments_by_radar %}{{radar.name}},{% endfor %}</p>
31 </div>
32 <div class="col-sm-6">
33 <p class="list-group-item-text">From: {{item.start_date}}</p>
34 <p class="list-group-item-text">To: {{item.end_date}}</p>
42 35 </div>
43
44 36
37 </div>
38 </a>
39 {% endfor %}
40 </div>
41 </div>
42 </div>
45 43
46 44 {% endif %}
47 45
48 46
49 47 {% if campaign %}
50 48
51 49 <h3>Systems</h3>
52 50 <br>
53 51 <div class="panel-group" id="accordion" role="tablist" aria-multiselectable="true" >
54 52
55 53 {% for location in locations %}
56 54
57 55 <div class="panel panel-default bootcards-summary">
58 56 <div class="panel-heading" role="tab">
59 57 <h3 class="panel-title">
60 58 {{location.name}} [{{campaign.start_date|date:"Y/m/d"}} - {{campaign.end_date|date:"Y/m/d"}}]
61 59 <button type="button" name="bt_play" class="btn btn-primary pull-right btn-xs" data-url="{% url 'url_radar_start' campaign.id location.id %}" style="margin-left: 10px">
62 60 <span class="glyphicon glyphicon-play" aria-hidden="true"></span>
63 61 </button>
64 62 <button type="button" name="bt_stop" class="btn btn-primary pull-right btn-xs" data-url="{% url 'url_radar_stop' campaign.id location.id %}" aria-label="Left Align" style="margin-left: 10px">
65 63 <span class="glyphicon glyphicon-stop" aria-hidden="true"></span>
66 64 </button>
67 65 <button type="button" name="bt_refresh" class="btn btn-primary pull-right btn-xs" data-url="{% url 'url_radar_refresh' campaign.id location.id %}" aria-label="Left Align" style="margin-left: 10px">
68 66 <span class="glyphicon glyphicon-refresh" aria-hidden="true"></span>
69 67 </button>
70 68 </h3>
71 69 </div>
72 70 <div class="panel-body">
73 71 <div class="row">
74 72 {% for item in location.experiments %}
75 73 {% if location.name in item.location.name %}
76 74 <div class="col-xs-6 col-sm-3" >
77 75 <a class="bootcards-summary-item" href="{{item.get_absolute_url}}">
78 76 <i class="fa fa-2x fa-cogs"></i>
79 77 <h4>{{item.name}}<br><small>{{item.start_time}}-{{item.end_time}}</small>
80 78 <span class="label label-{{item.status_color}}">{{item.get_status_display}}</span>
81 79 </h4>
82 80 </a>
83 81 </div>
84 82 {% endif %}
85 83 {% endfor %}
86 84 </div>
87 85 </div>
88 86 </div>
89 87
90 88 {% endfor %}
91 89 </div>
92 90
93 91 {% endif %}
94 92
95 93 {% endblock %}
96 94
97 95
98 96
99 97 {% block extra-js%}
100 98 <script type="text/javascript">
101 99
102 100 //--------For PLAY Button-------
103 101 $("#accordion").on("click", "button[name=bt_play]", function(){
104 102 //alert($(this).data('url'));
105 103 document.location = $(this).data('url');
106 104 });
107 105
108 106 //--------For STOP Button-------
109 107 $("#accordion").on("click", "button[name=bt_stop]", function(){
110 108 //alert($(this).data('url'));
111 109 document.location = $(this).data('url');
112 110 });
113 111
114 112 //--------For REFRESH Button-------
115 113 $("#accordion").on("click", "button[name=bt_refresh]", function(){
116 114 document.location = $(this).data('url');
117 115 });
118 116
119 117 $("#id_campaign").change(function() {
120 118 document.location = "{% url 'url_operation'%}"+$(this).val();
121 119 });
122 120
123 121
124 122
125 123 </script>
126 124 {% endblock %}
@@ -1,1734 +1,1736
1 1 import ast
2 2 import json
3 3 from datetime import datetime, timedelta
4 4
5 5 from django.shortcuts import render, redirect, get_object_or_404, HttpResponse
6 6 from django.utils.safestring import mark_safe
7 7 from django.http import HttpResponseRedirect
8 8 from django.core.urlresolvers import reverse
9 9 from django.db.models import Q
10 10 from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
11 11 from django.contrib import messages
12 12 from django.http.request import QueryDict
13 13
14 14 try:
15 15 from urllib.parse import urlencode
16 16 except ImportError:
17 17 from urllib import urlencode
18 18
19 19 from .forms import CampaignForm, ExperimentForm, DeviceForm, ConfigurationForm, LocationForm, UploadFileForm, DownloadFileForm, OperationForm, NewForm
20 20 from .forms import OperationSearchForm, FilterForm, ChangeIpForm
21 21
22 from .tasks import task_start, task_stop, task_status, kill_tasks
22 from .tasks import task_start
23 23
24 24 from apps.rc.forms import RCConfigurationForm, RCLineCode, RCMixConfigurationForm
25 25 from apps.dds.forms import DDSConfigurationForm
26 26 from apps.jars.forms import JARSConfigurationForm
27 27 from apps.cgs.forms import CGSConfigurationForm
28 28 from apps.abs.forms import ABSConfigurationForm
29 29 from apps.usrp.forms import USRPConfigurationForm
30 30 from .utils import Params
31 31
32 32 from .models import Campaign, Experiment, Device, Configuration, Location, RunningExperiment, DEV_STATES
33 33 from apps.cgs.models import CGSConfiguration
34 34 from apps.jars.models import JARSConfiguration, EXPERIMENT_TYPE
35 35 from apps.usrp.models import USRPConfiguration
36 36 from apps.abs.models import ABSConfiguration
37 37 from apps.rc.models import RCConfiguration, RCLine, RCLineType
38 38 from apps.dds.models import DDSConfiguration
39 39
40 from radarsys.celery import app
41
40 42 from django.contrib.auth.decorators import login_required
41 43 from django.contrib.auth.decorators import user_passes_test
42 44 from django.contrib.admin.views.decorators import staff_member_required
43 45
44 46 CONF_FORMS = {
45 47 'rc': RCConfigurationForm,
46 48 'dds': DDSConfigurationForm,
47 49 'jars': JARSConfigurationForm,
48 50 'cgs': CGSConfigurationForm,
49 51 'abs': ABSConfigurationForm,
50 52 'usrp': USRPConfigurationForm,
51 53 }
52 54
53 55 CONF_MODELS = {
54 56 'rc': RCConfiguration,
55 57 'dds': DDSConfiguration,
56 58 'jars': JARSConfiguration,
57 59 'cgs': CGSConfiguration,
58 60 'abs': ABSConfiguration,
59 61 'usrp': USRPConfiguration,
60 62 }
61 63
62 64 MIX_MODES = {
63 65 '0': 'P',
64 66 '1': 'S',
65 67 }
66 68
67 69 MIX_OPERATIONS = {
68 70 '0': 'OR',
69 71 '1': 'XOR',
70 72 '2': 'AND',
71 73 '3': 'NAND',
72 74 }
73 75
74 76 def index(request):
75 77 kwargs = {'no_sidebar':True}
76 78
77 79 return render(request, 'index.html', kwargs)
78 80
79 81
80 82 def locations(request):
81 83
82 84 page = request.GET.get('page')
83 85 order = ('name',)
84 86
85 87 kwargs = get_paginator(Location, page, order)
86 88
87 89 kwargs['keys'] = ['name', 'description']
88 90 kwargs['title'] = 'Radar System'
89 91 kwargs['suptitle'] = 'List'
90 92 kwargs['no_sidebar'] = True
91 93
92 94 return render(request, 'base_list.html', kwargs)
93 95
94 96
95 97 def location(request, id_loc):
96 98
97 99 location = get_object_or_404(Location, pk=id_loc)
98 100
99 101 kwargs = {}
100 102 kwargs['location'] = location
101 103 kwargs['location_keys'] = ['name', 'description']
102 104
103 105 kwargs['title'] = 'Location'
104 106 kwargs['suptitle'] = 'Details'
105 107
106 108 return render(request, 'location.html', kwargs)
107 109
108 110
109 111 @user_passes_test(lambda u:u.is_staff)
110 112 def location_new(request):
111 113
112 114 if request.method == 'GET':
113 115 form = LocationForm()
114 116
115 117 if request.method == 'POST':
116 118 form = LocationForm(request.POST)
117 119
118 120 if form.is_valid():
119 121 form.save()
120 122 return redirect('url_locations')
121 123
122 124 kwargs = {}
123 125 kwargs['form'] = form
124 126 kwargs['title'] = 'Radar System'
125 127 kwargs['suptitle'] = 'New'
126 128 kwargs['button'] = 'Create'
127 129
128 130 return render(request, 'base_edit.html', kwargs)
129 131
130 132
131 133 @user_passes_test(lambda u:u.is_staff)
132 134 def location_edit(request, id_loc):
133 135
134 136 location = get_object_or_404(Location, pk=id_loc)
135 137
136 138 if request.method=='GET':
137 139 form = LocationForm(instance=location)
138 140
139 141 if request.method=='POST':
140 142 form = LocationForm(request.POST, instance=location)
141 143
142 144 if form.is_valid():
143 145 form.save()
144 146 return redirect('url_locations')
145 147
146 148 kwargs = {}
147 149 kwargs['form'] = form
148 150 kwargs['title'] = 'Location'
149 151 kwargs['suptitle'] = 'Edit'
150 152 kwargs['button'] = 'Update'
151 153
152 154 return render(request, 'base_edit.html', kwargs)
153 155
154 156
155 157 @user_passes_test(lambda u:u.is_staff)
156 158 def location_delete(request, id_loc):
157 159
158 160 location = get_object_or_404(Location, pk=id_loc)
159 161
160 162 if request.method=='POST':
161 163
162 164 if request.user.is_staff:
163 165 location.delete()
164 166 return redirect('url_locations')
165 167
166 168 messages.error(request, 'Not enough permission to delete this object')
167 169 return redirect(location.get_absolute_url())
168 170
169 171 kwargs = {
170 172 'title': 'Delete',
171 173 'suptitle': 'Location',
172 174 'object': location,
173 175 'previous': location.get_absolute_url(),
174 176 'delete': True
175 177 }
176 178
177 179 return render(request, 'confirm.html', kwargs)
178 180
179 181
180 182 def devices(request):
181 183
182 184 page = request.GET.get('page')
183 185 order = ('device_type', 'name')
184 186
185 187 kwargs = get_paginator(Device, page, order)
186 188 kwargs['keys'] = ['name', 'ip_address', 'port_address', 'device_type']
187 189 kwargs['title'] = 'Device'
188 190 kwargs['suptitle'] = 'List'
189 191 kwargs['no_sidebar'] = True
190 192
191 193 return render(request, 'base_list.html', kwargs)
192 194
193 195
194 196 def device(request, id_dev):
195 197
196 198 device = get_object_or_404(Device, pk=id_dev)
197 199
198 200 kwargs = {}
199 201 kwargs['device'] = device
200 202 kwargs['device_keys'] = ['device_type', 'name', 'ip_address', 'port_address', 'description']
201 203
202 204 kwargs['title'] = 'Device'
203 205 kwargs['suptitle'] = 'Details'
204 206
205 207 return render(request, 'device.html', kwargs)
206 208
207 209
208 210 @user_passes_test(lambda u:u.is_staff)
209 211 def device_new(request):
210 212
211 213 if request.method == 'GET':
212 214 form = DeviceForm()
213 215
214 216 if request.method == 'POST':
215 217 form = DeviceForm(request.POST)
216 218
217 219 if form.is_valid():
218 220 form.save()
219 221 return redirect('url_devices')
220 222
221 223 kwargs = {}
222 224 kwargs['form'] = form
223 225 kwargs['title'] = 'Device'
224 226 kwargs['suptitle'] = 'New'
225 227 kwargs['button'] = 'Create'
226 228
227 229 return render(request, 'base_edit.html', kwargs)
228 230
229 231
230 232 @user_passes_test(lambda u:u.is_staff)
231 233 def device_edit(request, id_dev):
232 234
233 235 device = get_object_or_404(Device, pk=id_dev)
234 236
235 237 if request.method=='GET':
236 238 form = DeviceForm(instance=device)
237 239
238 240 if request.method=='POST':
239 241 form = DeviceForm(request.POST, instance=device)
240 242
241 243 if form.is_valid():
242 244 form.save()
243 245 return redirect(device.get_absolute_url())
244 246
245 247 kwargs = {}
246 248 kwargs['form'] = form
247 249 kwargs['title'] = 'Device'
248 250 kwargs['suptitle'] = 'Edit'
249 251 kwargs['button'] = 'Update'
250 252
251 253 return render(request, 'base_edit.html', kwargs)
252 254
253 255
254 256 @user_passes_test(lambda u:u.is_staff)
255 257 def device_delete(request, id_dev):
256 258
257 259 device = get_object_or_404(Device, pk=id_dev)
258 260
259 261 if request.method=='POST':
260 262
261 263 if request.user.is_staff:
262 264 device.delete()
263 265 return redirect('url_devices')
264 266
265 267 messages.error(request, 'Not enough permission to delete this object')
266 268 return redirect(device.get_absolute_url())
267 269
268 270 kwargs = {
269 271 'title': 'Delete',
270 272 'suptitle': 'Device',
271 273 'object': device,
272 274 'previous': device.get_absolute_url(),
273 275 'delete': True
274 276 }
275 277
276 278 return render(request, 'confirm.html', kwargs)
277 279
278 280
279 281 @user_passes_test(lambda u:u.is_staff)
280 282 def device_change_ip(request, id_dev):
281 283
282 284 device = get_object_or_404(Device, pk=id_dev)
283 285
284 286 if request.method=='POST':
285 287
286 288 if request.user.is_staff:
287 289 device.change_ip(**request.POST.dict())
288 290 level, message = device.message.split('|')
289 291 messages.add_message(request, level, message)
290 292 else:
291 293 messages.error(request, 'Not enough permission to delete this object')
292 294 return redirect(device.get_absolute_url())
293 295
294 296 kwargs = {
295 297 'title': 'Device',
296 298 'suptitle': 'Change IP',
297 299 'object': device,
298 300 'previous': device.get_absolute_url(),
299 301 'form': ChangeIpForm(initial={'ip_address':device.ip_address}),
300 302 'message' : ' ',
301 303 }
302 304
303 305 return render(request, 'confirm.html', kwargs)
304 306
305 307
306 308 def campaigns(request):
307 309
308 310 page = request.GET.get('page')
309 311 order = ('start_date',)
310 312 filters = request.GET.copy()
311 313
312 314 kwargs = get_paginator(Campaign, page, order, filters)
313 315
314 316 form = FilterForm(initial=request.GET, extra_fields=['range_date', 'tags','template'])
315 317 kwargs['keys'] = ['name', 'start_date', 'end_date']
316 318 kwargs['title'] = 'Campaign'
317 319 kwargs['suptitle'] = 'List'
318 320 kwargs['no_sidebar'] = True
319 321 kwargs['form'] = form
320 322 filters.pop('page', None)
321 323 kwargs['q'] = urlencode(filters)
322 324
323 325 return render(request, 'base_list.html', kwargs)
324 326
325 327
326 328 def campaign(request, id_camp):
327 329
328 330 campaign = get_object_or_404(Campaign, pk=id_camp)
329 331 experiments = Experiment.objects.filter(campaign=campaign)
330 332
331 333 form = CampaignForm(instance=campaign)
332 334
333 335 kwargs = {}
334 336 kwargs['campaign'] = campaign
335 337 kwargs['campaign_keys'] = ['template', 'name', 'start_date', 'end_date', 'tags', 'description']
336 338
337 339 kwargs['experiments'] = experiments
338 340 kwargs['experiment_keys'] = ['name', 'radar_system', 'start_time', 'end_time']
339 341
340 342 kwargs['title'] = 'Campaign'
341 343 kwargs['suptitle'] = 'Details'
342 344
343 345 kwargs['form'] = form
344 346 kwargs['button'] = 'Add Experiment'
345 347
346 348 return render(request, 'campaign.html', kwargs)
347 349
348 350
349 351 @user_passes_test(lambda u:u.is_staff)
350 352 def campaign_new(request):
351 353
352 354 kwargs = {}
353 355
354 356 if request.method == 'GET':
355 357
356 358 if 'template' in request.GET:
357 359 if request.GET['template']=='0':
358 360 form = NewForm(initial={'create_from':2},
359 361 template_choices=Campaign.objects.filter(template=True).values_list('id', 'name'))
360 362 else:
361 363 kwargs['button'] = 'Create'
362 364 kwargs['experiments'] = Configuration.objects.filter(experiment=request.GET['template'])
363 365 kwargs['experiment_keys'] = ['name', 'start_time', 'end_time']
364 366 camp = Campaign.objects.get(pk=request.GET['template'])
365 367 form = CampaignForm(instance=camp,
366 368 initial={'name':'{}_{:%Y%m%d}'.format(camp.name, datetime.now()),
367 369 'template':False})
368 370 elif 'blank' in request.GET:
369 371 kwargs['button'] = 'Create'
370 372 form = CampaignForm()
371 373 else:
372 374 form = NewForm()
373 375
374 376 if request.method == 'POST':
375 377 kwargs['button'] = 'Create'
376 378 post = request.POST.copy()
377 379 experiments = []
378 380
379 381 for id_exp in post.getlist('experiments'):
380 382 exp = Experiment.objects.get(pk=id_exp)
381 383 new_exp = exp.clone(template=False)
382 384 experiments.append(new_exp)
383 385
384 386 post.setlist('experiments', [])
385 387
386 388 form = CampaignForm(post)
387 389
388 390 if form.is_valid():
389 391 campaign = form.save()
390 392 for exp in experiments:
391 393 campaign.experiments.add(exp)
392 394 campaign.save()
393 395 return redirect('url_campaign', id_camp=campaign.id)
394 396
395 397 kwargs['form'] = form
396 398 kwargs['title'] = 'Campaign'
397 399 kwargs['suptitle'] = 'New'
398 400
399 401 return render(request, 'campaign_edit.html', kwargs)
400 402
401 403
402 404 @user_passes_test(lambda u:u.is_staff)
403 405 def campaign_edit(request, id_camp):
404 406
405 407 campaign = get_object_or_404(Campaign, pk=id_camp)
406 408
407 409 if request.method=='GET':
408 410 form = CampaignForm(instance=campaign)
409 411
410 412 if request.method=='POST':
411 413 exps = campaign.experiments.all().values_list('pk', flat=True)
412 414 post = request.POST.copy()
413 415 new_exps = post.getlist('experiments')
414 416 post.setlist('experiments', [])
415 417 form = CampaignForm(post, instance=campaign)
416 418
417 419 if form.is_valid():
418 420 camp = form.save()
419 421 for id_exp in new_exps:
420 422 if int(id_exp) in exps:
421 423 exps.pop(id_exp)
422 424 else:
423 425 exp = Experiment.objects.get(pk=id_exp)
424 426 if exp.template:
425 427 camp.experiments.add(exp.clone(template=False))
426 428 else:
427 429 camp.experiments.add(exp)
428 430
429 431 for id_exp in exps:
430 432 camp.experiments.remove(Experiment.objects.get(pk=id_exp))
431 433
432 434 return redirect('url_campaign', id_camp=id_camp)
433 435
434 436 kwargs = {}
435 437 kwargs['form'] = form
436 438 kwargs['title'] = 'Campaign'
437 439 kwargs['suptitle'] = 'Edit'
438 440 kwargs['button'] = 'Update'
439 441
440 442 return render(request, 'campaign_edit.html', kwargs)
441 443
442 444
443 445 @user_passes_test(lambda u:u.is_staff)
444 446 def campaign_delete(request, id_camp):
445 447
446 448 campaign = get_object_or_404(Campaign, pk=id_camp)
447 449
448 450 if request.method=='POST':
449 451 if request.user.is_staff:
450 452
451 453 for exp in campaign.experiments.all():
452 454 for conf in Configuration.objects.filter(experiment=exp):
453 455 conf.delete()
454 456 exp.delete()
455 457 campaign.delete()
456 458
457 459 return redirect('url_campaigns')
458 460
459 461 messages.error(request, 'Not enough permission to delete this object')
460 462 return redirect(campaign.get_absolute_url())
461 463
462 464 kwargs = {
463 465 'title': 'Delete',
464 466 'suptitle': 'Campaign',
465 467 'object': campaign,
466 468 'previous': campaign.get_absolute_url(),
467 469 'delete': True
468 470 }
469 471
470 472 return render(request, 'confirm.html', kwargs)
471 473
472 474
473 475 @user_passes_test(lambda u:u.is_staff)
474 476 def campaign_export(request, id_camp):
475 477
476 478 campaign = get_object_or_404(Campaign, pk=id_camp)
477 479 content = campaign.parms_to_dict()
478 480 content_type = 'application/json'
479 481 filename = '%s_%s.json' %(campaign.name, campaign.id)
480 482
481 483 response = HttpResponse(content_type=content_type)
482 484 response['Content-Disposition'] = 'attachment; filename="%s"' %filename
483 485 response.write(json.dumps(content, indent=2))
484 486
485 487 return response
486 488
487 489
488 490 @user_passes_test(lambda u:u.is_staff)
489 491 def campaign_import(request, id_camp):
490 492
491 493 campaign = get_object_or_404(Campaign, pk=id_camp)
492 494
493 495 if request.method == 'GET':
494 496 file_form = UploadFileForm()
495 497
496 498 if request.method == 'POST':
497 499 file_form = UploadFileForm(request.POST, request.FILES)
498 500
499 501 if file_form.is_valid():
500 502 new_camp = campaign.dict_to_parms(json.load(request.FILES['file']), CONF_MODELS)
501 503 messages.success(request, "Parameters imported from: '%s'." %request.FILES['file'].name)
502 504 return redirect(new_camp.get_absolute_url_edit())
503 505
504 506 messages.error(request, "Could not import parameters from file")
505 507
506 508 kwargs = {}
507 509 kwargs['title'] = 'Campaign'
508 510 kwargs['form'] = file_form
509 511 kwargs['suptitle'] = 'Importing file'
510 512 kwargs['button'] = 'Import'
511 513
512 514 return render(request, 'campaign_import.html', kwargs)
513 515
514 516
515 517 def experiments(request):
516 518
517 519 page = request.GET.get('page')
518 520 order = ('location',)
519 521 filters = request.GET.copy()
520 522
521 523 kwargs = get_paginator(Experiment, page, order, filters)
522 524
523 525 form = FilterForm(initial=request.GET, extra_fields=['tags','template'])
524 526
525 527 kwargs['keys'] = ['name', 'radar_system', 'start_time', 'end_time']
526 528 kwargs['title'] = 'Experiment'
527 529 kwargs['suptitle'] = 'List'
528 530 kwargs['no_sidebar'] = True
529 531 kwargs['form'] = form
530 532 filters.pop('page', None)
531 533 kwargs['q'] = urlencode(filters)
532 534
533 535 return render(request, 'base_list.html', kwargs)
534 536
535 537
536 538 def experiment(request, id_exp):
537 539
538 540 experiment = get_object_or_404(Experiment, pk=id_exp)
539 541
540 542 configurations = Configuration.objects.filter(experiment=experiment, type=0)
541 543
542 544 kwargs = {}
543 545
544 546 kwargs['experiment_keys'] = ['template', 'radar_system', 'name', 'freq', 'start_time', 'end_time']
545 547 kwargs['experiment'] = experiment
546 548
547 549 kwargs['configuration_keys'] = ['name', 'device__ip_address', 'device__port_address', 'device__status']
548 550 kwargs['configurations'] = configurations
549 551
550 552 kwargs['title'] = 'Experiment'
551 553 kwargs['suptitle'] = 'Details'
552 554
553 555 kwargs['button'] = 'Add Configuration'
554 556
555 557 ###### SIDEBAR ######
556 558 kwargs.update(sidebar(experiment=experiment))
557 559
558 560 return render(request, 'experiment.html', kwargs)
559 561
560 562
561 563 @user_passes_test(lambda u:u.is_staff)
562 564 def experiment_new(request, id_camp=None):
563 565
564 566 kwargs = {}
565 567
566 568 if request.method == 'GET':
567 569 if 'template' in request.GET:
568 570 if request.GET['template']=='0':
569 571 form = NewForm(initial={'create_from':2},
570 572 template_choices=Experiment.objects.filter(template=True).values_list('id', 'name'))
571 573 else:
572 574 kwargs['button'] = 'Create'
573 575 kwargs['configurations'] = Configuration.objects.filter(experiment=request.GET['template'])
574 576 kwargs['configuration_keys'] = ['name', 'device__name', 'device__ip_address', 'device__port_address']
575 577 exp=Experiment.objects.get(pk=request.GET['template'])
576 578 form = ExperimentForm(instance=exp,
577 579 initial={'name': '{}_{:%y%m%d}'.format(exp.name, datetime.now()),
578 580 'template': False})
579 581 elif 'blank' in request.GET:
580 582 kwargs['button'] = 'Create'
581 583 form = ExperimentForm()
582 584 else:
583 585 form = NewForm()
584 586
585 587 if request.method == 'POST':
586 588 form = ExperimentForm(request.POST)
587 589 if form.is_valid():
588 590 experiment = form.save()
589 591
590 592 if 'template' in request.GET:
591 593 configurations = Configuration.objects.filter(experiment=request.GET['template'], type=0)
592 594 for conf in configurations:
593 595 conf.clone(experiment=experiment, template=False)
594 596
595 597 return redirect('url_experiment', id_exp=experiment.id)
596 598
597 599 kwargs['form'] = form
598 600 kwargs['title'] = 'Experiment'
599 601 kwargs['suptitle'] = 'New'
600 602
601 603 return render(request, 'experiment_edit.html', kwargs)
602 604
603 605
604 606 @user_passes_test(lambda u:u.is_staff)
605 607 def experiment_edit(request, id_exp):
606 608
607 609 experiment = get_object_or_404(Experiment, pk=id_exp)
608 610
609 611 if request.method == 'GET':
610 612 form = ExperimentForm(instance=experiment)
611 613
612 614 if request.method=='POST':
613 615 form = ExperimentForm(request.POST, instance=experiment)
614 616
615 617 if form.is_valid():
616 618 experiment = form.save()
617 619 return redirect('url_experiment', id_exp=experiment.id)
618 620
619 621 kwargs = {}
620 622 kwargs['form'] = form
621 623 kwargs['title'] = 'Experiment'
622 624 kwargs['suptitle'] = 'Edit'
623 625 kwargs['button'] = 'Update'
624 626
625 627 return render(request, 'experiment_edit.html', kwargs)
626 628
627 629
628 630 @user_passes_test(lambda u:u.is_staff)
629 631 def experiment_delete(request, id_exp):
630 632
631 633 experiment = get_object_or_404(Experiment, pk=id_exp)
632 634
633 635 if request.method=='POST':
634 636 if request.user.is_staff:
635 637 for conf in Configuration.objects.filter(experiment=experiment):
636 638 conf.delete()
637 639 experiment.delete()
638 640 return redirect('url_experiments')
639 641
640 642 messages.error(request, 'Not enough permission to delete this object')
641 643 return redirect(experiment.get_absolute_url())
642 644
643 645 kwargs = {
644 646 'title': 'Delete',
645 647 'suptitle': 'Experiment',
646 648 'object': experiment,
647 649 'previous': experiment.get_absolute_url(),
648 650 'delete': True
649 651 }
650 652
651 653 return render(request, 'confirm.html', kwargs)
652 654
653 655
654 656 @user_passes_test(lambda u:u.is_staff)
655 657 def experiment_export(request, id_exp):
656 658
657 659 experiment = get_object_or_404(Experiment, pk=id_exp)
658 660 content = experiment.parms_to_dict()
659 661 content_type = 'application/json'
660 662 filename = '%s_%s.json' %(experiment.name, experiment.id)
661 663
662 664 response = HttpResponse(content_type=content_type)
663 665 response['Content-Disposition'] = 'attachment; filename="%s"' %filename
664 666 response.write(json.dumps(content, indent=2))
665 667
666 668 return response
667 669
668 670
669 671 @user_passes_test(lambda u:u.is_staff)
670 672 def experiment_import(request, id_exp):
671 673
672 674 experiment = get_object_or_404(Experiment, pk=id_exp)
673 675 configurations = Configuration.objects.filter(experiment=experiment)
674 676
675 677 if request.method == 'GET':
676 678 file_form = UploadFileForm()
677 679
678 680 if request.method == 'POST':
679 681 file_form = UploadFileForm(request.POST, request.FILES)
680 682
681 683 if file_form.is_valid():
682 684 new_exp = experiment.dict_to_parms(json.load(request.FILES['file']), CONF_MODELS)
683 685 messages.success(request, "Parameters imported from: '%s'." %request.FILES['file'].name)
684 686 return redirect(new_exp.get_absolute_url_edit())
685 687
686 688 messages.error(request, "Could not import parameters from file")
687 689
688 690 kwargs = {}
689 691 kwargs['title'] = 'Experiment'
690 692 kwargs['form'] = file_form
691 693 kwargs['suptitle'] = 'Importing file'
692 694 kwargs['button'] = 'Import'
693 695
694 696 kwargs.update(sidebar(experiment=experiment))
695 697
696 698 return render(request, 'experiment_import.html', kwargs)
697 699
698 700
699 701 @user_passes_test(lambda u:u.is_staff)
700 702 def experiment_start(request, id_exp):
701 703
702 704 exp = get_object_or_404(Experiment, pk=id_exp)
703 705
704 706 if exp.status == 2:
705 707 messages.warning(request, 'Experiment {} already runnnig'.format(exp))
706 708 else:
707 709 exp.status = exp.start()
708 710 if exp.status==0:
709 711 messages.error(request, 'Experiment {} not start'.format(exp))
710 712 if exp.status==2:
711 713 messages.success(request, 'Experiment {} started'.format(exp))
712 714
713 715 exp.save()
714 716
715 717 return redirect(exp.get_absolute_url())
716 718
717 719
718 720 @user_passes_test(lambda u:u.is_staff)
719 721 def experiment_stop(request, id_exp):
720 722
721 723 exp = get_object_or_404(Experiment, pk=id_exp)
722 724
723 725 if exp.status == 2:
724 726 exp.status = exp.stop()
725 727 exp.save()
726 728 messages.success(request, 'Experiment {} stopped'.format(exp))
727 729 else:
728 730 messages.error(request, 'Experiment {} not running'.format(exp))
729 731
730 732 return redirect(exp.get_absolute_url())
731 733
732 734
733 735 def experiment_status(request, id_exp):
734 736
735 737 exp = get_object_or_404(Experiment, pk=id_exp)
736 738
737 739 exp.get_status()
738 740
739 741 return redirect(exp.get_absolute_url())
740 742
741 743
742 744 @user_passes_test(lambda u:u.is_staff)
743 745 def experiment_mix(request, id_exp):
744 746
745 747 experiment = get_object_or_404(Experiment, pk=id_exp)
746 748 rc_confs = [conf for conf in RCConfiguration.objects.filter(experiment=id_exp,
747 749 mix=False)]
748 750
749 751 if len(rc_confs)<2:
750 752 messages.warning(request, 'You need at least two RC Configurations to make a mix')
751 753 return redirect(experiment.get_absolute_url())
752 754
753 755 mix_confs = RCConfiguration.objects.filter(experiment=id_exp, mix=True)
754 756
755 757 if mix_confs:
756 758 mix = mix_confs[0]
757 759 else:
758 760 mix = RCConfiguration(experiment=experiment,
759 761 device=rc_confs[0].device,
760 762 ipp=rc_confs[0].ipp,
761 763 clock_in=rc_confs[0].clock_in,
762 764 clock_divider=rc_confs[0].clock_divider,
763 765 mix=True,
764 766 parameters='')
765 767 mix.save()
766 768
767 769 line_type = RCLineType.objects.get(name='mix')
768 770 for i in range(len(rc_confs[0].get_lines())):
769 771 line = RCLine(rc_configuration=mix, line_type=line_type, channel=i)
770 772 line.save()
771 773
772 774 initial = {'name': mix.name,
773 775 'result': parse_mix_result(mix.parameters),
774 776 'delay': 0,
775 777 'mask': [0,1,2,3,4,5,6,7]
776 778 }
777 779
778 780 if request.method=='GET':
779 781 form = RCMixConfigurationForm(confs=rc_confs, initial=initial)
780 782
781 783 if request.method=='POST':
782 784 result = mix.parameters
783 785
784 786 if '{}|'.format(request.POST['experiment']) in result:
785 787 messages.error(request, 'Configuration already added')
786 788 else:
787 789 if 'operation' in request.POST:
788 790 operation = MIX_OPERATIONS[request.POST['operation']]
789 791 else:
790 792 operation = ' '
791 793
792 794 mode = MIX_MODES[request.POST['mode']]
793 795
794 796 if result:
795 797 result = '{}-{}|{}|{}|{}|{}'.format(mix.parameters,
796 798 request.POST['experiment'],
797 799 mode,
798 800 operation,
799 801 float(request.POST['delay']),
800 802 parse_mask(request.POST.getlist('mask'))
801 803 )
802 804 else:
803 805 result = '{}|{}|{}|{}|{}'.format(request.POST['experiment'],
804 806 mode,
805 807 operation,
806 808 float(request.POST['delay']),
807 809 parse_mask(request.POST.getlist('mask'))
808 810 )
809 811
810 812 mix.parameters = result
811 813 mix.name = request.POST['name']
812 814 mix.save()
813 815 mix.update_pulses()
814 816
815 817 initial['result'] = parse_mix_result(result)
816 818 initial['name'] = mix.name
817 819
818 820 form = RCMixConfigurationForm(initial=initial, confs=rc_confs)
819 821
820 822
821 823 kwargs = {
822 824 'title': 'Experiment',
823 825 'suptitle': 'Mix Configurations',
824 826 'form' : form,
825 827 'extra_button': 'Delete',
826 828 'button': 'Add',
827 829 'cancel': 'Back',
828 830 'previous': experiment.get_absolute_url(),
829 831 'id_exp':id_exp,
830 832
831 833 }
832 834
833 835 return render(request, 'experiment_mix.html', kwargs)
834 836
835 837
836 838 @user_passes_test(lambda u:u.is_staff)
837 839 def experiment_mix_delete(request, id_exp):
838 840
839 conf = RCConfiguration.objects.get(experiment=id_exp, mix=True)
841 conf = RCConfiguration.objects.get(experiment=id_exp, mix=True, type=0)
840 842 values = conf.parameters.split('-')
841 843 conf.parameters = '-'.join(values[:-1])
842 844 conf.save()
843 845
844 846 return redirect('url_mix_experiment', id_exp=id_exp)
845 847
846 848
847 849 def experiment_summary(request, id_exp):
848 850
849 851 experiment = get_object_or_404(Experiment, pk=id_exp)
850 852 configurations = Configuration.objects.filter(experiment=experiment, type=0)
851 853
852 854 kwargs = {}
853 855
854 856 kwargs['experiment_keys'] = ['radar_system', 'name', 'freq', 'start_time', 'end_time']
855 857 kwargs['experiment'] = experiment
856 858
857 859 kwargs['configurations'] = []
858 860
859 861 kwargs['title'] = 'Experiment Summary'
860 862 kwargs['suptitle'] = 'Details'
861 863
862 864 kwargs['button'] = 'Verify Parameters'
863 865
864 866 c_vel = 3.0*(10**8) #m/s
865 867 ope_freq = experiment.freq*(10**6) #1/s
866 868 radar_lambda = c_vel/ope_freq #m
867 869 kwargs['radar_lambda'] = radar_lambda
868 870
869 871 jars_conf = False
870 872 rc_conf = False
871 873 code_id = 0
872 874 tx_line = {}
873 875
874 876 for configuration in configurations:
875 877
876 878 #--------------------- RC ----------------------:
877 879 if configuration.device.device_type.name == 'rc':
878 880 if configuration.mix:
879 881 continue
880 882 rc_conf = True
881 883 ipp = configuration.ipp
882 884 lines = configuration.get_lines(line_type__name='tx')
883 885 configuration.tx_lines = []
884 886
885 887 for tx_line in lines:
886 888 if tx_line.get_name()[-1] == 'A':
887 889 txa_line = tx_line
888 890 txa_params = json.loads(txa_line.params)
889 891 line = {'name':tx_line.get_name()}
890 892 tx_params = json.loads(tx_line.params)
891 893 line['width'] = tx_params['pulse_width']
892 894 if line['width'] in (0, '0'):
893 895 continue
894 896 delays = tx_params['delays']
895 897
896 898 if delays not in ('', '0'):
897 899 n = len(delays.split(','))
898 900 line['taus'] = '{} Taus: {}'.format(n, delays)
899 901 else:
900 902 line['taus'] = '-'
901 903
902 904 for code_line in configuration.get_lines(line_type__name='codes'):
903 905 code_params = json.loads(code_line.params)
904 906 code_id = code_params['code']
905 907 if tx_line.pk==int(code_params['TX_ref']):
906 908 line['codes'] = '{}:{}'.format(RCLineCode.objects.get(pk=code_params['code']),
907 909 '-'.join(code_params['codes']))
908 910
909 911 for windows_line in configuration.get_lines(line_type__name='windows'):
910 912 win_params = json.loads(windows_line.params)
911 913 if tx_line.pk==int(win_params['TX_ref']):
912 914 windows = ''
913 915 nsa = win_params['params'][0]['number_of_samples']
914 916 for i, params in enumerate(win_params['params']):
915 917 windows += 'W{}: Ho={first_height} km DH={resolution} km NSA={number_of_samples}<br>'.format(i, **params)
916 918 line['windows'] = mark_safe(windows)
917 919
918 920 configuration.tx_lines.append(line)
919 921
920 922 if txa_line:
921 923 kwargs['duty_cycle'] = float(txa_params['pulse_width'])/ipp*100
922 924
923 925 #-------------------- JARS -----------------------:
924 926 if configuration.device.device_type.name == 'jars':
925 927 jars_conf = True
926 928 kwargs['exp_type'] = EXPERIMENT_TYPE[configuration.exp_type][1]
927 929 channels_number = configuration.channels_number
928 930 exp_type = configuration.exp_type
929 931 fftpoints = configuration.fftpoints
930 932 filter_parms = configuration.filter_parms
931 933 filter_parms = ast.literal_eval(filter_parms)
932 934 spectral_number = configuration.spectral_number
933 935 acq_profiles = configuration.acq_profiles
934 936 cohe_integr = configuration.cohe_integr
935 937 profiles_block = configuration.profiles_block
936 938
937 939 if filter_parms.__class__.__name__=='str':
938 940 filter_parms = eval(filter_parms)
939 941
940 942 kwargs['configurations'].append(configuration)
941 943
942 944
943 945 #------ RC & JARS ------:
944 946 if rc_conf and jars_conf:
945 947 #RC filter values:
946 948
947 949 if exp_type == 0: #Short
948 950 bytes_ = 2
949 951 b = nsa*2*bytes_*channels_number
950 952 else: #Float
951 953 bytes_ = 4
952 954 channels = channels_number + spectral_number
953 955 b = nsa*2*bytes_*fftpoints*channels
954 956
955 957 codes_num = 7
956 958 if code_id == 2:
957 959 codes_num = 7
958 960 elif code_id == 12:
959 961 codes_num = 15
960 962
961 963 #Jars filter values:
962 964 try:
963 965 clock = eval(filter_parms['clock'])
964 966 filter_2 = eval(filter_parms['filter_2'])
965 967 filter_5 = eval(filter_parms['filter_5'])
966 968 filter_fir = eval(filter_parms['filter_fir'])
967 969 except:
968 970 clock = float(filter_parms['clock'])
969 971 filter_2 = int(filter_parms['filter_2'])
970 972 filter_5 = int(filter_parms['filter_5'])
971 973 filter_fir = int(filter_parms['filter_fir'])
972 974 Fs_MHz = clock/(filter_2*filter_5*filter_fir)
973 975
974 976 #Jars values:
975 977 IPP_units = ipp/0.15*Fs_MHz
976 978 IPP_us = IPP_units / Fs_MHz
977 979 IPP_s = IPP_units / (Fs_MHz * (10**6))
978 980 Ts = 1/(Fs_MHz*(10**6))
979 981
980 982 #Values
981 983 Va = radar_lambda/(4*Ts*cohe_integr)
982 984 rate_bh = ((nsa-codes_num)*channels_number*2*bytes_/IPP_us)*(36*(10**8)/cohe_integr)
983 985 rate_gh = rate_bh/(1024*1024*1024)
984 986 kwargs['rate_bh'] = str(rate_bh) + " (Bytes/h)"
985 987 kwargs['rate_gh'] = str(rate_gh)+" (GBytes/h)"
986 988 kwargs['va'] = Va
987 989 kwargs['time_per_block'] = IPP_s * profiles_block * cohe_integr
988 990 kwargs['acqtime'] = IPP_s * acq_profiles
989 991 kwargs['vrange'] = 3/(2*IPP_s*cohe_integr)
990 992
991 993 else:
992 994 kwargs['rate_bh'] = ''
993 995 kwargs['rate_gh'] = ''
994 996 kwargs['va'] = ''
995 997 kwargs['time_per_block'] = ''
996 998 kwargs['acqtime'] = ''
997 999 kwargs['vrange'] = ''
998 1000
999 1001 ###### SIDEBAR ######
1000 1002 kwargs.update(sidebar(experiment=experiment))
1001 1003
1002 1004 return render(request, 'experiment_summary.html', kwargs)
1003 1005
1004 1006
1005 1007 @user_passes_test(lambda u:u.is_staff)
1006 1008 def experiment_verify(request, id_exp):
1007 1009
1008 1010 experiment = get_object_or_404(Experiment, pk=id_exp)
1009 1011 experiment_data = experiment.parms_to_dict()
1010 1012 configurations = Configuration.objects.filter(experiment=experiment, type=0)
1011 1013
1012 1014 kwargs = {}
1013 1015
1014 1016 kwargs['experiment_keys'] = ['template', 'radar_system', 'name', 'start_time', 'end_time']
1015 1017 kwargs['experiment'] = experiment
1016 1018
1017 1019 kwargs['configuration_keys'] = ['name', 'device__ip_address', 'device__port_address', 'device__status']
1018 1020 kwargs['configurations'] = configurations
1019 1021 kwargs['experiment_data'] = experiment_data
1020 1022
1021 1023 kwargs['title'] = 'Verify Experiment'
1022 1024 kwargs['suptitle'] = 'Parameters'
1023 1025
1024 1026 kwargs['button'] = 'Update'
1025 1027
1026 1028 jars_conf = False
1027 1029 rc_conf = False
1028 1030 dds_conf = False
1029 1031
1030 1032 for configuration in configurations:
1031 1033 #-------------------- JARS -----------------------:
1032 1034 if configuration.device.device_type.name == 'jars':
1033 1035 jars_conf = True
1034 1036 jars = configuration
1035 1037 kwargs['jars_conf'] = jars_conf
1036 1038 filter_parms = jars.filter_parms
1037 1039 filter_parms = ast.literal_eval(filter_parms)
1038 1040 kwargs['filter_parms'] = filter_parms
1039 1041 #--Sampling Frequency
1040 1042 clock = eval(filter_parms['clock'])
1041 1043 filter_2 = eval(filter_parms['filter_2'])
1042 1044 filter_5 = eval(filter_parms['filter_5'])
1043 1045 filter_fir = eval(filter_parms['filter_fir'])
1044 1046 samp_freq_jars = clock/filter_2/filter_5/filter_fir
1045 1047
1046 1048 kwargs['samp_freq_jars'] = samp_freq_jars
1047 1049 kwargs['jars'] = configuration
1048 1050
1049 1051 #--------------------- RC ----------------------:
1050 1052 if configuration.device.device_type.name == 'rc' and not configuration.mix:
1051 1053 rc_conf = True
1052 1054 rc = configuration
1053 1055
1054 1056 rc_parms = configuration.parms_to_dict()
1055 1057
1056 1058 win_lines = rc.get_lines(line_type__name='windows')
1057 1059 if win_lines:
1058 1060 dh = json.loads(win_lines[0].params)['params'][0]['resolution']
1059 1061 #--Sampling Frequency
1060 1062 samp_freq_rc = 0.15/dh
1061 1063 kwargs['samp_freq_rc'] = samp_freq_rc
1062 1064
1063 1065 kwargs['rc_conf'] = rc_conf
1064 1066 kwargs['rc'] = configuration
1065 1067
1066 1068 #-------------------- DDS ----------------------:
1067 1069 if configuration.device.device_type.name == 'dds':
1068 1070 dds_conf = True
1069 1071 dds = configuration
1070 1072 dds_parms = configuration.parms_to_dict()
1071 1073
1072 1074 kwargs['dds_conf'] = dds_conf
1073 1075 kwargs['dds'] = configuration
1074 1076
1075 1077
1076 1078 #------------Validation------------:
1077 1079 #Clock
1078 1080 if dds_conf and rc_conf and jars_conf:
1079 1081 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']):
1080 1082 messages.warning(request, "Devices don't have the same clock.")
1081 1083 elif rc_conf and jars_conf:
1082 1084 if float(filter_parms['clock']) != float(rc_parms['configurations']['byId'][str(rc.pk)]['clock_in']):
1083 1085 messages.warning(request, "Devices don't have the same clock.")
1084 1086 elif rc_conf and dds_conf:
1085 1087 if float(rc_parms['configurations']['byId'][str(rc.pk)]['clock_in']) != float(dds_parms['configurations']['byId'][str(dds.pk)]['clock']):
1086 1088 messages.warning(request, "Devices don't have the same clock.")
1087 1089 if float(samp_freq_rc) != float(dds_parms['configurations']['byId'][str(dds.pk)]['frequencyA']):
1088 1090 messages.warning(request, "Devices don't have the same Frequency A.")
1089 1091
1090 1092
1091 1093 #------------POST METHOD------------:
1092 1094 if request.method == 'POST':
1093 1095 if request.POST['suggest_clock']:
1094 1096 try:
1095 1097 suggest_clock = float(request.POST['suggest_clock'])
1096 1098 except:
1097 1099 messages.warning(request, "Invalid value in CLOCK IN.")
1098 1100 return redirect('url_verify_experiment', id_exp=experiment.id)
1099 1101 else:
1100 1102 suggest_clock = ""
1101 1103 if suggest_clock:
1102 1104 if rc_conf:
1103 1105 rc.clock_in = suggest_clock
1104 1106 rc.save()
1105 1107 if jars_conf:
1106 1108 filter_parms = jars.filter_parms
1107 1109 filter_parms = ast.literal_eval(filter_parms)
1108 1110 filter_parms['clock'] = suggest_clock
1109 1111 jars.filter_parms = json.dumps(filter_parms)
1110 1112 jars.save()
1111 1113 kwargs['filter_parms'] = filter_parms
1112 1114 if dds_conf:
1113 1115 dds.clock = suggest_clock
1114 1116 dds.save()
1115 1117
1116 1118 if request.POST['suggest_frequencyA']:
1117 1119 try:
1118 1120 suggest_frequencyA = float(request.POST['suggest_frequencyA'])
1119 1121 except:
1120 1122 messages.warning(request, "Invalid value in FREQUENCY A.")
1121 1123 return redirect('url_verify_experiment', id_exp=experiment.id)
1122 1124 else:
1123 1125 suggest_frequencyA = ""
1124 1126 if suggest_frequencyA:
1125 1127 if jars_conf:
1126 1128 filter_parms = jars.filter_parms
1127 1129 filter_parms = ast.literal_eval(filter_parms)
1128 1130 filter_parms['fch'] = suggest_frequencyA
1129 1131 jars.filter_parms = json.dumps(filter_parms)
1130 1132 jars.save()
1131 1133 kwargs['filter_parms'] = filter_parms
1132 1134 if dds_conf:
1133 1135 dds.frequencyA_Mhz = request.POST['suggest_frequencyA']
1134 1136 dds.save()
1135 1137
1136 1138 ###### SIDEBAR ######
1137 1139 kwargs.update(sidebar(experiment=experiment))
1138 1140
1139 1141
1140 1142
1141 1143
1142 1144
1143 1145 return render(request, 'experiment_verify.html', kwargs)
1144 1146
1145 1147
1146 1148 #@user_passes_test(lambda u:u.is_staff)
1147 1149 def parse_mix_result(s):
1148 1150
1149 1151 values = s.split('-')
1150 1152 html = 'EXP MOD OPE DELAY MASK\r\n'
1151 1153
1152 1154 if not values or values[0] in ('', ' '):
1153 1155 return mark_safe(html)
1154 1156
1155 1157 for i, value in enumerate(values):
1156 1158 if not value:
1157 1159 continue
1158 1160 pk, mode, operation, delay, mask = value.split('|')
1159 1161 conf = RCConfiguration.objects.get(pk=pk)
1160 1162 if i==0:
1161 1163 html += '{:20.18}{:3}{:4}{:9}km{:>6}\r\n'.format(
1162 1164 conf.name,
1163 1165 mode,
1164 1166 ' ',
1165 1167 delay,
1166 1168 mask)
1167 1169 else:
1168 1170 html += '{:20.18}{:3}{:4}{:9}km{:>6}\r\n'.format(
1169 1171 conf.name,
1170 1172 mode,
1171 1173 operation,
1172 1174 delay,
1173 1175 mask)
1174 1176
1175 1177 return mark_safe(html)
1176 1178
1177 1179 def parse_mask(l):
1178 1180
1179 1181 values = []
1180 1182
1181 1183 for x in range(8):
1182 1184 if '{}'.format(x) in l:
1183 1185 values.append(1)
1184 1186 else:
1185 1187 values.append(0)
1186 1188
1187 1189 values.reverse()
1188 1190
1189 1191 return int(''.join([str(x) for x in values]), 2)
1190 1192
1191 1193
1192 1194 def dev_confs(request):
1193 1195
1194 1196
1195 1197 page = request.GET.get('page')
1196 1198 order = ('type', 'device__device_type', 'experiment')
1197 1199 filters = request.GET.copy()
1198 1200
1199 1201 kwargs = get_paginator(Configuration, page, order, filters)
1200 1202
1201 1203 form = FilterForm(initial=request.GET, extra_fields=['tags', 'template', 'historical'])
1202 1204 kwargs['keys'] = ['name', 'experiment', 'type', 'programmed_date']
1203 1205 kwargs['title'] = 'Configuration'
1204 1206 kwargs['suptitle'] = 'List'
1205 1207 kwargs['no_sidebar'] = True
1206 1208 kwargs['form'] = form
1207 1209 filters.pop('page', None)
1208 1210 kwargs['q'] = urlencode(filters)
1209 1211
1210 1212 return render(request, 'base_list.html', kwargs)
1211 1213
1212 1214
1213 1215 def dev_conf(request, id_conf):
1214 1216
1215 1217 conf = get_object_or_404(Configuration, pk=id_conf)
1216 1218
1217 1219 return redirect(conf.get_absolute_url())
1218 1220
1219 1221
1220 1222 @user_passes_test(lambda u:u.is_staff)
1221 1223 def dev_conf_new(request, id_exp=0, id_dev=0):
1222 1224
1223 1225 initial = {}
1224 1226 kwargs = {}
1225 1227
1226 1228 if id_exp!=0:
1227 1229 initial['experiment'] = id_exp
1228 1230
1229 1231 if id_dev!=0:
1230 1232 initial['device'] = id_dev
1231 1233
1232 1234 if request.method == 'GET':
1233 1235
1234 1236 if id_dev:
1235 1237 kwargs['button'] = 'Create'
1236 1238 device = Device.objects.get(pk=id_dev)
1237 1239 DevConfForm = CONF_FORMS[device.device_type.name]
1238 1240 initial['name'] = request.GET['name']
1239 1241 form = DevConfForm(initial=initial)
1240 1242 else:
1241 1243 if 'template' in request.GET:
1242 1244 if request.GET['template']=='0':
1243 1245 choices = [(conf.pk, '{}'.format(conf)) for conf in Configuration.objects.filter(template=True)]
1244 1246 form = NewForm(initial={'create_from':2},
1245 1247 template_choices=choices)
1246 1248 else:
1247 1249 kwargs['button'] = 'Create'
1248 1250 conf = Configuration.objects.get(pk=request.GET['template'])
1249 1251 id_dev = conf.device.pk
1250 1252 DevConfForm = CONF_FORMS[conf.device.device_type.name]
1251 1253 form = DevConfForm(instance=conf,
1252 1254 initial={'name': '{}_{:%y%m%d}'.format(conf.name, datetime.now()),
1253 1255 'template': False,
1254 1256 'experiment':id_exp})
1255 1257 elif 'blank' in request.GET:
1256 1258 kwargs['button'] = 'Create'
1257 1259 form = ConfigurationForm(initial=initial)
1258 1260 else:
1259 1261 form = NewForm()
1260 1262
1261 1263 if request.method == 'POST':
1262 1264
1263 1265 device = Device.objects.get(pk=request.POST['device'])
1264 1266 DevConfForm = CONF_FORMS[device.device_type.name]
1265 1267
1266 1268 form = DevConfForm(request.POST)
1267 1269 kwargs['button'] = 'Create'
1268 1270 if form.is_valid():
1269 1271 conf = form.save()
1270 1272
1271 1273 if 'template' in request.GET and conf.device.device_type.name=='rc':
1272 1274 lines = RCLine.objects.filter(rc_configuration=request.GET['template'])
1273 1275 for line in lines:
1274 1276 line.clone(rc_configuration=conf)
1275 1277
1276 1278 new_lines = conf.get_lines()
1277 1279 for line in new_lines:
1278 1280 line_params = json.loads(line.params)
1279 1281 if 'TX_ref' in line_params:
1280 1282 ref_line = RCLine.objects.get(pk=line_params['TX_ref'])
1281 1283 line_params['TX_ref'] = ['{}'.format(l.pk) for l in new_lines if l.get_name()==ref_line.get_name()][0]
1282 1284 line.params = json.dumps(line_params)
1283 1285 line.save()
1284 1286
1285 1287 return redirect('url_dev_conf', id_conf=conf.pk)
1286 1288
1287 1289 kwargs['id_exp'] = id_exp
1288 1290 kwargs['form'] = form
1289 1291 kwargs['title'] = 'Configuration'
1290 1292 kwargs['suptitle'] = 'New'
1291 1293
1292 1294
1293 1295 if id_dev != 0:
1294 1296 device = Device.objects.get(pk=id_dev)
1295 1297 kwargs['device'] = device.device_type.name
1296 1298
1297 1299 return render(request, 'dev_conf_edit.html', kwargs)
1298 1300
1299 1301
1300 1302 @user_passes_test(lambda u:u.is_staff)
1301 1303 def dev_conf_edit(request, id_conf):
1302 1304
1303 1305 conf = get_object_or_404(Configuration, pk=id_conf)
1304 1306
1305 1307 DevConfForm = CONF_FORMS[conf.device.device_type.name]
1306 1308
1307 1309 if request.method=='GET':
1308 1310 form = DevConfForm(instance=conf)
1309 1311
1310 1312 if request.method=='POST':
1311 1313 form = DevConfForm(request.POST, instance=conf)
1312 1314
1313 1315 if form.is_valid():
1314 1316 form.save()
1315 1317 return redirect('url_dev_conf', id_conf=id_conf)
1316 1318
1317 1319 kwargs = {}
1318 1320 kwargs['form'] = form
1319 1321 kwargs['title'] = 'Device Configuration'
1320 1322 kwargs['suptitle'] = 'Edit'
1321 1323 kwargs['button'] = 'Update'
1322 1324
1323 1325 ###### SIDEBAR ######
1324 1326 kwargs.update(sidebar(conf=conf))
1325 1327
1326 1328 return render(request, '%s_conf_edit.html' % conf.device.device_type.name, kwargs)
1327 1329
1328 1330
1329 1331 @user_passes_test(lambda u:u.is_staff)
1330 1332 def dev_conf_start(request, id_conf):
1331 1333
1332 1334 conf = get_object_or_404(Configuration, pk=id_conf)
1333 1335
1334 1336 if conf.start_device():
1335 1337 messages.success(request, conf.message)
1336 1338 else:
1337 1339 messages.error(request, conf.message)
1338 1340
1339 1341 #conf.status_device()
1340 1342
1341 1343 return redirect(conf.get_absolute_url())
1342 1344
1343 1345
1344 1346 @user_passes_test(lambda u:u.is_staff)
1345 1347 def dev_conf_stop(request, id_conf):
1346 1348
1347 1349 conf = get_object_or_404(Configuration, pk=id_conf)
1348 1350
1349 1351 if conf.stop_device():
1350 1352 messages.success(request, conf.message)
1351 1353 else:
1352 1354 messages.error(request, conf.message)
1353 1355
1354 1356 #conf.status_device()
1355 1357
1356 1358 return redirect(conf.get_absolute_url())
1357 1359
1358 1360
1359 1361 def dev_conf_status(request, id_conf):
1360 1362
1361 1363 conf = get_object_or_404(Configuration, pk=id_conf)
1362 1364
1363 1365 if conf.status_device():
1364 1366 messages.success(request, conf.message)
1365 1367 else:
1366 1368 messages.error(request, conf.message)
1367 1369
1368 1370 return redirect(conf.get_absolute_url())
1369 1371
1370 1372
1371 1373 @user_passes_test(lambda u:u.is_staff)
1372 1374 def dev_conf_reset(request, id_conf):
1373 1375
1374 1376 conf = get_object_or_404(Configuration, pk=id_conf)
1375 1377
1376 1378 if conf.reset_device():
1377 1379 messages.success(request, conf.message)
1378 1380 else:
1379 1381 messages.error(request, conf.message)
1380 1382
1381 1383 return redirect(conf.get_absolute_url())
1382 1384
1383 1385
1384 1386 @user_passes_test(lambda u:u.is_staff)
1385 1387 def dev_conf_write(request, id_conf):
1386 1388
1387 1389 conf = get_object_or_404(Configuration, pk=id_conf)
1388 1390
1389 1391 if conf.write_device():
1390 1392 messages.success(request, conf.message)
1391 1393 conf.clone(type=1, template=False)
1392 1394 else:
1393 1395 messages.error(request, conf.message)
1394 1396
1395 1397 return redirect(get_object_or_404(Configuration, pk=id_conf).get_absolute_url())
1396 1398
1397 1399
1398 1400 @user_passes_test(lambda u:u.is_staff)
1399 1401 def dev_conf_read(request, id_conf):
1400 1402
1401 1403 conf = get_object_or_404(Configuration, pk=id_conf)
1402 1404
1403 1405 DevConfForm = CONF_FORMS[conf.device.device_type.name]
1404 1406
1405 1407 if request.method=='GET':
1406 1408
1407 1409 parms = conf.read_device()
1408 1410 #conf.status_device()
1409 1411
1410 1412 if not parms:
1411 1413 messages.error(request, conf.message)
1412 1414 return redirect(conf.get_absolute_url())
1413 1415
1414 1416 form = DevConfForm(initial=parms, instance=conf)
1415 1417
1416 1418 if request.method=='POST':
1417 1419 form = DevConfForm(request.POST, instance=conf)
1418 1420
1419 1421 if form.is_valid():
1420 1422 form.save()
1421 1423 return redirect(conf.get_absolute_url())
1422 1424
1423 1425 messages.error(request, "Parameters could not be saved")
1424 1426
1425 1427 kwargs = {}
1426 1428 kwargs['id_dev'] = conf.id
1427 1429 kwargs['form'] = form
1428 1430 kwargs['title'] = 'Device Configuration'
1429 1431 kwargs['suptitle'] = 'Parameters read from device'
1430 1432 kwargs['button'] = 'Save'
1431 1433
1432 1434 ###### SIDEBAR ######
1433 1435 kwargs.update(sidebar(conf=conf))
1434 1436
1435 1437 return render(request, '%s_conf_edit.html' %conf.device.device_type.name, kwargs)
1436 1438
1437 1439
1438 1440 @user_passes_test(lambda u:u.is_staff)
1439 1441 def dev_conf_import(request, id_conf):
1440 1442
1441 1443 conf = get_object_or_404(Configuration, pk=id_conf)
1442 1444 DevConfForm = CONF_FORMS[conf.device.device_type.name]
1443 1445
1444 1446 if request.method == 'GET':
1445 1447 file_form = UploadFileForm()
1446 1448
1447 1449 if request.method == 'POST':
1448 1450 file_form = UploadFileForm(request.POST, request.FILES)
1449 1451
1450 1452 if file_form.is_valid():
1451 1453
1452 1454 data = conf.import_from_file(request.FILES['file'])
1453 1455 parms = Params(data=data).get_conf(dtype=conf.device.device_type.name)
1454 1456
1455 1457 if parms:
1456 1458
1457 1459 form = DevConfForm(initial=parms, instance=conf)
1458 1460
1459 1461 kwargs = {}
1460 1462 kwargs['id_dev'] = conf.id
1461 1463 kwargs['form'] = form
1462 1464 kwargs['title'] = 'Device Configuration'
1463 1465 kwargs['suptitle'] = 'Parameters imported'
1464 1466 kwargs['button'] = 'Save'
1465 1467 kwargs['action'] = conf.get_absolute_url_edit()
1466 1468 kwargs['previous'] = conf.get_absolute_url()
1467 1469
1468 1470 ###### SIDEBAR ######
1469 1471 kwargs.update(sidebar(conf=conf))
1470 1472
1471 1473 messages.success(request, "Parameters imported from: '%s'." %request.FILES['file'].name)
1472 1474
1473 1475 return render(request, '%s_conf_edit.html' % conf.device.device_type.name, kwargs)
1474 1476
1475 1477 messages.error(request, "Could not import parameters from file")
1476 1478
1477 1479 kwargs = {}
1478 1480 kwargs['id_dev'] = conf.id
1479 1481 kwargs['title'] = 'Device Configuration'
1480 1482 kwargs['form'] = file_form
1481 1483 kwargs['suptitle'] = 'Importing file'
1482 1484 kwargs['button'] = 'Import'
1483 1485
1484 1486 kwargs.update(sidebar(conf=conf))
1485 1487
1486 1488 return render(request, 'dev_conf_import.html', kwargs)
1487 1489
1488 1490
1489 1491 @user_passes_test(lambda u:u.is_staff)
1490 1492 def dev_conf_export(request, id_conf):
1491 1493
1492 1494 conf = get_object_or_404(Configuration, pk=id_conf)
1493 1495
1494 1496 if request.method == 'GET':
1495 1497 file_form = DownloadFileForm(conf.device.device_type.name)
1496 1498
1497 1499 if request.method == 'POST':
1498 1500 file_form = DownloadFileForm(conf.device.device_type.name, request.POST)
1499 1501
1500 1502 if file_form.is_valid():
1501 1503 fields = conf.export_to_file(format = file_form.cleaned_data['format'])
1502 1504 if not fields['content']:
1503 1505 messages.error(request, conf.message)
1504 1506 return redirect(conf.get_absolute_url_export())
1505 1507 response = HttpResponse(content_type=fields['content_type'])
1506 1508 response['Content-Disposition'] = 'attachment; filename="%s"' %fields['filename']
1507 1509 response.write(fields['content'])
1508 1510
1509 1511 return response
1510 1512
1511 1513 messages.error(request, "Could not export parameters")
1512 1514
1513 1515 kwargs = {}
1514 1516 kwargs['id_dev'] = conf.id
1515 1517 kwargs['title'] = 'Device Configuration'
1516 1518 kwargs['form'] = file_form
1517 1519 kwargs['suptitle'] = 'Exporting file'
1518 1520 kwargs['button'] = 'Export'
1519 1521
1520 1522 return render(request, 'dev_conf_export.html', kwargs)
1521 1523
1522 1524
1523 1525 @user_passes_test(lambda u:u.is_staff)
1524 1526 def dev_conf_delete(request, id_conf):
1525 1527
1526 1528 conf = get_object_or_404(Configuration, pk=id_conf)
1527 1529
1528 1530 if request.method=='POST':
1529 1531 if request.user.is_staff:
1530 1532 conf.delete()
1531 1533 return redirect('url_dev_confs')
1532 1534
1533 1535 messages.error(request, 'Not enough permission to delete this object')
1534 1536 return redirect(conf.get_absolute_url())
1535 1537
1536 1538 kwargs = {
1537 1539 'title': 'Delete',
1538 1540 'suptitle': 'Experiment',
1539 1541 'object': conf,
1540 1542 'previous': conf.get_absolute_url(),
1541 1543 'delete': True
1542 1544 }
1543 1545
1544 1546 return render(request, 'confirm.html', kwargs)
1545 1547
1546 1548
1547 1549 def sidebar(**kwargs):
1548 1550
1549 1551 side_data = {}
1550 1552
1551 1553 conf = kwargs.get('conf', None)
1552 1554 experiment = kwargs.get('experiment', None)
1553 1555
1554 1556 if not experiment:
1555 1557 experiment = conf.experiment
1556 1558
1557 1559 if experiment:
1558 1560 side_data['experiment'] = experiment
1559 1561 campaign = experiment.campaign_set.all()
1560 1562 if campaign:
1561 1563 side_data['campaign'] = campaign[0]
1562 1564 experiments = campaign[0].experiments.all()
1563 1565 else:
1564 1566 experiments = [experiment]
1565 1567 configurations = experiment.configuration_set.filter(type=0)
1566 1568 side_data['side_experiments'] = experiments
1567 1569 side_data['side_configurations'] = configurations
1568 1570
1569 1571 return side_data
1570 1572
1571 1573 def get_paginator(model, page, order, filters={}, n=10):
1572 1574
1573 1575 kwargs = {}
1574 1576 query = Q()
1575 1577 if isinstance(filters, QueryDict):
1576 1578 filters = filters.dict()
1577 1579 [filters.pop(key) for key in filters.keys() if filters[key] in ('', ' ')]
1578 1580 filters.pop('page', None)
1579 1581
1580 1582 fields = [f.name for f in model._meta.get_fields()]
1581 1583
1582 1584 if 'template' in filters:
1583 1585 filters['template'] = True
1584 1586 if 'historical' in filters:
1585 1587 filters.pop('historical')
1586 1588 filters['type'] = 1
1587 1589 elif 'type' in fields:
1588 1590 filters['type'] = 0
1589 1591 if 'start_date' in filters:
1590 1592 filters['start_date__gte'] = filters.pop('start_date')
1591 1593 if 'end_date' in filters:
1592 1594 filters['start_date__lte'] = filters.pop('end_date')
1593 1595 if 'tags' in filters:
1594 1596 tags = filters.pop('tags')
1595 1597 if 'tags' in fields:
1596 1598 query = query | Q(tags__icontains=tags)
1597 1599 if 'name' in fields:
1598 1600 query = query | Q(name__icontains=tags)
1599 1601 if 'location' in fields:
1600 1602 query = query | Q(location__name__icontains=tags)
1601 1603 if 'device' in fields:
1602 1604 query = query | Q(device__device_type__name__icontains=tags)
1603 1605
1604 1606 object_list = model.objects.filter(query, **filters).order_by(*order)
1605 1607 paginator = Paginator(object_list, n)
1606 1608
1607 1609 try:
1608 1610 objects = paginator.page(page)
1609 1611 except PageNotAnInteger:
1610 1612 objects = paginator.page(1)
1611 1613 except EmptyPage:
1612 1614 objects = paginator.page(paginator.num_pages)
1613 1615
1614 1616 kwargs['objects'] = objects
1615 1617 kwargs['offset'] = (int(page)-1)*n if page else 0
1616 1618
1617 1619 return kwargs
1618 1620
1619 1621 def operation(request, id_camp=None):
1620 1622
1621 1623 kwargs = {}
1622 1624 kwargs['title'] = 'Radars Operation'
1623 1625 kwargs['no_sidebar'] = True
1624 1626 campaigns = Campaign.objects.filter(start_date__lte=datetime.now(),
1625 1627 end_date__gte=datetime.now()).order_by('-start_date')
1626 1628
1627 1629
1628 1630 if id_camp:
1629 1631 campaign = get_object_or_404(Campaign, pk = id_camp)
1630 1632 form = OperationForm(initial={'campaign': campaign.id}, campaigns=campaigns)
1631 1633 kwargs['campaign'] = campaign
1632 1634 else:
1633 1635 # form = OperationForm(campaigns=campaigns)
1634 1636 kwargs['campaigns'] = campaigns
1635 1637 return render(request, 'operation.html', kwargs)
1636 1638
1637 1639 #---Experiment
1638 1640 keys = ['id', 'name', 'start_time', 'end_time', 'status']
1639 1641 kwargs['experiment_keys'] = keys[1:]
1640 1642 kwargs['experiments'] = experiments
1641 1643 #---Radar
1642 1644 kwargs['locations'] = campaign.get_experiments_by_radar()
1643 1645 kwargs['form'] = form
1644 1646
1645 1647 return render(request, 'operation.html', kwargs)
1646 1648
1647 1649
1648 1650 @login_required
1649 1651 def radar_start(request, id_camp, id_radar):
1650 1652
1651 1653 campaign = get_object_or_404(Campaign, pk = id_camp)
1652 1654 experiments = campaign.get_experiments_by_radar(id_radar)[0]['experiments']
1653 1655 now = datetime.now()
1654 1656 for exp in experiments:
1655 1657 start = datetime.combine(datetime.now().date(), exp.start_time)
1656 end = datetime.combine(datetime.now().date(), exp.start_time)
1658 end = datetime.combine(datetime.now().date(), exp.end_time)
1657 1659 if end < start:
1658 1660 end += timedelta(1)
1659 1661
1660 1662 if exp.status == 2:
1661 1663 messages.warning(request, 'Experiment {} already running'.format(exp))
1662 1664 continue
1663 1665
1664 1666 if exp.status == 3:
1665 1667 messages.warning(request, 'Experiment {} already programmed'.format(exp))
1666 1668 continue
1667 1669
1668 1670 if start > campaign.end_date or start < campaign.start_date:
1669 1671 messages.warning(request, 'Experiment {} out of date'.format(exp))
1670 1672 continue
1671 1673
1672 1674 if now > start and now <= end:
1673 task = task_start.delay(exp.pk)
1675 exp.status = 3
1676 exp.save()
1677 task = task_start.delay(exp.id)
1674 1678 exp.status = task.wait()
1675 1679 if exp.status==0:
1676 1680 messages.error(request, 'Experiment {} not start'.format(exp))
1677 1681 if exp.status==2:
1678 task = task_stop.apply_async((exp.pk,), eta=end+timedelta(hours=5))
1679 1682 messages.success(request, 'Experiment {} started'.format(exp))
1680 1683 else:
1681 task = task_start.apply_async((exp.pk,), eta=start+timedelta(hours=5))
1682 task = task_stop.apply_async((exp.pk,), eta=end+timedelta(hours=5))
1684 task = task_start.apply_async((exp.pk, ), eta=start+timedelta(hours=5))
1685 exp.task = task.id
1683 1686 exp.status = 3
1684 1687 messages.success(request, 'Experiment {} programmed to start at {}'.format(exp, start))
1685 1688
1686 1689 exp.save()
1687 1690
1688 1691 return HttpResponseRedirect(reverse('url_operation', args=[id_camp]))
1689 1692
1690 1693
1691 1694 @login_required
1692 1695 def radar_stop(request, id_camp, id_radar):
1693 1696
1694 1697 campaign = get_object_or_404(Campaign, pk = id_camp)
1695 1698 experiments = campaign.get_experiments_by_radar(id_radar)[0]['experiments']
1696 1699
1697 1700 for exp in experiments:
1698 1701
1702 if exp.task:
1703 app.control.revoke(exp.task)
1699 1704 if exp.status == 2:
1700 task = task_stop.delay(exp.pk)
1701 exp.status = task.wait()
1705 exp.stop()
1702 1706 messages.warning(request, 'Experiment {} stopped'.format(exp))
1703 exp.save()
1704 else:
1705 messages.error(request, 'Experiment {} not running'.format(exp))
1706 kill_tasks()
1707 exp.status = 1
1708 exp.save()
1707 1709
1708 1710 return HttpResponseRedirect(reverse('url_operation', args=[id_camp]))
1709 1711
1710 1712
1711 1713 @login_required
1712 1714 def radar_refresh(request, id_camp, id_radar):
1713 1715
1714 1716 campaign = get_object_or_404(Campaign, pk = id_camp)
1715 1717 experiments = campaign.get_experiments_by_radar(id_radar)[0]['experiments']
1716 1718
1717 1719 for exp in experiments:
1718 1720 exp.get_status()
1719 1721
1720 1722 return HttpResponseRedirect(reverse('url_operation', args=[id_camp]))
1721 1723
1722 1724
1723 1725 def real_time(request):
1724 1726
1725 1727 graphic_path = "/home/fiorella/Pictures/catwbeanie.jpg"
1726 1728
1727 1729 kwargs = {}
1728 1730 kwargs['title'] = 'CLAIRE'
1729 1731 kwargs['suptitle'] = 'Real Time'
1730 1732 kwargs['no_sidebar'] = True
1731 1733 kwargs['graphic_path'] = graphic_path
1732 1734 kwargs['graphic1_path'] = 'http://www.bluemaize.net/im/girls-accessories/shark-beanie-11.jpg'
1733 1735
1734 return render(request, 'real_time.html', kwargs) No newline at end of file
1736 return render(request, 'real_time.html', kwargs)
@@ -1,18 +1,19
1 1 from __future__ import absolute_import
2 2 import os
3 3 from celery import Celery
4 4 from django.conf import settings
5 5
6 6 # set the default Django settings module for the 'celery' program.
7 7 os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'radarsys.settings')
8 8 app = Celery('radarsys')
9 9
10 10 # Using a string here means the worker will not have to
11 11 # pickle the object when using Windows.
12 12 app.config_from_object('django.conf:settings')
13 app.conf.broker_transport_options = {'visibility_timeout': 86400}
13 14 app.autodiscover_tasks(lambda: settings.INSTALLED_APPS)
14 15
15 16
16 17 @app.task(bind=True)
17 18 def debug_task(self):
18 19 print('Request: {0!r}'.format(self.request))
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
General Comments 0
You need to be logged in to leave comments. Login now