##// END OF EJS Templates
Added monitor channel to the RC configuration.
krodriguez -
r414:08d5cd67904a
parent child
Show More
@@ -1,1079 +1,1095
1 1
2 2
3 3 import ast
4 4 import json
5 5 import requests
6 6 import numpy as np
7 7 from base64 import b64encode
8 8 from struct import pack
9 9
10 10 from django.db import models
11 11 from django.urls import reverse
12 12 from django.core.validators import MinValueValidator, MaxValueValidator
13 13
14 14 from apps.main.models import Configuration
15 15 from apps.main.utils import Params
16 16 from devices.rc import api
17 17 from apps.rc.utils import RCFile
18 18
19 19
20 20 LINE_TYPES = (
21 21 ('none', 'Not used'),
22 22 ('tr', 'Transmission/reception selector signal'),
23 23 ('tx', 'A modulating signal (Transmission pulse)'),
24 24 ('codes', 'BPSK modulating signal'),
25 25 ('windows', 'Sample window signal'),
26 26 ('sync', 'Synchronizing signal'),
27 27 ('flip', 'IPP related periodic signal'),
28 28 ('prog_pulses', 'Programmable pulse'),
29 29 ('mix', 'Mixed line'),
30 30 )
31 31
32 32
33 33 SAMPLING_REFS = (
34 34 ('none', 'No Reference'),
35 35 ('begin_baud', 'Begin of the first baud'),
36 36 ('first_baud', 'Middle of the first baud'),
37 37 ('sub_baud', 'Middle of the sub-baud')
38 38 )
39 39
40 40 DAT_CMDS = {
41 41 # Pulse Design commands
42 42 'DISABLE' : 0, # Disables pulse generation
43 43 'ENABLE' : 24, # Enables pulse generation
44 44 'DELAY_START' : 40, # Write delay status to memory
45 45 'FLIP_START' : 48, # Write flip status to memory
46 46 'SAMPLING_PERIOD' : 64, # Establish Sampling Period
47 47 'TX_ONE' : 72, # Output '0' in line TX
48 48 'TX_ZERO' : 88, # Output '0' in line TX
49 49 'SW_ONE' : 104, # Output '0' in line SW
50 50 'SW_ZERO' : 112, # Output '1' in line SW
51 51 'RESTART': 120, # Restarts CR8 Firmware
52 52 'CONTINUE' : 253, # Function Unknown
53 53 # Commands available to new controllers
54 54 # In Pulse Design Executable, the clock divisor code is written as 12 at the start, but it should be written as code 22(below) just before the final enable.
55 55 'CLOCK_DIVISOR_INIT' : 12, # Specifies Clock Divisor. Legacy command, ignored in the actual .dat conversion
56 56 'CLOCK_DIVISOR_LAST' : 22, # Specifies Clock Divisor (default 60 if not included) syntax: 255,22 254,N-1.
57 57 'CLOCK_DIVIDER' : 8,
58 58 }
59 59
60 60 MAX_BITS = 8
61 61
62 62 # Rotate left: 0b1001 --> 0b0011
63 63 rol = lambda val, r_bits: \
64 64 (val << r_bits%MAX_BITS) & (2**MAX_BITS-1) | \
65 65 ((val & (2**MAX_BITS-1)) >> (MAX_BITS-(r_bits%MAX_BITS)))
66 66
67 67 # Rotate right: 0b1001 --> 0b1100
68 68 ror = lambda val, r_bits: \
69 69 ((val & (2**MAX_BITS-1)) >> r_bits%MAX_BITS) | \
70 70 (val << (MAX_BITS-(r_bits%MAX_BITS)) & (2**MAX_BITS-1))
71 71
72 72
73 73 class RCConfiguration(Configuration):
74 74
75 75 ipp = models.FloatField(verbose_name='IPP [Km]', validators=[MinValueValidator(1)], default=300)
76 76 ntx = models.PositiveIntegerField(verbose_name='Number of TX', validators=[MinValueValidator(1)], default=1)
77 77 clock_in = models.FloatField(verbose_name='Clock in [MHz]', validators=[MinValueValidator(1), MaxValueValidator(80)], default=1)
78 78 clock_divider = models.PositiveIntegerField(verbose_name='Clock divider', validators=[MinValueValidator(1), MaxValueValidator(256)], default=1)
79 79 clock = models.FloatField(verbose_name='Clock Master [MHz]', blank=True, default=1)
80 80 time_before = models.PositiveIntegerField(verbose_name='Time before [&mu;S]', default=12)
81 81 time_after = models.PositiveIntegerField(verbose_name='Time after [&mu;S]', default=1)
82 82 sync = models.PositiveIntegerField(verbose_name='Synchro delay', default=0)
83 ch_monitor = models.PositiveIntegerField(verbose_name='Channel Monitor', validators=[MinValueValidator(0), MaxValueValidator(15)], default=6)
83 84 sampling_reference = models.CharField(verbose_name='Sampling Reference', choices=SAMPLING_REFS, default='none', max_length=40)
84 85 control_tx = models.BooleanField(verbose_name='Control Switch TX', default=False)
85 86 control_sw = models.BooleanField(verbose_name='Control Switch SW', default=False)
86 87 total_units = models.PositiveIntegerField(default=0)
87 88 mix = models.BooleanField(default=False)
88 89
89 90 class Meta:
90 91 db_table = 'rc_configurations'
91 92
92 93 def get_absolute_url_plot(self):
93 94 return reverse('url_plot_rc_pulses', args=[str(self.id)])
94 95
95 96 @property
96 97 def ipp_unit(self):
97 98
98 99 return '{} ({})'.format(self.ipp, int(self.ipp*self.km2unit))
99 100
100 101 @property
101 102 def us2unit(self):
102 103
103 104 return self.clock_in/self.clock_divider
104 105
105 106 @property
106 107 def km2unit(self):
107 108
108 109 return 20./3*(self.clock_in/self.clock_divider)
109 110
110 111 def clone(self, **kwargs):
111 112
112 113 lines = self.get_lines()
113 114 self.pk = None
114 115 self.id = None
115 116 for attr, value in kwargs.items():
116 117 setattr(self, attr, value)
117 118 self.save()
118 119
119 120 for line in lines:
120 121 line.clone(rc_configuration=self)
121 122
122 123 new_lines = self.get_lines()
123 124 for line in new_lines:
124 125 line_params = json.loads(line.params)
125 126 if 'TX_ref' in line_params and (line_params['TX_ref'] != '0'):
126 127 ref_line = RCLine.objects.get(pk=line_params['TX_ref'])
127 128 line_params['TX_ref'] = ['{}'.format(l.pk) for l in new_lines if l.get_name()==ref_line.get_name()][0]
128 129 line.params = json.dumps(line_params)
129 130 line.save()
130 131
131 132 return self
132 133
133 134 def get_lines(self, **kwargs):
134 135 '''
135 136 Retrieve configuration lines
136 137 '''
137 138
138 139 return RCLine.objects.filter(rc_configuration=self.pk, **kwargs)
139 140
140 141
141 142 def clean_lines(self):
142 143 '''
143 144 '''
144 145
145 146 empty_line = RCLineType.objects.get(name='none')
146 147
147 148 for line in self.get_lines():
148 149 line.line_type = empty_line
149 150 line.params = '{}'
150 151 line.save()
151 152
152 153 def dict_to_parms(self, params, id=None):
153 154 '''
154 155 '''
155 156
156 157 if id:
157 158 data = Params(params).get_conf(id_conf=id)
158 159 else:
159 160 data = Params(params).get_conf(dtype='rc')
160 161
161 162 #print(data)
162 163 # self.name = data['name']
163 164 self.ipp = data['ipp']
164 165 self.ntx = data['ntx']
165 166 self.clock_in = data['clock_in']
166 167 self.clock_divider = data['clock_divider']
167 168 self.clock = data['clock']
168 169 self.time_before = data['time_before']
169 170 self.time_after = data['time_after']
170 171 self.sync = data['sync']
171 172 self.sampling_reference = data['sampling_reference']
172 173 self.total_units = self.ipp*self.ntx*self.km2unit
173 174 self.save()
174 175 self.clean_lines()
175 176
176 177 #print(params)
177 178
178 179 positions = {'tx':0, 'tr':0}
179 180 for i, id in enumerate(data['lines']):
180 181 line_data = params['lines']['byId'][id]
181 182 line_type = RCLineType.objects.get(name=line_data['line_type'])
182 183 if line_type.name == 'codes':
183 184 code = RCLineCode.objects.get(name=line_data['params']['code'])
184 185 line_data['params']['code'] = code.pk
185 186 if line_type.name == 'tx':
186 187 position = positions['tx']
187 188 positions['tx'] += 1
188 189 elif line_type.name == 'tr':
189 190 position = positions['tr']
190 191 positions['tr'] += 1
191 192 else:
192 193 position = 0
193 194 line, dum = RCLine.objects.update_or_create(
194 195 rc_configuration=self,
195 196 channel=i,
196 197 position=position,
197 198 defaults={
198 199 'line_type': line_type,
199 200 'params': json.dumps(line_data['params'])
200 201 }
201 202 )
202 203
203 204 for i, line in enumerate(self.get_lines()):
204 205 line_params = json.loads(line.params)
205 206 if 'TX_ref' in line_params:
206 207 if line_params['TX_ref'] in (0, '0'):
207 208 line_params['TX_ref'] = '0'
208 209 else:
209 210 ref_id = '{}'.format(line_params['TX_ref'])
210 211 ref_line = params['lines']['byId'][ref_id]
211 212 line_params['TX_ref'] = RCLine.objects.get(
212 213 rc_configuration=self,
213 214 params=json.dumps(ref_line['params'])
214 215 ).pk
215 216 line.params = json.dumps(line_params)
216 217 print(line.params)
217 218 line.save()
218 219 print("Fin de dict to param")
219 220
220 221 def get_delays(self):
221 222
222 223 pulses = [line.pulses_as_points() for line in self.get_lines()]
223 224 points = [tup for tups in pulses for tup in tups]
224 225 points = set([x for tup in points for x in tup])
225 226 points = list(points)
226 227 points.sort()
227 228
228 229 if points[0]!=0:
229 230 points.insert(0, 0)
230 231
231 232 return [points[i+1]-points[i] for i in range(len(points)-1)]
232 233
233 234 def get_pulses(self, binary=True):
234 235
235 236 pulses = [line.pulses_as_points() for line in self.get_lines()]
236 237 tuples = [tup for tups in pulses for tup in tups]
237 238 points = set([x for tup in tuples for x in tup])
238 239 points = list(points)
239 240 points.sort()
240 241 states = []
241 242 last = [0 for x in pulses]
242 243 n_pulses = len(pulses)
243 244 print('len_pulses', n_pulses)
244 245 print('len_points', len(points))
245 246 ups_arr = [[] for _ in range(n_pulses)]
246 247 dws_arr = [[] for _ in range(n_pulses)]
247 248
248 249 for i, tups in enumerate(pulses):
249 250 ups_arr[i] = [tup[0] for tup in tups if tup!=(0,0)]
250 251 dws_arr[i] = [tup[1] for tup in tups if tup!=(0,0)]
251 252 print('len_points*n_pulses',len(points)*n_pulses)
252 253 #print('ups_arr', ups_arr)
253 254 #print('dws_arr', dws_arr)
254 255
255 256 for x in points:
256 257 dum = []
257 258 print('loading', x*100/max(points))
258 259
259 260 for i in range(n_pulses):
260 261 if x in ups_arr[i]:
261 262 dum.append(1)
262 263 elif x in dws_arr[i]:
263 264 dum.append(0)
264 265 else:
265 266 dum.append(last[i])
266 267 #print(dum)
267 268 states.append(dum)
268 269 last = dum
269 270
270 271 if binary:
271 272 ret = []
272 273 for flips in states:
273 274 flips.reverse()
274 275 ret.append(int(''.join([str(x) for x in flips]), 2))
275 276 states = ret
276 277 #print(states[:-1])
277 278 #print('len_states',len(states[:-1]))
278 279
279 280 return states[:-1]
280 281
281 282 def add_cmd(self, cmd):
282 283
283 284 if cmd in DAT_CMDS:
284 285 return (255, DAT_CMDS[cmd])
285 286
286 287 def add_data(self, value):
287 288
288 289 return (254, value-1)
289 290
290 291 def parms_to_binary(self, dat=True):
291 292 '''
292 293 Create "dat" stream to be send to CR
293 294 '''
294 295
295 296 data = bytearray()
296 297 # create header
297 298 data.extend(self.add_cmd('DISABLE'))
298 299 data.extend(self.add_cmd('CONTINUE'))
299 300 data.extend(self.add_cmd('RESTART'))
300 301
301 302 if self.control_sw:
302 303 data.extend(self.add_cmd('SW_ONE'))
303 304 else:
304 305 data.extend(self.add_cmd('SW_ZERO'))
305 306
306 307 if self.control_tx:
307 308 data.extend(self.add_cmd('TX_ONE'))
308 309 else:
309 310 data.extend(self.add_cmd('TX_ZERO'))
310 311
311 312 # write divider
312 313 data.extend(self.add_cmd('CLOCK_DIVIDER'))
313 314 data.extend(self.add_data(self.clock_divider))
314 315
315 316 # write delays
316 317 data.extend(self.add_cmd('DELAY_START'))
317 318 # first delay is always zero
318 319 data.extend(self.add_data(1))
319 320
320 321 delays = self.get_delays()
321 322
322 323 for delay in delays:
323 324 while delay>252:
324 325 data.extend(self.add_data(253))
325 326 delay -= 253
326 327 data.extend(self.add_data(int(delay)))
327 328
328 329 # write flips
329 330 data.extend(self.add_cmd('FLIP_START'))
330 331
331 332 states = self.get_pulses(binary=True)
332 333
333 334
334 335 last = 0
335 336 for flip, delay in zip(states, delays):
336 337 data.extend(self.add_data((flip^last)+1))
337 338 last = flip
338 339 while delay>252:
339 340 data.extend(self.add_data(1))
340 341 delay -= 253
341 342
342 343 # write sampling period
343 344 data.extend(self.add_cmd('SAMPLING_PERIOD'))
344 345 wins = self.get_lines(line_type__name='windows')
345 346 if wins:
346 347 win_params = json.loads(wins[0].params)['params']
347 348 if win_params:
348 349 dh = int(win_params[0]['resolution']*self.km2unit)
349 350 else:
350 351 dh = 1
351 352 else:
352 353 dh = 1
353 354 data.extend(self.add_data(dh))
354 355
355 356 # write enable
356 357 data.extend(self.add_cmd('ENABLE'))
357 358
358 359 if not dat:
359 360 return data
360 361
361 362 return '\n'.join(['{}'.format(x) for x in data])
362 363
363 364 def update_pulses(self):
364 365 contador = 0
365 366 for line in self.get_lines():
366 367 contador=contador+1
367 368 print(contador)
368 369 line.update_pulses()
369 370
370 371 def plot_pulses2(self, km=False):
371 372
372 373 import matplotlib
373 374 matplotlib.use('Agg')
374 375 import matplotlib.pyplot as plt
375 376 from bokeh.resources import CDN
376 377 from bokeh.embed import components
377 378 from bokeh.mpl import to_bokeh
378 379 from bokeh.models.tools import WheelZoomTool, ResetTool, PanTool, HoverTool, SaveTool
379 380
380 381 lines = self.get_lines()
381 382
382 383 N = len(lines)
383 384 npoints = self.total_units/self.km2unit if km else self.total_units
384 385 fig = plt.figure(figsize=(12, 2+N*0.5))
385 386 ax = fig.add_subplot(111)
386 387 labels = ['IPP']
387 388
388 389 for i, line in enumerate(lines):
389 390 labels.append(line.get_name(channel=True))
390 391 l = ax.plot((0, npoints),(N-i-1, N-i-1))
391 392 points = [(tup[0], tup[1]-tup[0]) for tup in line.pulses_as_points(km=km) if tup!=(0,0)]
392 393 ax.broken_barh(points, (N-i-1, 0.5),
393 394 edgecolor=l[0].get_color(), facecolor='none')
394 395
395 396 n = 0
396 397 f = ((self.ntx+50)/100)*5 if ((self.ntx+50)/100)*10>0 else 2
397 398 for x in np.arange(0, npoints, self.ipp if km else self.ipp*self.km2unit):
398 399 if n%f==0:
399 400 ax.text(x, N, '%s' % n, size=10)
400 401 n += 1
401 402
402 403 labels.reverse()
403 404 ax.set_yticks(range(len(labels)))
404 405 ax.set_yticklabels(labels)
405 406 ax.set_xlabel = 'Units'
406 407 plot = to_bokeh(fig, use_pandas=False)
407 408 plot.tools = [PanTool(dimensions="width"), WheelZoomTool(dimensions="width"), ResetTool(), SaveTool()]
408 409 plot.toolbar_location="above"
409 410
410 411 return components(plot, CDN)
411 412
412 413 def plot_pulses(self, km=False):
413 414
414 415 from bokeh.plotting import figure
415 416 from bokeh.resources import CDN
416 417 from bokeh.embed import components
417 418 from bokeh.models import FixedTicker, PrintfTickFormatter, Label
418 419 from bokeh.models.tools import WheelZoomTool, ResetTool, PanTool, HoverTool, SaveTool
419 420 from bokeh.models.sources import ColumnDataSource
420 421
421 422 lines = self.get_lines().reverse()
422 423
423 424 N = len(lines)
424 425 npoints = self.total_units/self.km2unit if km else self.total_units
425 426 ipp = self.ipp if km else self.ipp*self.km2unit
426 427
427 428 hover = HoverTool(tooltips=[("Line", "@name"),
428 429 ("IPP", "@ipp"),
429 430 ("X", "@left")])
430 431
431 432 tools = [PanTool(dimensions="width"),
432 433 WheelZoomTool(dimensions="width"),
433 434 hover, SaveTool()]
434 435
435 436 plot = figure(width=1000,
436 437 height=40+N*50,
437 438 y_range = (0, N),
438 439 tools=tools,
439 440 toolbar_location='above',
440 441 toolbar_sticky=False,)
441 442
442 443 pulses = [line.pulses_as_points() for line in self.get_lines()]
443 444 tuples = [tup for tups in pulses for tup in tups]
444 445 points = set([x for tup in tuples for x in tup])
445 446 capacity_bytes = round((8*(len(points)-1)+12)/2) # se divide entre 2 porque la mitad era solo para direcciones
446 447 capacity_percent = (capacity_bytes/2097152)*100
447 448 # Add the used memory message
448 449 x_label_memory = Label(x=900, y=-1.5, text='Used memory of '+str(capacity_bytes)+'/2097152 bytes ('+'%.3f'%capacity_percent+'%)', text_align="right", x_units='screen', text_font_size='14pt')
449 450 plot.add_layout(x_label_memory, 'below')
450 451
451 452 plot.xaxis.axis_label = 'Km' if km else 'Units'
452 453 plot.xaxis[0].formatter = PrintfTickFormatter(format='%d')
453 454 plot.yaxis.axis_label = 'Pulses'
454 455 plot.yaxis[0].ticker=FixedTicker(ticks=list(range(N)))
455 456 plot.yaxis[0].formatter = PrintfTickFormatter(format='Line %d')
456 457
457 458 for i, line in enumerate(lines):
458 459
459 460 points = [tup for tup in line.pulses_as_points(km=km) if tup!=(0,0)]
460 461
461 462 source = ColumnDataSource(data = dict(
462 463 bottom = [i for tup in points],
463 464 top = [i+0.5 for tup in points],
464 465 left = [tup[0] for tup in points],
465 466 right = [tup[1] for tup in points],
466 467 ipp = [int(tup[0]/ipp) for tup in points],
467 468 name = [line.get_name() for tup in points]
468 469 ))
469 470
470 471 plot.quad(
471 472 bottom = 'bottom',
472 473 top = 'top',
473 474 left = 'left',
474 475 right = 'right',
475 476 source = source,
476 477 fill_alpha = 0,
477 478 #line_color = 'blue',
478 479 )
479 480
480 481 plot.line([0, npoints], [i, i])#, color='blue')
481 482
482 483 return components(plot, CDN)
483 484
484 485 def request(self, cmd, method='get', **kwargs):
485 486
486 487 req = getattr(requests, method)(self.device.url(cmd), **kwargs)
487 488 payload = req.json()
488 489
489 490 return payload
490 491
491 492 def status_device(self):
492 493
493 494 try:
494 495 self.device.status = 0
495 496 payload = self.request('status')
496 497 if payload['status']=='enable':
497 498 self.device.status = 3
498 499 elif payload['status']=='disable':
499 500 self.device.status = 2
500 501 else:
501 502 self.device.status = 1
502 503 self.device.save()
503 504 self.message = 'RC status: {}'.format(payload['status'])
504 505 return False
505 506 except Exception as e:
506 507 if 'No route to host' not in str(e):
507 508 self.device.status = 4
508 509 self.device.save()
509 510 self.message = 'RC status: {}'.format(str(e))
510 511 return False
511 512
512 513 self.device.save()
513 514 return True
514 515
515 516 def reset_device(self):
516 517
517 518 try:
518 519 payload = self.request('reset', 'post')
519 520 if payload['reset']=='ok':
520 521 self.message = 'RC restarted OK'
521 522 self.device.status = 2
522 523 self.device.save()
523 524 else:
524 525 self.message = 'RC restart fail'
525 526 self.device.status = 4
526 527 self.device.save()
527 528 except Exception as e:
528 529 self.message = 'RC reset: {}'.format(str(e))
529 530 return False
530 531
531 532 return True
532 533
533 534 def stop_device(self):
534 535
535 536 try:
536 537 payload = self.request('stop', 'post')
537 538 self.message = 'RC stop: {}'.format(payload['stop'])
538 539 if payload['stop']=='ok':
539 540 self.device.status = 2
540 541 self.device.save()
541 542 else:
542 543 self.device.status = 4
543 544 self.device.save()
544 545 return False
545 546 except Exception as e:
546 547 if 'No route to host' not in str(e):
547 548 self.device.status = 4
548 549 else:
549 550 self.device.status = 0
550 551 self.message = 'RC stop: {}'.format(str(e))
551 552 self.device.save()
552 553 return False
553 554
554 555 return True
555 556
556 557 def start_device(self):
557 558
558 559 try:
559 560 payload = self.request('start', 'post')
560 561 self.message = 'RC start: {}'.format(payload['start'])
561 562 if payload['start']=='ok':
562 563 self.device.status = 3
563 564 self.device.save()
564 565 else:
565 566 return False
566 567 except Exception as e:
567 568 if 'No route to host' not in str(e):
568 569 self.device.status = 4
569 570 else:
570 571 self.device.status = 0
571 572 self.message = 'RC start: {}'.format(str(e))
572 573 self.device.save()
573 574 return False
574 575
575 576 return True
576 577
577 578 def write_device(self, raw=False):
578 579 print("write device")
579 580
580 581 if not raw:
582
583
584
581 585 clock = RCClock.objects.get(rc_configuration=self)
582 586 if clock.mode:
583 587 data = {'default': clock.frequency}
584 588 else:
585 589 data = {'manual': [clock.multiplier, clock.divisor, clock.reference]}
586 590 payload = self.request('setfreq', 'post', data=json.dumps(data))
587 591 #if payload['setfreq'] != 'ok':
588 592 if payload['command'] != 'ok':
589 593 #self.message = 'RC write: {}'.format(payload['setfreq'])
590 594 self.message = 'RC write: {}'.format(payload['command'])
591 595 else:
592 596 #self.message = payload['setfreq']
593 597 self.message = payload['programming']
594 598 #if payload['setfreq'] == 'fail':
595 599 if payload['programming'] == 'fail':
596 600 self.message = 'RC write: error programming CGS chip'
601
602 ##############################################################
603 data = {'setwindow': self.ch_monitor}
604 print(data)
605 payload = self.request('setwin', 'post', data=json.dumps(data))
606
607 if payload['setwindow'] == 'ok':
608 self.message = 'RC write: {}'.format(payload['setwindow'])
609 else:
610 if payload['command'] != 'wrong format or key':
611 self.message = 'Error RC monitor channel: {}'.format(payload['command'])
612 ##############################################################
597 613
598 614 values = []
599 615 print('wait delay values...')
600 616 for pulse, delay in zip(self.get_pulses(), self.get_delays()):
601 617 #print('wait zip...')
602 618 while delay > 65536:
603 619 values.append((pulse, 65535))
604 620 delay -= 65536
605 621 values.append((pulse, delay-1))
606 622 data = bytearray()
607 623 #reset
608 624 data.extend((128, 0))
609 625 #disable
610 626 data.extend((129, 0))
611 627 #SW switch
612 628 if self.control_sw:
613 629 data.extend((130, 2))
614 630 else:
615 631 data.extend((130, 0))
616 632 #divider
617 633 data.extend((131, self.clock_divider-1))
618 634 #enable writing
619 635 data.extend((139, 62))
620 636
621 637 last = 0
622 638 print('wait data...')
623 639 for tup in values:
624 640 vals = pack('<HH', last^tup[0], tup[1])
625 641 last = tup[0]
626 642 data.extend((133, vals[1], 132, vals[0], 133, vals[3], 132, vals[2]))
627 643
628 644 #enable
629 645 data.extend((129, 1))
630 646 print('len',len(data))
631 647
632 648 if raw:
633 649 return b64encode(data)
634 650
635 651 #try:
636 652 print('requests')
637 653 payload = self.request('stop', 'post')
638 654 payload = self.request('reset', 'post')
639 655 #payload = self.request('divider', 'post', data={'divider': self.clock_divider-1})
640 656 #payload = self.request('write', 'post', data=b64encode(bytearray((139, 62))), timeout=20)
641 657 n = len(data)
642 658 print('len: ',n)
643 659 x = 0
644 660 cnt = 0
645 661 while x < n:
646 662 print('writing...', cnt)
647 663 payload = self.request('write', 'post', data=b64encode(data[x:x+3072]))#(data))#
648 664 x += 3072
649 665 cnt += 1#time.sleep(1)
650 666 print('writing...', x*100/n)
651 667
652 668 if payload['write']=='ok':
653 669 self.device.status = 3
654 670 self.device.save()
655 671 self.message = 'RC configured and started'
656 672 else:
657 673 self.device.status = 1
658 674 self.device.save()
659 675 self.message = 'RC write: {}'.format(payload['write'])
660 676 return False
661 677
662 678 #payload = self.request('start', 'post')
663 679
664 680 #except Exception as e:
665 681 # if 'No route to host' not in str(e):
666 682 # self.device.status = 4
667 683 # else:
668 684 # self.device.status = 0
669 685 # self.message = 'RC write: {}'.format(str(e))
670 686 # self.device.save()
671 687 # return False
672 688
673 689 return True
674 690
675 691
676 692 def get_absolute_url_import(self):
677 693 return reverse('url_import_rc_conf', args=[str(self.id)])
678 694
679 695
680 696 class RCLineCode(models.Model):
681 697
682 698 name = models.CharField(max_length=40)
683 699 bits_per_code = models.PositiveIntegerField(default=0)
684 700 number_of_codes = models.PositiveIntegerField(default=0)
685 701 codes = models.TextField(blank=True, null=True)
686 702
687 703 class Meta:
688 704 db_table = 'rc_line_codes'
689 705 ordering = ('name',)
690 706
691 707 def __str__(self):
692 708 return u'%s' % self.name
693 709
694 710
695 711 class RCLineType(models.Model):
696 712
697 713 name = models.CharField(choices=LINE_TYPES, max_length=40)
698 714 description = models.TextField(blank=True, null=True)
699 715 params = models.TextField(default='[]')
700 716
701 717 class Meta:
702 718 db_table = 'rc_line_types'
703 719
704 720 def __str__(self):
705 721 return u'%s - %s' % (self.name.upper(), self.get_name_display())
706 722
707 723
708 724 class RCLine(models.Model):
709 725
710 726 rc_configuration = models.ForeignKey('RCConfiguration', on_delete=models.CASCADE)
711 727 line_type = models.ForeignKey('RCLineType',on_delete=models.CASCADE)
712 728 channel = models.PositiveIntegerField(default=0)
713 729 position = models.PositiveIntegerField(default=0)
714 730 params = models.TextField(default='{}')
715 731 pulses = models.TextField(default='')
716 732
717 733 class Meta:
718 734 db_table = 'rc_lines'
719 735 ordering = ['channel']
720 736
721 737 def __str__(self):
722 738 if self.rc_configuration:
723 739 return u'{}|{} - {}'.format(self.pk, self.get_name(), self.rc_configuration.name)
724 740
725 741 def jsonify(self):
726 742
727 743 data = {}
728 744 data['params'] = json.loads(self.params)
729 745 data['id'] = '{}'.format(self.pk)
730 746 data['line_type'] = self.line_type.name
731 747 data['name'] = self.get_name()
732 748 if data['line_type']=='codes':
733 749 data['params']['code'] = RCLineCode.objects.get(pk=data['params']['code']).name
734 750
735 751 return data
736 752
737 753
738 754 def clone(self, **kwargs):
739 755
740 756 self.pk = None
741 757 self.id = None
742 758
743 759 for attr, value in kwargs.items():
744 760 setattr(self, attr, value)
745 761
746 762 self.save()
747 763
748 764 return self
749 765
750 766 def get_name(self, channel=False):
751 767
752 768 chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
753 769 s = ''
754 770
755 771 if self.line_type.name in ('tx',):
756 772 s = chars[self.position]
757 773 elif self.line_type.name in ('codes', 'windows', 'tr'):
758 774 if 'TX_ref' in json.loads(self.params):
759 775 pk = json.loads(self.params)['TX_ref']
760 776 if pk in (0, '0'):
761 777 s = ','.join(chars[l.position] for l in self.rc_configuration.get_lines(line_type__name='tx'))
762 778 else:
763 779 ref = RCLine.objects.get(pk=pk)
764 780 s = chars[ref.position]
765 781 s = '({})'.format(s)
766 782
767 783 s = '{}{}'.format(self.line_type.name.upper(), s)
768 784
769 785 if channel:
770 786 return '{} {}'.format(s, self.channel)
771 787 else:
772 788 return s
773 789
774 790 def get_lines(self, **kwargs):
775 791
776 792 return RCLine.objects.filter(rc_configuration=self.rc_configuration, **kwargs)
777 793
778 794 def pulses_as_array(self):
779 795
780 796 y = np.zeros(self.rc_configuration.total_units)
781 797
782 798 for tup in ast.literal_eval(self.pulses):
783 799 y[tup[0]:tup[1]] = 1
784 800
785 801 return y.astype(np.int8)
786 802
787 803 def pulses_as_points(self, km=False):
788 804
789 805 if km:
790 806 unit2km = 1/self.rc_configuration.km2unit
791 807 return [(tup[0]*unit2km, tup[1]*unit2km) for tup in ast.literal_eval(self.pulses)]
792 808 else:
793 809 return ast.literal_eval(self.pulses)
794 810
795 811 def get_win_ref(self, params, tx_id, km2unit):
796 812
797 813 ref = self.rc_configuration.sampling_reference
798 814 codes = [line for line in self.get_lines(line_type__name='codes') if int(json.loads(line.params)['TX_ref'])==int(tx_id)]
799 815
800 816 if codes:
801 817 tx_width = float(json.loads(RCLine.objects.get(pk=tx_id).params)['pulse_width'])*km2unit/len(json.loads(codes[0].params)['codes'][0])
802 818 else:
803 819 tx_width = float(json.loads(RCLine.objects.get(pk=tx_id).params)['pulse_width'])*km2unit
804 820
805 821 if ref=='first_baud':
806 822 return int(1 + round((tx_width + 1)/2 + params['first_height']*km2unit - params['resolution']*km2unit))
807 823 elif ref=='sub_baud':
808 824 return np.ceil(1 + params['first_height']*km2unit - params['resolution']*km2unit/2)
809 825 else:
810 826 return 0
811 827
812 828 def update_pulses(self):
813 829 '''
814 830 Update pulses field
815 831 '''
816 832
817 833 km2unit = self.rc_configuration.km2unit
818 834 us2unit = self.rc_configuration.us2unit
819 835 ipp = self.rc_configuration.ipp
820 836 ntx = int(self.rc_configuration.ntx)
821 837 ipp_u = int(ipp*km2unit)
822 838 total = ipp_u*ntx if self.rc_configuration.total_units==0 else self.rc_configuration.total_units
823 839 y = []
824 840
825 841 if self.line_type.name=='tr':
826 842 tr_params = json.loads(self.params)
827 843 #print(tr_params)
828 844 #print(tr_params['TX_ref'])
829 845 if tr_params['TX_ref'] in ('0', 0):
830 846 txs = self.get_lines(line_type__name='tx')
831 847 else:
832 848 txs = RCLine.objects.filter(pk=tr_params['TX_ref'])
833 849
834 850 for tx in txs:
835 851 params = json.loads(tx.params)
836 852
837 853 if float(params['pulse_width'])==0:
838 854 continue
839 855 delays = [float(d)*km2unit for d in params['delays'].split(',') if d]
840 856 width = float(params['pulse_width'])*km2unit+int(self.rc_configuration.time_before*us2unit)
841 857 before = 0
842 858 after = int(self.rc_configuration.time_after*us2unit)
843 859
844 860 y_tx = self.points(ntx, ipp_u, width,
845 861 delay=delays,
846 862 before=before,
847 863 after=after,
848 864 sync=self.rc_configuration.sync)
849 865
850 866 ranges = params['range'].split(',')
851 867
852 868 if len(ranges)>0 and ranges[0]!='0':
853 869 y_tx = self.mask_ranges(y_tx, ranges)
854 870
855 871 tr_ranges = tr_params['range'].split(',')
856 872
857 873 if len(tr_ranges)>0 and tr_ranges[0]!='0':
858 874 y_tx = self.mask_ranges(y_tx, tr_ranges)
859 875
860 876 y.extend(y_tx)
861 877
862 878 self.pulses = str(y)
863 879 y = self.array_to_points(self.pulses_as_array())
864 880
865 881 elif self.line_type.name=='tx':
866 882 params = json.loads(self.params)
867 883 delays = [float(d)*km2unit for d in params['delays'].split(',') if d]
868 884 width = float(params['pulse_width'])*km2unit
869 885
870 886 if width>0:
871 887 before = int(self.rc_configuration.time_before*us2unit)
872 888 after = 0
873 889
874 890 y = self.points(ntx, ipp_u, width,
875 891 delay=delays,
876 892 before=before,
877 893 after=after,
878 894 sync=self.rc_configuration.sync)
879 895
880 896 ranges = params['range'].split(',')
881 897
882 898 if len(ranges)>0 and ranges[0]!='0':
883 899 y = self.mask_ranges(y, ranges)
884 900
885 901 elif self.line_type.name=='flip':
886 902 n = float(json.loads(self.params)['number_of_flips'])
887 903 width = n*ipp*km2unit
888 904 y = self.points(int((ntx+1)/(2*n)), ipp_u*n*2, width)
889 905
890 906 elif self.line_type.name=='codes':
891 907 params = json.loads(self.params)
892 908 tx = RCLine.objects.get(pk=params['TX_ref'])
893 909 tx_params = json.loads(tx.params)
894 910 delays = [float(d)*km2unit for d in tx_params['delays'].split(',') if d]
895 911 f = int(float(tx_params['pulse_width'])*km2unit/len(params['codes'][0]))
896 912 codes = [(np.fromstring(''.join([s*f for s in code]), dtype=np.uint8)-48).astype(np.int8) for code in params['codes']]
897 913 codes = [self.array_to_points(code) for code in codes]
898 914 n = len(codes)
899 915
900 916 ranges = tx_params['range'].split(',')
901 917 if len(ranges)>0 and ranges[0]!='0':
902 918 dum = self.mask_ranges(tx.pulses_as_points(), ranges)
903 919 else:
904 920 dum = tx.pulses_as_points()
905 921
906 922 for i, tup in enumerate(dum):
907 923 if tup==(0,0): continue
908 924 code = codes[i%n]
909 925 y.extend([(c[0]+tup[0], c[1]+tup[0]) for c in code])
910 926
911 927 elif self.line_type.name=='sync':
912 928 params = json.loads(self.params)
913 929 n = ipp_u*ntx
914 930 if params['invert'] in ('1', 1):
915 931 y = [(n-1, n)]
916 932 else:
917 933 y = [(0, 1)]
918 934
919 935 elif self.line_type.name=='prog_pulses':
920 936 params = json.loads(self.params)
921 937 if int(params['periodic'])==0:
922 938 nntx = 1
923 939 nipp = ipp_u*ntx
924 940 else:
925 941 nntx = ntx
926 942 nipp = ipp_u
927 943
928 944 if 'params' in params and len(params['params'])>0:
929 945 for p in params['params']:
930 946 y_pp = self.points(nntx, nipp,
931 947 p['end']-p['begin'],
932 948 before=p['begin'])
933 949
934 950 y.extend(y_pp)
935 951
936 952 elif self.line_type.name=='windows':
937 953 params = json.loads(self.params)
938 954 if 'params' in params and len(params['params'])>0:
939 955 tx = RCLine.objects.get(pk=params['TX_ref'])
940 956 tx_params = json.loads(tx.params)
941 957 ranges = tx_params['range'].split(',')
942 958 for p in params['params']:
943 959 y_win = self.points(ntx, ipp_u,
944 960 p['resolution']*p['number_of_samples']*km2unit,
945 961 before=int(self.rc_configuration.time_before*us2unit)+p['first_height']*km2unit,
946 962 sync=self.rc_configuration.sync+self.get_win_ref(p, params['TX_ref'], km2unit))
947 963
948 964
949 965 if len(ranges)>0 and ranges[0]!='0':
950 966 y_win = self.mask_ranges(y_win, ranges)
951 967
952 968 y.extend(y_win)
953 969
954 970 elif self.line_type.name=='mix':
955 971 values = self.rc_configuration.parameters.split('-')
956 972 confs = [RCConfiguration.objects.get(pk=value.split('|')[0]) for value in values]
957 973 modes = [value.split('|')[1] for value in values]
958 974 ops = [value.split('|')[2] for value in values]
959 975 delays = [value.split('|')[3] for value in values]
960 976 masks = [value.split('|')[4] for value in values]
961 977 print("masks")
962 978 print(masks)
963 979 print('{:8b}'.format(int(masks[0])))
964 980 mask = list('{:8b}'.format(int(masks[0])))
965 981 print("mask")
966 982 print(mask)
967 983 mask.reverse()
968 984 print("mask reverse")
969 985 print(mask)
970 986 if mask[self.channel] in ('0', '', ' '):
971 987 y = np.zeros(confs[0].total_units, dtype=np.int8)
972 988 else:
973 989 y = confs[0].get_lines(channel=self.channel)[0].pulses_as_array()
974 990
975 991 for i in range(1, len(values)):
976 992 mask = list('{:8b}'.format(int(masks[i])))
977 993 mask.reverse()
978 994
979 995 if mask[self.channel] in ('0', '', ' '):
980 996 continue
981 997 Y = confs[i].get_lines(channel=self.channel)[0].pulses_as_array()
982 998 delay = float(delays[i])*km2unit
983 999
984 1000 if modes[i]=='P':
985 1001 if delay>0:
986 1002 if delay<self.rc_configuration.ipp*km2unit and len(Y)==len(y):
987 1003 y_temp = np.empty_like(Y)
988 1004 y_temp[:delay] = 0
989 1005 y_temp[delay:] = Y[:-delay]
990 1006 elif delay+len(Y)>len(y):
991 1007 y_new = np.zeros(delay+len(Y), dtype=np.int8)
992 1008 y_new[:len(y)] = y
993 1009 y = y_new
994 1010 y_temp = np.zeros(delay+len(Y), dtype=np.int8)
995 1011 y_temp[-len(Y):] = Y
996 1012 elif delay+len(Y)==len(y):
997 1013 y_temp = np.zeros(delay+len(Y))
998 1014 y_temp[-len(Y):] = Y
999 1015 elif delay+len(Y)<len(y):
1000 1016 y_temp = np.zeros(len(y), dtype=np.int8)
1001 1017 y_temp[delay:delay+len(Y)] = Y
1002 1018 else:
1003 1019 y_temp = Y.copy()
1004 1020
1005 1021 if ops[i]=='OR':
1006 1022 y = y | y_temp
1007 1023 elif ops[i]=='XOR':
1008 1024 y = y ^ y_temp
1009 1025 elif ops[i]=='AND':
1010 1026 y = y & y_temp
1011 1027 elif ops[i]=='NAND':
1012 1028 y = y & ~y_temp
1013 1029 else:
1014 1030 y = np.concatenate([y, Y])
1015 1031
1016 1032 total = len(y)
1017 1033 y = self.array_to_points(y)
1018 1034
1019 1035 else:
1020 1036 y = []
1021 1037
1022 1038 if self.rc_configuration.total_units != total:
1023 1039 self.rc_configuration.total_units = total
1024 1040 self.rc_configuration.save()
1025 1041
1026 1042 self.pulses = str(y)
1027 1043 self.save()
1028 1044
1029 1045 @staticmethod
1030 1046 def array_to_points(X):
1031 1047
1032 1048 if X.size==0:
1033 1049 return []
1034 1050
1035 1051 d = X[1:]-X[:-1]
1036 1052
1037 1053 up = np.where(d==1)[0]
1038 1054 if X[0]==1:
1039 1055 up = np.concatenate((np.array([-1]), up))
1040 1056 up += 1
1041 1057
1042 1058 dw = np.where(d==-1)[0]
1043 1059 if X[-1]==1:
1044 1060 dw = np.concatenate((dw, np.array([len(X)-1])))
1045 1061 dw += 1
1046 1062
1047 1063 return [(tup[0], tup[1]) for tup in zip(up, dw)]
1048 1064
1049 1065 @staticmethod
1050 1066 def mask_ranges(Y, ranges):
1051 1067
1052 1068 y = [(0, 0) for __ in Y]
1053 1069
1054 1070 for index in ranges:
1055 1071 if '-' in index:
1056 1072 args = [int(a) for a in index.split('-')]
1057 1073 y[args[0]-1:args[1]] = Y[args[0]-1:args[1]]
1058 1074 else:
1059 1075 y[int(index)-1] = Y[int(index)-1]
1060 1076
1061 1077 return y
1062 1078
1063 1079 @staticmethod
1064 1080 def points(ntx, ipp, width, delay=[0], before=0, after=0, sync=0):
1065 1081
1066 1082 delays = len(delay)
1067 1083
1068 1084 Y = [(int(ipp*x+before+delay[x%delays]+sync), int(ipp*x+width+before+delay[x%delays]+after+sync)) for x in range(ntx)]
1069 1085
1070 1086 return Y
1071 1087
1072 1088 class RCClock(models.Model):
1073 1089
1074 1090 rc_configuration = models.ForeignKey('RCConfiguration', on_delete=models.CASCADE)
1075 1091 mode = models.BooleanField(default=True, choices=((True, 'Auto'), (False, 'Manual')))
1076 1092 multiplier = models.PositiveIntegerField(default=60)
1077 1093 divisor = models.PositiveIntegerField(default=10)
1078 1094 reference = models.PositiveSmallIntegerField(default=1, choices=((0, 'Internal (25MHz)'), (1, 'External (10MHz)')))
1079 1095 frequency = models.FloatField(default=60.0)
@@ -1,435 +1,435
1 1 import json
2 2
3 3 from django.contrib import messages
4 4 from django.utils.safestring import mark_safe
5 5 from django.shortcuts import render, redirect, get_object_or_404, HttpResponse
6 6 from django.contrib.auth.decorators import login_required
7 7
8 8 from apps.main.models import Experiment, Device
9 9 from apps.main.views import sidebar
10 10
11 11 from .models import RCConfiguration, RCLine, RCLineType, RCLineCode, RCClock
12 12 from .forms import RCConfigurationForm, RCLineForm, RCLineViewForm, RCLineEditForm, RCImportForm, RCLineCodesForm, RCClockForm
13 13
14 14
15 15 def conf(request, conf_id):
16 16
17 17 conf = get_object_or_404(RCConfiguration, pk=conf_id)
18 18
19 19 lines = RCLine.objects.filter(rc_configuration=conf).order_by('channel')
20 20 clk = RCClock.objects.filter(rc_configuration=conf).first()
21 21 if clk is None:
22 22 clk = RCClock(rc_configuration=conf)
23 23 clk.save()
24 24
25 25 for line in lines:
26 26 params = json.loads(line.params)
27 27 line.form = RCLineViewForm(extra_fields=params, line=line)
28 28 if 'params' in params:
29 29 line.subforms = [RCLineViewForm(extra_fields=fields, line=line, subform=True) for fields in params['params']]
30 30
31 31 kwargs = {}
32 32 kwargs['clock'] = clk
33 33 kwargs['dev_conf'] = conf
34 34 kwargs['rc_lines'] = lines
35 35 kwargs['dev_conf_keys'] = ['ipp_unit', 'ntx', 'clock_divider', 'clock',
36 'time_before', 'time_after', 'sync', 'sampling_reference',
36 'time_before', 'time_after', 'sync', 'ch_monitor', 'sampling_reference',
37 37 'control_tx', 'control_sw']
38 38
39 39 kwargs['title'] = 'Configuration'
40 40 kwargs['suptitle'] = 'Detail'
41 41
42 42 kwargs['button'] = 'Edit Configuration'
43 43 ###### SIDEBAR ######
44 44 kwargs.update(sidebar(conf=conf))
45 45
46 46 return render(request, 'rc_conf.html', kwargs)
47 47
48 48 @login_required
49 49 def conf_edit(request, conf_id):
50 50
51 51 conf = get_object_or_404(RCConfiguration, pk=conf_id)
52 52 clock = RCClock.objects.get(rc_configuration=conf)
53 53 lines = RCLine.objects.filter(rc_configuration=conf).order_by('channel')
54 54
55 55 for line in lines:
56 56 params = json.loads(line.params)
57 57 #print(params)
58 58 line.form = RCLineEditForm(conf=conf, line=line, extra_fields=params)
59 59 line.subform = False
60 60
61 61 if 'params' in params:
62 62 line.subforms = [RCLineEditForm(extra_fields=fields, line=line, subform=i) for i, fields in enumerate(params['params'])]
63 63 line.subform = True
64 64 print(params)
65 65 print("fin de sub carga de params")
66 66 #print("fin de carga de params")
67 67 if request.method=='GET':
68 68 print("GET case")
69 69 form = RCConfigurationForm(instance=conf)
70 70 form_clock = RCClockForm(instance=clock)
71 71
72 72 elif request.method=='POST':
73 73 #print("ingreso a post conf edit")
74 74 line_data = {}
75 75 conf_data = {}
76 76 clock_data = {}
77 77 extras = []
78 78 print("Inicio impresion POST#####")
79 79 print(request.POST.items)
80 80 print("Fin impresion de POST items#####")
81 81 #classified post fields
82 82 for label,value in request.POST.items():
83 83 if label=='csrfmiddlewaretoken':
84 84 continue
85 85
86 86 if label.count('|')==0:
87 87 if label in ('mode', 'multiplier', 'divisor', 'reference', 'frequency'):
88 88 clock_data[label] = value
89 89 else:
90 90 conf_data[label] = value
91 91 continue
92 92
93 93 elif label.split('|')[0]!='-1':
94 94 extras.append(label)
95 95 continue
96 96
97 97 #print(label)
98 98 x, pk, name = label.split('|')
99 99
100 100 if name=='codes':
101 101 value = [s for s in value.split('\r\n') if s]
102 102
103 103 if pk in line_data:
104 104 line_data[pk][name] = value
105 105 else:
106 106 line_data[pk] = {name:value}
107 107 #print(line_data[pk])
108 108 #update conf
109 109
110 110 form_clock = RCClockForm(clock_data, instance=clock)
111 111 form = RCConfigurationForm(conf_data, instance=conf)
112 112
113 113 #print(request.POST.items())
114 114
115 115 if form_clock.is_valid() and form.is_valid():
116 116 form_clock.save()
117 117 form.save()
118 118
119 119 #update lines fields
120 120 extras.sort(key=lambda x: int(x.split('|')[0]))
121 121 #print("Inicio extras")
122 122 #print(extras)
123 123 #print("Fin extras")
124 124 for label in extras:
125 125 x, pk, name = label.split('|')
126 126 if pk not in line_data:
127 127 line_data[pk] = {}
128 128 if 'params' not in line_data[pk]:
129 129 line_data[pk]['params'] = []
130 130 if len(line_data[pk]['params'])<int(x)+1:
131 131 line_data[pk]['params'].append({})
132 132 line_data[pk]['params'][int(x)][name] = float(request.POST[label])
133 133
134 134 for pk, params in line_data.items():
135 135 line = RCLine.objects.get(pk=pk)
136 136 if line.line_type.name in ('windows', 'prog_pulses'):
137 137 if 'params' not in params:
138 138 params['params'] = []
139 139 line.params = json.dumps(params)
140 140 #print(line.params)
141 141 line.save()
142 142
143 143
144 144 #update pulses field
145 145 conf.update_pulses()
146 146
147 147 messages.success(request, 'RC Configuration successfully updated')
148 148
149 149 return redirect(conf.get_absolute_url())
150 150
151 151 kwargs = {}
152 152 kwargs['dev_conf'] = conf
153 153 kwargs['form'] = form
154 154 kwargs['form_clock'] = form_clock
155 155 kwargs['rc_lines'] = lines
156 156 kwargs['edit'] = True
157 157
158 158 kwargs['title'] = 'RC Configuration'
159 159 kwargs['suptitle'] = 'Edit'
160 160 kwargs['button'] = 'Update'
161 161
162 162 return render(request, 'rc_conf_edit.html', kwargs)
163 163
164 164
165 165 def add_line(request, conf_id, line_type_id=None, code_id=None):
166 166
167 167 conf = get_object_or_404(RCConfiguration, pk=conf_id)
168 168
169 169 if request.method=='GET':
170 170 if line_type_id:
171 171 line_type = get_object_or_404(RCLineType, pk=line_type_id)
172 172
173 173 if code_id:
174 174 form = RCLineForm(initial={'rc_configuration':conf_id, 'line_type': line_type_id, 'code_id': code_id},
175 175 extra_fields=json.loads(line_type.params))
176 176 else:
177 177 form = RCLineForm(initial={'rc_configuration':conf_id, 'line_type': line_type_id},
178 178 extra_fields=json.loads(line_type.params))
179 179 else:
180 180 line_type = {'id':0}
181 181 form = RCLineForm(initial={'rc_configuration':conf_id})
182 182
183 183 if request.method=='POST':
184 184
185 185 line_type = get_object_or_404(RCLineType, pk=line_type_id)
186 186 form = RCLineForm(request.POST,
187 187 extra_fields=json.loads(line_type.params))
188 188
189 189 if form.is_valid():
190 190 form.save()
191 191 form.instance.update_pulses()
192 192 return redirect('url_edit_rc_conf', conf.id)
193 193
194 194 kwargs = {}
195 195 kwargs['form'] = form
196 196 kwargs['title'] = 'RC Configuration'
197 197 kwargs['suptitle'] = 'Add Line'
198 198 kwargs['button'] = 'Add'
199 199 kwargs['previous'] = conf.get_absolute_url_edit()
200 200 kwargs['dev_conf'] = conf
201 201 kwargs['line_type'] = line_type
202 202
203 203 return render(request, 'rc_add_line.html', kwargs)
204 204
205 205 def edit_codes(request, conf_id, line_id, code_id=None):
206 206
207 207 conf = get_object_or_404(RCConfiguration, pk=conf_id)
208 208 line = get_object_or_404(RCLine, pk=line_id)
209 209 params = json.loads(line.params)
210 210
211 211 if request.method=='GET':
212 212 if code_id:
213 213 code = get_object_or_404(RCLineCode, pk=code_id)
214 214 form = RCLineCodesForm(instance=code)
215 215 else:
216 216 initial = {'code': params['code'],
217 217 'codes': params['codes'] if 'codes' in params else [],
218 218 'number_of_codes': len(params['codes']) if 'codes' in params else 0,
219 219 'bits_per_code': len(params['codes'][0]) if 'codes' in params else 0,
220 220 }
221 221 form = RCLineCodesForm(initial=initial)
222 222
223 223 if request.method=='POST':
224 224 form = RCLineCodesForm(request.POST)
225 225 if form.is_valid():
226 226 params['code'] = request.POST['code']
227 227 params['codes'] = [s for s in request.POST['codes'].split('\r\n') if s]
228 228 line.params = json.dumps(params)
229 229 line.save()
230 230 messages.success(request, 'Line: "%s" has been updated.' % line)
231 231 return redirect('url_edit_rc_conf', conf.id)
232 232
233 233 kwargs = {}
234 234 kwargs['form'] = form
235 235 kwargs['title'] = line
236 236 kwargs['suptitle'] = 'Edit'
237 237 kwargs['button'] = 'Update'
238 238 kwargs['dev_conf'] = conf
239 239 kwargs['previous'] = conf.get_absolute_url_edit()
240 240 kwargs['line'] = line
241 241
242 242 return render(request, 'rc_edit_codes.html', kwargs)
243 243
244 244 def add_subline(request, conf_id, line_id):
245 245
246 246 conf = get_object_or_404(RCConfiguration, pk=conf_id)
247 247 line = get_object_or_404(RCLine, pk=line_id)
248 248
249 249 if request.method == 'POST':
250 250 if line:
251 251 params = json.loads(line.params)
252 252 subparams = json.loads(line.line_type.params)
253 253 if 'params' in subparams:
254 254 dum = {}
255 255 for key, value in subparams['params'].items():
256 256 dum[key] = value['value']
257 257 params['params'].append(dum)
258 258 line.params = json.dumps(params)
259 259 line.save()
260 260 return redirect('url_edit_rc_conf', conf.id)
261 261
262 262 kwargs = {}
263 263
264 264 kwargs['title'] = 'Add new'
265 265 kwargs['suptitle'] = '%s to %s' % (line.line_type.name, line)
266 266
267 267 return render(request, 'confirm.html', kwargs)
268 268
269 269 def remove_line(request, conf_id, line_id):
270 270
271 271 conf = get_object_or_404(RCConfiguration, pk=conf_id)
272 272 line = get_object_or_404(RCLine, pk=line_id)
273 273
274 274 if request.method == 'POST':
275 275 if line:
276 276 try:
277 277 channel = line.channel
278 278 line.delete()
279 279 for ch in range(channel+1, RCLine.objects.filter(rc_configuration=conf).count()+1):
280 280 l = RCLine.objects.get(rc_configuration=conf, channel=ch)
281 281 l.channel = l.channel-1
282 282 l.save()
283 283 messages.success(request, 'Line: "%s" has been deleted.' % line)
284 284 except:
285 285 messages.error(request, 'Unable to delete line: "%s".' % line)
286 286
287 287 return redirect('url_edit_rc_conf', conf.id)
288 288
289 289 kwargs = {}
290 290
291 291 kwargs['object'] = line
292 292 kwargs['delete'] = True
293 293 kwargs['title'] = 'Delete'
294 294 kwargs['suptitle'] = 'Line'
295 295 kwargs['previous'] = conf.get_absolute_url_edit()
296 296 return render(request, 'confirm.html', kwargs)
297 297
298 298
299 299 def remove_subline(request, conf_id, line_id, subline_id):
300 300
301 301 conf = get_object_or_404(RCConfiguration, pk=conf_id)
302 302 line = get_object_or_404(RCLine, pk=line_id)
303 303
304 304 if request.method == 'POST':
305 305 if line:
306 306 params = json.loads(line.params)
307 307 params['params'].remove(params['params'][int(subline_id)-1])
308 308 line.params = json.dumps(params)
309 309 line.save()
310 310
311 311 return redirect('url_edit_rc_conf', conf.id)
312 312
313 313 kwargs = {}
314 314
315 315 kwargs['object'] = line
316 316 kwargs['object_name'] = line.line_type.name
317 317 kwargs['delete_view'] = True
318 318 kwargs['title'] = 'Confirm delete'
319 319
320 320 return render(request, 'confirm.html', kwargs)
321 321
322 322
323 323 def update_lines_position(request, conf_id):
324 324
325 325 conf = get_object_or_404(RCConfiguration, pk=conf_id)
326 326 print("ingreso a update_lines_position")
327 327 if request.method=='POST':
328 328 ch = 0
329 329 for item in request.POST['items'].split('&'):
330 330 line = RCLine.objects.get(pk=item.split('=')[-1])
331 331 line.channel = ch
332 332 line.save()
333 333 ch += 1
334 334
335 335 lines = RCLine.objects.filter(rc_configuration=conf).order_by('channel')
336 336
337 337 for line in lines:
338 338
339 339 params = json.loads(line.params)
340 340 print(params)
341 341 print("Fin de impresion_lines_position")
342 342 line.form = RCLineEditForm(conf=conf, line=line, extra_fields=params)
343 343
344 344 if 'params' in params:
345 345 line.subform = True
346 346 line.subforms = [RCLineEditForm(extra_fields=fields, line=line, subform=i) for i, fields in enumerate(params['params'])]
347 347
348 348 html = render(request, 'rc_lines.html', {'dev_conf':conf, 'rc_lines':lines, 'edit':True})
349 349 data = {'html': html.content.decode('utf8')}
350 350
351 351 return HttpResponse(json.dumps(data), content_type="application/json")
352 352 return redirect('url_edit_rc_conf', conf.id)
353 353
354 354
355 355 def import_file(request, conf_id):
356 356
357 357 conf = get_object_or_404(RCConfiguration, pk=conf_id)
358 358 if request.method=='POST':
359 359 form = RCImportForm(request.POST, request.FILES)
360 360 if form.is_valid():
361 361 try:
362 362 data = conf.import_from_file(request.FILES['file_name'])
363 363 conf.dict_to_parms(data)
364 364 conf.update_pulses()
365 365 messages.success(request, 'Configuration "%s" loaded succesfully' % request.FILES['file_name'])
366 366 return redirect(conf.get_absolute_url_edit())
367 367
368 368 except Exception as e:
369 369 messages.error(request, 'Error parsing file: "%s" - %s' % (request.FILES['file_name'], repr(e)))
370 370 else:
371 371 messages.warning(request, 'Your current configuration will be replaced')
372 372 form = RCImportForm()
373 373
374 374 kwargs = {}
375 375 kwargs['form'] = form
376 376 kwargs['title'] = 'RC Configuration'
377 377 kwargs['suptitle'] = 'Import file'
378 378 kwargs['button'] = 'Upload'
379 379 kwargs['previous'] = conf.get_absolute_url()
380 380
381 381 return render(request, 'rc_import.html', kwargs)
382 382
383 383
384 384 def plot_pulses(request, conf_id):
385 385
386 386 conf = get_object_or_404(RCConfiguration, pk=conf_id)
387 387 km = True if 'km' in request.GET else False
388 388
389 389 script, div = conf.plot_pulses(km=km)
390 390
391 391 kwargs = {}
392 392 kwargs['no_sidebar'] = True
393 393 kwargs['title'] = 'RC Pulses'
394 394 kwargs['suptitle'] = conf.name
395 395 kwargs['div'] = mark_safe(div)
396 396 kwargs['script'] = mark_safe(script)
397 397 kwargs['units'] = conf.km2unit
398 398 kwargs['kms'] = 1/conf.km2unit
399 399
400 400 if km:
401 401 kwargs['km_selected'] = True
402 402
403 403 if 'json' in request.GET:
404 404 return HttpResponse(json.dumps({'div':mark_safe(div), 'script':mark_safe(script)}), content_type="application/json")
405 405 else:
406 406 return render(request, 'rc_pulses.html', kwargs)
407 407
408 408 def plot_pulses2(request, conf_id):
409 409
410 410 conf = get_object_or_404(RCConfiguration, pk=conf_id)
411 411 km = True if 'km' in request.GET else False
412 412
413 413 script, div = conf.plot_pulses2(km=km)
414 414
415 415 kwargs = {}
416 416 kwargs['no_sidebar'] = True
417 417 kwargs['title'] = 'RC Pulses'
418 418 kwargs['suptitle'] = conf.name
419 419 kwargs['div'] = mark_safe(div)
420 420 kwargs['script'] = mark_safe(script)
421 421 kwargs['units'] = conf.km2unit
422 422 kwargs['kms'] = 1/conf.km2unit
423 423
424 424 if km:
425 425 kwargs['km_selected'] = True
426 426
427 427 if 'json' in request.GET:
428 428 return HttpResponse(json.dumps({'div':mark_safe(div), 'script':mark_safe(script)}), content_type="application/json")
429 429 else:
430 430 return render(request, 'rc_pulses.html', kwargs)
431 431
432 432 def conf_raw(request, conf_id):
433 433 conf = get_object_or_404(RCConfiguration, pk=conf_id)
434 434 raw = conf.write_device(raw=True)
435 435 return HttpResponse(raw, content_type='application/json')
General Comments 0
You need to be logged in to leave comments. Login now