##// END OF EJS Templates
Add compatibility with embed CGS in RC
Juan C. Espinoza -
r328:e61e12b2d8be
parent child
Show More
@@ -1,12 +1,12
1 1 REDIS_HOST=radarsys-redis
2 2 REDIS_PORT=6379
3 POSTGRES_DB_NAME=radarsys
4 3 POSTGRES_PORT_5432_TCP_ADDR=radarsys-postgres
5 4 POSTGRES_PORT_5432_TCP_PORT=5432
6 POSTGRES_USER=docker
7 POSTGRES_PASSWORD=docker
5 DB_NAME=radarsys
6 DB_USER=docker
7 DB_PASSWORD=docker
8 8 PGDATA=/var/lib/postgresql/data
9 9 LC_ALL=C.UTF-8
10 10 TZ=America/Lima
11 11 DOCKER_DATA=/Volumes/dockers/radarsys/
12 12 LOCAL_IP=192.168.1.128
@@ -1,79 +1,81
1 1 {% extends "base.html" %}
2 2 {% load bootstrap3 %}
3 3 {% load static %}
4 4 {% load main_tags %}
5 5 {% block content-title %}{{title}}{% endblock %}
6 6 {% block content-suptitle %}{{suptitle}}{% endblock %}
7 7
8 8 {% block content %}
9 9
10 10 {% block menu-actions %}
11 11 <span class=" dropdown pull-right">
12 12 <a href="#" class="dropdown-toggle" data-toggle="dropdown"><span class="glyphicon glyphicon-menu-hamburger gi-2x" aria-hidden="true"></span></a>
13 13 <ul class="dropdown-menu" role="menu">
14 14 <li><a href="{{ dev_conf.get_absolute_url_edit }}"><span class="glyphicon glyphicon-pencil" aria-hidden="true"></span> Edit</a></li>
15 15 <li><a href="{{ dev_conf.get_absolute_url_delete }}"><span class="glyphicon glyphicon-remove" aria-hidden="true"></span> Delete</a></li>
16 16 <li><a href="{{ dev_conf.get_absolute_url_import }}"><span class="glyphicon glyphicon-import" aria-hidden="true"></span> Import </a></li>
17 17 <li><a href="{{ dev_conf.get_absolute_url_export }}"><span class="glyphicon glyphicon-export" aria-hidden="true"></span> Export </a></li>
18 18 {% block extra-menu-actions %}
19 19 {% endblock %}
20 20 <li><a>----------------</a></li>
21 21 <li><a href="{{ dev_conf.get_absolute_url_status }}"><span class="glyphicon glyphicon-refresh" aria-hidden="true"></span> Status</a></li>
22 22 {% if not no_play %}
23 23 {% if not only_stop %}
24 24 <li><a href="{{ dev_conf.get_absolute_url_start}}"><span class="glyphicon glyphicon-play" aria-hidden="true"></span> Start</a></li>
25 25 {% endif %}
26 26 <li><a href="{{ dev_conf.get_absolute_url_stop }}"><span class="glyphicon glyphicon-stop" aria-hidden="true"></span> Stop</a></li>
27 27 {% endif %}
28 28 <li><a href="{{ dev_conf.get_absolute_url_write }}"><span class="glyphicon glyphicon-download" aria-hidden="true"></span> Write</a></li>
29 29 {% if dev_conf.device.device_type.name != 'abs' %}
30 30 <li><a href="{{ dev_conf.get_absolute_url_read }}"><span class="glyphicon glyphicon-upload" aria-hidden="true"></span> Read</a></li>
31 31 {% endif %}
32 32 </ul>
33 33 </span>
34 34 {% endblock %}
35 35
36 {% block content-detail %}
36 37 <table class="table table-bordered">
37 38 <tr>
38 39 <th>Status</th>
39 40 <td class="text-{{dev_conf.device.status_color}}"><strong> {% if dev_conf.device.device_type.name == 'abs' %} {{connected_modules}} {% else %} {{dev_conf.device.get_status_display}}{% endif %}</strong></td>
40 41 </tr>
41 42
42 43 {% for key in dev_conf_keys %}
43 44 <tr>
44 45 <th>{% get_verbose_field_name dev_conf key %}</th>
45 46 <td>{{dev_conf|attr:key}}</td>
46 47 </tr>
47 48 {% endfor %}
48 49 </table>
50 {% endblock %}
49 51
50 52 {% block extra-content %}
51 53 {% endblock %}
52 54
53 55 {% endblock %}
54 56
55 57 {% block extra-js%}
56 58 <script type="text/javascript">
57 59
58 60 $("#bt_edit").click(function() {
59 61 document.location = "{{ dev_conf.get_absolute_url_edit }}";
60 62 });
61 63
62 64 $("#bt_read").click(function() {
63 65 document.location = "{{ dev_conf.get_absolute_url_read }}";
64 66 });
65 67
66 68 $("#bt_write").click(function() {
67 69 document.location = "{{ dev_conf.get_absolute_url_write }}";
68 70 });
69 71
70 72 $("#bt_import").click(function() {
71 73 document.location = "{{ dev_conf.get_absolute_url_import }}";
72 74 });
73 75
74 76 $("#bt_export").click(function() {
75 77 document.location = "{{ dev_conf.get_absolute_url_export }}";
76 78 });
77 79
78 80 </script>
79 81 {% endblock %}
@@ -1,1865 +1,1868
1 1 import ast
2 2 import json
3 3 import hashlib
4 4 from datetime import datetime, timedelta
5 5
6 6 from django.shortcuts import render, redirect, get_object_or_404, HttpResponse
7 7 from django.utils.safestring import mark_safe
8 8 from django.http import HttpResponseRedirect
9 9 from django.core.urlresolvers import reverse
10 10 from django.db.models import Q
11 11 from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
12 12 from django.contrib import messages
13 13 from django.http.request import QueryDict
14 14 from django.contrib.auth.decorators import login_required, user_passes_test
15 15
16 16 try:
17 17 from urllib.parse import urlencode
18 18 except ImportError:
19 19 from urllib import urlencode
20 20
21 21 from .forms import CampaignForm, ExperimentForm, DeviceForm, ConfigurationForm, LocationForm, UploadFileForm, DownloadFileForm, OperationForm, NewForm
22 22 from .forms import OperationSearchForm, FilterForm, ChangeIpForm
23 23
24 24 from .tasks import task_start
25 25
26 26 from apps.rc.forms import RCConfigurationForm, RCLineCode, RCMixConfigurationForm
27 27 from apps.dds.forms import DDSConfigurationForm
28 28 from apps.jars.forms import JARSConfigurationForm
29 29 from apps.cgs.forms import CGSConfigurationForm
30 30 from apps.abs.forms import ABSConfigurationForm
31 31 from apps.usrp.forms import USRPConfigurationForm
32 32 from .utils import Params
33 33
34 34 from .models import Campaign, Experiment, Device, Configuration, Location, RunningExperiment, DEV_STATES
35 35 from apps.cgs.models import CGSConfiguration
36 36 from apps.jars.models import JARSConfiguration, EXPERIMENT_TYPE
37 37 from apps.usrp.models import USRPConfiguration
38 38 from apps.abs.models import ABSConfiguration
39 from apps.rc.models import RCConfiguration, RCLine, RCLineType
39 from apps.rc.models import RCConfiguration, RCLine, RCLineType, RCClock
40 40 from apps.dds.models import DDSConfiguration
41 41
42 42 from radarsys.celery import app
43 43
44 44
45 45 CONF_FORMS = {
46 46 'rc': RCConfigurationForm,
47 47 'dds': DDSConfigurationForm,
48 48 'jars': JARSConfigurationForm,
49 49 'cgs': CGSConfigurationForm,
50 50 'abs': ABSConfigurationForm,
51 51 'usrp': USRPConfigurationForm,
52 52 }
53 53
54 54 CONF_MODELS = {
55 55 'rc': RCConfiguration,
56 56 'dds': DDSConfiguration,
57 57 'jars': JARSConfiguration,
58 58 'cgs': CGSConfiguration,
59 59 'abs': ABSConfiguration,
60 60 'usrp': USRPConfiguration,
61 61 }
62 62
63 63 MIX_MODES = {
64 64 '0': 'P',
65 65 '1': 'S',
66 66 }
67 67
68 68 MIX_OPERATIONS = {
69 69 '0': 'OR',
70 70 '1': 'XOR',
71 71 '2': 'AND',
72 72 '3': 'NAND',
73 73 }
74 74
75 75
76 76 def is_developer(user):
77 77
78 78 groups = [str(g.name) for g in user.groups.all()]
79 79 return 'Developer' in groups or user.is_staff
80 80
81 81
82 82 def is_operator(user):
83 83
84 84 groups = [str(g.name) for g in user.groups.all()]
85 85 return 'Operator' in groups or user.is_staff
86 86
87 87
88 88 def has_been_modified(model):
89 89
90 90 prev_hash = model.hash
91 91 new_hash = hashlib.sha256(str(model.parms_to_dict)).hexdigest()
92 92 if prev_hash != new_hash:
93 93 model.hash = new_hash
94 94 model.save()
95 95 return True
96 96 return False
97 97
98 98
99 99 def index(request):
100 100 kwargs = {'no_sidebar': True}
101 101
102 102 return render(request, 'index.html', kwargs)
103 103
104 104
105 105 def locations(request):
106 106
107 107 page = request.GET.get('page')
108 108 order = ('name',)
109 109
110 110 kwargs = get_paginator(Location, page, order)
111 111
112 112 kwargs['keys'] = ['name', 'description']
113 113 kwargs['title'] = 'Radar System'
114 114 kwargs['suptitle'] = 'List'
115 115 kwargs['no_sidebar'] = True
116 116
117 117 return render(request, 'base_list.html', kwargs)
118 118
119 119
120 120 def location(request, id_loc):
121 121
122 122 location = get_object_or_404(Location, pk=id_loc)
123 123
124 124 kwargs = {}
125 125 kwargs['location'] = location
126 126 kwargs['location_keys'] = ['name', 'description']
127 127
128 128 kwargs['title'] = 'Location'
129 129 kwargs['suptitle'] = 'Details'
130 130
131 131 return render(request, 'location.html', kwargs)
132 132
133 133
134 134 @login_required
135 135 def location_new(request):
136 136
137 137 if request.method == 'GET':
138 138 form = LocationForm()
139 139
140 140 if request.method == 'POST':
141 141 form = LocationForm(request.POST)
142 142
143 143 if form.is_valid():
144 144 form.save()
145 145 return redirect('url_locations')
146 146
147 147 kwargs = {}
148 148 kwargs['form'] = form
149 149 kwargs['title'] = 'Radar System'
150 150 kwargs['suptitle'] = 'New'
151 151 kwargs['button'] = 'Create'
152 152
153 153 return render(request, 'base_edit.html', kwargs)
154 154
155 155
156 156 @login_required
157 157 def location_edit(request, id_loc):
158 158
159 159 location = get_object_or_404(Location, pk=id_loc)
160 160
161 161 if request.method == 'GET':
162 162 form = LocationForm(instance=location)
163 163
164 164 if request.method == 'POST':
165 165 form = LocationForm(request.POST, instance=location)
166 166
167 167 if form.is_valid():
168 168 form.save()
169 169 return redirect('url_locations')
170 170
171 171 kwargs = {}
172 172 kwargs['form'] = form
173 173 kwargs['title'] = 'Location'
174 174 kwargs['suptitle'] = 'Edit'
175 175 kwargs['button'] = 'Update'
176 176
177 177 return render(request, 'base_edit.html', kwargs)
178 178
179 179
180 180 @login_required
181 181 def location_delete(request, id_loc):
182 182
183 183 location = get_object_or_404(Location, pk=id_loc)
184 184
185 185 if request.method == 'POST':
186 186
187 187 if is_developer(request.user):
188 188 location.delete()
189 189 return redirect('url_locations')
190 190
191 191 messages.error(request, 'Not enough permission to delete this object')
192 192 return redirect(location.get_absolute_url())
193 193
194 194 kwargs = {
195 195 'title': 'Delete',
196 196 'suptitle': 'Location',
197 197 'object': location,
198 198 'delete': True
199 199 }
200 200
201 201 return render(request, 'confirm.html', kwargs)
202 202
203 203
204 204 def devices(request):
205 205
206 206 page = request.GET.get('page')
207 207 order = ('location', 'device_type')
208 208
209 209 filters = request.GET.copy()
210 210 kwargs = get_paginator(Device, page, order, filters)
211 211 form = FilterForm(initial=request.GET, extra_fields=['tags'])
212 212
213 213 kwargs['keys'] = ['device_type', 'location',
214 214 'ip_address', 'port_address', 'actions']
215 215 kwargs['title'] = 'Device'
216 216 kwargs['suptitle'] = 'List'
217 217 kwargs['no_sidebar'] = True
218 218 kwargs['form'] = form
219 219 kwargs['add_url'] = reverse('url_add_device')
220 220 filters.pop('page', None)
221 221 kwargs['q'] = urlencode(filters)
222 222 kwargs['menu_devices'] = 'active'
223 223 return render(request, 'base_list.html', kwargs)
224 224
225 225
226 226 def device(request, id_dev):
227 227
228 228 device = get_object_or_404(Device, pk=id_dev)
229 229
230 230 kwargs = {}
231 231 kwargs['device'] = device
232 232 kwargs['device_keys'] = ['device_type',
233 233 'ip_address', 'port_address', 'description']
234 234
235 235 kwargs['title'] = 'Device'
236 236 kwargs['suptitle'] = 'Details'
237 237 kwargs['menu_devices'] = 'active'
238 238
239 239 return render(request, 'device.html', kwargs)
240 240
241 241
242 242 @login_required
243 243 def device_new(request):
244 244
245 245 if request.method == 'GET':
246 246 form = DeviceForm()
247 247
248 248 if request.method == 'POST':
249 249 form = DeviceForm(request.POST)
250 250
251 251 if form.is_valid():
252 252 form.save()
253 253 return redirect('url_devices')
254 254
255 255 kwargs = {}
256 256 kwargs['form'] = form
257 257 kwargs['title'] = 'Device'
258 258 kwargs['suptitle'] = 'New'
259 259 kwargs['button'] = 'Create'
260 260 kwargs['menu_devices'] = 'active'
261 261
262 262 return render(request, 'base_edit.html', kwargs)
263 263
264 264
265 265 @login_required
266 266 def device_edit(request, id_dev):
267 267
268 268 device = get_object_or_404(Device, pk=id_dev)
269 269
270 270 if request.method == 'GET':
271 271 form = DeviceForm(instance=device)
272 272
273 273 if request.method == 'POST':
274 274 form = DeviceForm(request.POST, instance=device)
275 275
276 276 if form.is_valid():
277 277 form.save()
278 278 return redirect(device.get_absolute_url())
279 279
280 280 kwargs = {}
281 281 kwargs['form'] = form
282 282 kwargs['title'] = 'Device'
283 283 kwargs['suptitle'] = 'Edit'
284 284 kwargs['button'] = 'Update'
285 285 kwargs['menu_devices'] = 'active'
286 286
287 287 return render(request, 'base_edit.html', kwargs)
288 288
289 289
290 290 @login_required
291 291 def device_delete(request, id_dev):
292 292
293 293 device = get_object_or_404(Device, pk=id_dev)
294 294
295 295 if request.method == 'POST':
296 296
297 297 if is_developer(request.user):
298 298 device.delete()
299 299 return redirect('url_devices')
300 300
301 301 messages.error(request, 'Not enough permission to delete this object')
302 302 return redirect(device.get_absolute_url())
303 303
304 304 kwargs = {
305 305 'title': 'Delete',
306 306 'suptitle': 'Device',
307 307 'object': device,
308 308 'delete': True
309 309 }
310 310 kwargs['menu_devices'] = 'active'
311 311
312 312 return render(request, 'confirm.html', kwargs)
313 313
314 314
315 315 @login_required
316 316 def device_change_ip(request, id_dev):
317 317
318 318 device = get_object_or_404(Device, pk=id_dev)
319 319
320 320 if request.method == 'POST':
321 321
322 322 if is_developer(request.user):
323 323 device.change_ip(**request.POST.dict())
324 324 level, message = device.message.split('|')
325 325 messages.add_message(request, level, message)
326 326 else:
327 327 messages.error(
328 328 request, 'Not enough permission to delete this object')
329 329 return redirect(device.get_absolute_url())
330 330
331 331 kwargs = {
332 332 'title': 'Device',
333 333 'suptitle': 'Change IP',
334 334 'object': device,
335 335 'previous': device.get_absolute_url(),
336 336 'form': ChangeIpForm(initial={'ip_address': device.ip_address}),
337 337 'message': ' ',
338 338 }
339 339 kwargs['menu_devices'] = 'active'
340 340
341 341 return render(request, 'confirm.html', kwargs)
342 342
343 343
344 344 def campaigns(request):
345 345
346 346 page = request.GET.get('page')
347 347 order = ('-start_date',)
348 348 filters = request.GET.copy()
349 349
350 350 kwargs = get_paginator(Campaign, page, order, filters)
351 351
352 352 form = FilterForm(initial=request.GET, extra_fields=[
353 353 'range_date', 'tags', 'template'])
354 354 kwargs['keys'] = ['name', 'start_date', 'end_date', 'actions']
355 355 kwargs['title'] = 'Campaign'
356 356 kwargs['suptitle'] = 'List'
357 357 kwargs['no_sidebar'] = True
358 358 kwargs['form'] = form
359 359 kwargs['add_url'] = reverse('url_add_campaign')
360 360 filters.pop('page', None)
361 361 kwargs['q'] = urlencode(filters)
362 362 kwargs['menu_campaigns'] = 'active'
363 363
364 364 return render(request, 'base_list.html', kwargs)
365 365
366 366
367 367 def campaign(request, id_camp):
368 368
369 369 campaign = get_object_or_404(Campaign, pk=id_camp)
370 370 experiments = Experiment.objects.filter(campaign=campaign)
371 371
372 372 form = CampaignForm(instance=campaign)
373 373
374 374 kwargs = {}
375 375 kwargs['campaign'] = campaign
376 376 kwargs['campaign_keys'] = ['template', 'name',
377 377 'start_date', 'end_date', 'tags', 'description']
378 378
379 379 kwargs['experiments'] = experiments
380 380 kwargs['experiment_keys'] = [
381 381 'name', 'radar_system', 'start_time', 'end_time']
382 382
383 383 kwargs['title'] = 'Campaign'
384 384 kwargs['suptitle'] = 'Details'
385 385
386 386 kwargs['form'] = form
387 387 kwargs['button'] = 'Add Experiment'
388 388 kwargs['menu_campaigns'] = 'active'
389 389
390 390 return render(request, 'campaign.html', kwargs)
391 391
392 392
393 393 @login_required
394 394 def campaign_new(request):
395 395
396 396 kwargs = {}
397 397
398 398 if request.method == 'GET':
399 399
400 400 if 'template' in request.GET:
401 401 if request.GET['template'] == '0':
402 402 form = NewForm(initial={'create_from': 2},
403 403 template_choices=Campaign.objects.filter(template=True).values_list('id', 'name'))
404 404 else:
405 405 kwargs['button'] = 'Create'
406 406 kwargs['experiments'] = Configuration.objects.filter(
407 407 experiment=request.GET['template'])
408 408 kwargs['experiment_keys'] = ['name', 'start_time', 'end_time']
409 409 camp = Campaign.objects.get(pk=request.GET['template'])
410 410 form = CampaignForm(instance=camp,
411 411 initial={'name': '{}_{:%Y%m%d}'.format(camp.name, datetime.now()),
412 412 'template': False})
413 413 elif 'blank' in request.GET:
414 414 kwargs['button'] = 'Create'
415 415 form = CampaignForm()
416 416 else:
417 417 form = NewForm()
418 418
419 419 if request.method == 'POST':
420 420 kwargs['button'] = 'Create'
421 421 post = request.POST.copy()
422 422 experiments = []
423 423
424 424 for id_exp in post.getlist('experiments'):
425 425 exp = Experiment.objects.get(pk=id_exp)
426 426 new_exp = exp.clone(template=False)
427 427 experiments.append(new_exp)
428 428
429 429 post.setlist('experiments', [])
430 430
431 431 form = CampaignForm(post)
432 432
433 433 if form.is_valid():
434 434 campaign = form.save(commit=False)
435 435 campaign.author = request.user
436 436 for exp in experiments:
437 437 campaign.experiments.add(exp)
438 438 campaign.save()
439 439 return redirect('url_campaign', id_camp=campaign.id)
440 440
441 441 kwargs['form'] = form
442 442 kwargs['title'] = 'Campaign'
443 443 kwargs['suptitle'] = 'New'
444 444 kwargs['menu_campaigns'] = 'active'
445 445
446 446 return render(request, 'campaign_edit.html', kwargs)
447 447
448 448
449 449 @login_required
450 450 def campaign_edit(request, id_camp):
451 451
452 452 campaign = get_object_or_404(Campaign, pk=id_camp)
453 453
454 454 if request.method == 'GET':
455 455 form = CampaignForm(instance=campaign)
456 456
457 457 if request.method == 'POST':
458 458 exps = campaign.experiments.all().values_list('pk', flat=True)
459 459 post = request.POST.copy()
460 460 new_exps = post.getlist('experiments')
461 461 post.setlist('experiments', [])
462 462 form = CampaignForm(post, instance=campaign)
463 463
464 464 if form.is_valid():
465 465 camp = form.save()
466 466 for id_exp in new_exps:
467 467 if int(id_exp) in exps:
468 468 exps.pop(id_exp)
469 469 else:
470 470 exp = Experiment.objects.get(pk=id_exp)
471 471 if exp.template:
472 472 camp.experiments.add(exp.clone(template=False))
473 473 else:
474 474 camp.experiments.add(exp)
475 475
476 476 for id_exp in exps:
477 477 camp.experiments.remove(Experiment.objects.get(pk=id_exp))
478 478
479 479 return redirect('url_campaign', id_camp=id_camp)
480 480
481 481 kwargs = {}
482 482 kwargs['form'] = form
483 483 kwargs['title'] = 'Campaign'
484 484 kwargs['suptitle'] = 'Edit'
485 485 kwargs['button'] = 'Update'
486 486 kwargs['menu_campaigns'] = 'active'
487 487
488 488 return render(request, 'campaign_edit.html', kwargs)
489 489
490 490
491 491 @login_required
492 492 def campaign_delete(request, id_camp):
493 493
494 494 campaign = get_object_or_404(Campaign, pk=id_camp)
495 495
496 496 if request.method == 'POST':
497 497 if is_developer(request.user):
498 498
499 499 for exp in campaign.experiments.all():
500 500 for conf in Configuration.objects.filter(experiment=exp):
501 501 conf.delete()
502 502 exp.delete()
503 503 campaign.delete()
504 504
505 505 return redirect('url_campaigns')
506 506
507 507 messages.error(request, 'Not enough permission to delete this object')
508 508 return redirect(campaign.get_absolute_url())
509 509
510 510 kwargs = {
511 511 'title': 'Delete',
512 512 'suptitle': 'Campaign',
513 513 'object': campaign,
514 514 'delete': True
515 515 }
516 516 kwargs['menu_campaigns'] = 'active'
517 517
518 518 return render(request, 'confirm.html', kwargs)
519 519
520 520
521 521 @login_required
522 522 def campaign_export(request, id_camp):
523 523
524 524 campaign = get_object_or_404(Campaign, pk=id_camp)
525 525 content = campaign.parms_to_dict()
526 526 content_type = 'application/json'
527 527 filename = '%s_%s.json' % (campaign.name, campaign.id)
528 528
529 529 response = HttpResponse(content_type=content_type)
530 530 response['Content-Disposition'] = 'attachment; filename="%s"' % filename
531 531 response.write(json.dumps(content, indent=2))
532 532
533 533 return response
534 534
535 535
536 536 @login_required
537 537 def campaign_import(request, id_camp):
538 538
539 539 campaign = get_object_or_404(Campaign, pk=id_camp)
540 540
541 541 if request.method == 'GET':
542 542 file_form = UploadFileForm()
543 543
544 544 if request.method == 'POST':
545 545 file_form = UploadFileForm(request.POST, request.FILES)
546 546
547 547 if file_form.is_valid():
548 548 new_camp = campaign.dict_to_parms(
549 549 json.load(request.FILES['file']), CONF_MODELS)
550 550 messages.success(
551 551 request, "Parameters imported from: '%s'." % request.FILES['file'].name)
552 552 return redirect(new_camp.get_absolute_url_edit())
553 553
554 554 messages.error(request, "Could not import parameters from file")
555 555
556 556 kwargs = {}
557 557 kwargs['title'] = 'Campaign'
558 558 kwargs['form'] = file_form
559 559 kwargs['suptitle'] = 'Importing file'
560 560 kwargs['button'] = 'Import'
561 561 kwargs['menu_campaigns'] = 'active'
562 562
563 563 return render(request, 'campaign_import.html', kwargs)
564 564
565 565
566 566 def experiments(request):
567 567
568 568 page = request.GET.get('page')
569 569 order = ('location',)
570 570 filters = request.GET.copy()
571 571
572 572 if 'my experiments' in filters:
573 573 filters.pop('my experiments', None)
574 574 filters['mine'] = request.user.id
575 575
576 576 kwargs = get_paginator(Experiment, page, order, filters)
577 577
578 578 fields = ['tags', 'template']
579 579 if request.user.is_authenticated:
580 580 fields.append('my experiments')
581 581
582 582 form = FilterForm(initial=request.GET, extra_fields=fields)
583 583
584 584 kwargs['keys'] = ['name', 'radar_system',
585 585 'start_time', 'end_time', 'actions']
586 586 kwargs['title'] = 'Experiment'
587 587 kwargs['suptitle'] = 'List'
588 588 kwargs['no_sidebar'] = True
589 589 kwargs['form'] = form
590 590 kwargs['add_url'] = reverse('url_add_experiment')
591 591 filters = request.GET.copy()
592 592 filters.pop('page', None)
593 593 kwargs['q'] = urlencode(filters)
594 594 kwargs['menu_experiments'] = 'active'
595 595
596 596 return render(request, 'base_list.html', kwargs)
597 597
598 598
599 599 def experiment(request, id_exp):
600 600
601 601 experiment = get_object_or_404(Experiment, pk=id_exp)
602 602
603 603 configurations = Configuration.objects.filter(
604 604 experiment=experiment, type=0)
605 605
606 606 kwargs = {}
607 607
608 608 kwargs['experiment_keys'] = ['template', 'radar_system',
609 609 'name', 'freq', 'start_time', 'end_time']
610 610 kwargs['experiment'] = experiment
611 611 kwargs['configuration_keys'] = ['name', 'device__ip_address',
612 612 'device__port_address', 'device__status']
613 613 kwargs['configurations'] = configurations
614 614 kwargs['title'] = 'Experiment'
615 615 kwargs['suptitle'] = 'Details'
616 616 kwargs['button'] = 'Add Configuration'
617 617 kwargs['menu_experiments'] = 'active'
618 618
619 619 ###### SIDEBAR ######
620 620 kwargs.update(sidebar(experiment=experiment))
621 621
622 622 return render(request, 'experiment.html', kwargs)
623 623
624 624
625 625 @login_required
626 626 def experiment_new(request, id_camp=None):
627 627
628 628 if not is_developer(request.user):
629 629 messages.error(
630 630 request, 'Developer required, to create new Experiments')
631 631 return redirect('index')
632 632 kwargs = {}
633 633
634 634 if request.method == 'GET':
635 635 if 'template' in request.GET:
636 636 if request.GET['template'] == '0':
637 637 form = NewForm(initial={'create_from': 2},
638 638 template_choices=Experiment.objects.filter(template=True).values_list('id', 'name'))
639 639 else:
640 640 kwargs['button'] = 'Create'
641 641 kwargs['configurations'] = Configuration.objects.filter(
642 642 experiment=request.GET['template'])
643 643 kwargs['configuration_keys'] = ['name', 'device__name',
644 644 'device__ip_address', 'device__port_address']
645 645 exp = Experiment.objects.get(pk=request.GET['template'])
646 646 form = ExperimentForm(instance=exp,
647 647 initial={'name': '{}_{:%y%m%d}'.format(exp.name, datetime.now()),
648 648 'template': False})
649 649 elif 'blank' in request.GET:
650 650 kwargs['button'] = 'Create'
651 651 form = ExperimentForm()
652 652 else:
653 653 form = NewForm()
654 654
655 655 if request.method == 'POST':
656 656 form = ExperimentForm(request.POST)
657 657 if form.is_valid():
658 658 experiment = form.save(commit=False)
659 659 experiment.author = request.user
660 660 experiment.save()
661 661
662 662 if 'template' in request.GET:
663 663 configurations = Configuration.objects.filter(
664 664 experiment=request.GET['template'], type=0)
665 665 for conf in configurations:
666 666 conf.clone(experiment=experiment, template=False)
667 667
668 668 return redirect('url_experiment', id_exp=experiment.id)
669 669
670 670 kwargs['form'] = form
671 671 kwargs['title'] = 'Experiment'
672 672 kwargs['suptitle'] = 'New'
673 673 kwargs['menu_experiments'] = 'active'
674 674
675 675 return render(request, 'experiment_edit.html', kwargs)
676 676
677 677
678 678 @login_required
679 679 def experiment_edit(request, id_exp):
680 680
681 681 experiment = get_object_or_404(Experiment, pk=id_exp)
682 682
683 683 if request.method == 'GET':
684 684 form = ExperimentForm(instance=experiment)
685 685
686 686 if request.method == 'POST':
687 687 form = ExperimentForm(request.POST, instance=experiment)
688 688
689 689 if form.is_valid():
690 690 experiment = form.save()
691 691 return redirect('url_experiment', id_exp=experiment.id)
692 692
693 693 kwargs = {}
694 694 kwargs['form'] = form
695 695 kwargs['title'] = 'Experiment'
696 696 kwargs['suptitle'] = 'Edit'
697 697 kwargs['button'] = 'Update'
698 698 kwargs['menu_experiments'] = 'active'
699 699
700 700 return render(request, 'experiment_edit.html', kwargs)
701 701
702 702
703 703 @login_required
704 704 def experiment_delete(request, id_exp):
705 705
706 706 experiment = get_object_or_404(Experiment, pk=id_exp)
707 707
708 708 if request.method == 'POST':
709 709 if is_developer(request.user):
710 710 for conf in Configuration.objects.filter(experiment=experiment):
711 711 conf.delete()
712 712 experiment.delete()
713 713 return redirect('url_experiments')
714 714
715 715 messages.error(request, 'Not enough permission to delete this object')
716 716 return redirect(experiment.get_absolute_url())
717 717
718 718 kwargs = {
719 719 'title': 'Delete',
720 720 'suptitle': 'Experiment',
721 721 'object': experiment,
722 722 'delete': True
723 723 }
724 724
725 725 return render(request, 'confirm.html', kwargs)
726 726
727 727
728 728 @login_required
729 729 def experiment_export(request, id_exp):
730 730
731 731 experiment = get_object_or_404(Experiment, pk=id_exp)
732 732 content = experiment.parms_to_dict()
733 733 content_type = 'application/json'
734 734 filename = '%s_%s.json' % (experiment.name, experiment.id)
735 735
736 736 response = HttpResponse(content_type=content_type)
737 737 response['Content-Disposition'] = 'attachment; filename="%s"' % filename
738 738 response.write(json.dumps(content, indent=2))
739 739
740 740 return response
741 741
742 742
743 743 @login_required
744 744 def experiment_import(request, id_exp):
745 745
746 746 experiment = get_object_or_404(Experiment, pk=id_exp)
747 747 configurations = Configuration.objects.filter(experiment=experiment)
748 748
749 749 if request.method == 'GET':
750 750 file_form = UploadFileForm()
751 751
752 752 if request.method == 'POST':
753 753 file_form = UploadFileForm(request.POST, request.FILES)
754 754
755 755 if file_form.is_valid():
756 756 new_exp = experiment.dict_to_parms(
757 757 json.load(request.FILES['file']), CONF_MODELS)
758 758 messages.success(
759 759 request, "Parameters imported from: '%s'." % request.FILES['file'].name)
760 760 return redirect(new_exp.get_absolute_url_edit())
761 761
762 762 messages.error(request, "Could not import parameters from file")
763 763
764 764 kwargs = {}
765 765 kwargs['title'] = 'Experiment'
766 766 kwargs['form'] = file_form
767 767 kwargs['suptitle'] = 'Importing file'
768 768 kwargs['button'] = 'Import'
769 769 kwargs['menu_experiments'] = 'active'
770 770
771 771 kwargs.update(sidebar(experiment=experiment))
772 772
773 773 return render(request, 'experiment_import.html', kwargs)
774 774
775 775
776 776 @login_required
777 777 def experiment_start(request, id_exp):
778 778
779 779 exp = get_object_or_404(Experiment, pk=id_exp)
780 780
781 781 if exp.status == 2:
782 782 messages.warning(request, 'Experiment {} already runnnig'.format(exp))
783 783 else:
784 784 exp.status = exp.start()
785 785 if exp.status == 0:
786 786 messages.error(request, 'Experiment {} not start'.format(exp))
787 787 if exp.status == 2:
788 788 messages.success(request, 'Experiment {} started'.format(exp))
789 789
790 790 exp.save()
791 791
792 792 return redirect(exp.get_absolute_url())
793 793
794 794
795 795 @login_required
796 796 def experiment_stop(request, id_exp):
797 797
798 798 exp = get_object_or_404(Experiment, pk=id_exp)
799 799
800 800 if exp.status == 2:
801 801 exp.status = exp.stop()
802 802 exp.save()
803 803 messages.success(request, 'Experiment {} stopped'.format(exp))
804 804 else:
805 805 messages.error(request, 'Experiment {} not running'.format(exp))
806 806
807 807 return redirect(exp.get_absolute_url())
808 808
809 809
810 810 def experiment_status(request, id_exp):
811 811
812 812 exp = get_object_or_404(Experiment, pk=id_exp)
813 813
814 814 exp.get_status()
815 815
816 816 return redirect(exp.get_absolute_url())
817 817
818 818
819 819 @login_required
820 820 def experiment_mix(request, id_exp):
821 821
822 822 experiment = get_object_or_404(Experiment, pk=id_exp)
823 823 rc_confs = [conf for conf in RCConfiguration.objects.filter(
824 824 experiment=id_exp,
825 825 type=0,
826 826 mix=False)]
827 827
828 828 if len(rc_confs) < 2:
829 829 messages.warning(
830 830 request, 'You need at least two RC Configurations to make a mix')
831 831 return redirect(experiment.get_absolute_url())
832 832
833 833 mix_confs = RCConfiguration.objects.filter(experiment=id_exp, mix=True, type=0)
834 834
835 835 if mix_confs:
836 836 mix = mix_confs[0]
837 837 else:
838 838 mix = RCConfiguration(experiment=experiment,
839 839 device=rc_confs[0].device,
840 840 ipp=rc_confs[0].ipp,
841 841 clock_in=rc_confs[0].clock_in,
842 842 clock_divider=rc_confs[0].clock_divider,
843 843 mix=True,
844 844 parameters='')
845 845 mix.save()
846 846
847 847 line_type = RCLineType.objects.get(name='mix')
848 848 for i in range(len(rc_confs[0].get_lines())):
849 849 line = RCLine(rc_configuration=mix, line_type=line_type, channel=i)
850 850 line.save()
851 851
852 852 initial = {'name': mix.name,
853 853 'result': parse_mix_result(mix.parameters),
854 854 'delay': 0,
855 855 'mask': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
856 856 }
857 857
858 858 if request.method == 'GET':
859 859 form = RCMixConfigurationForm(confs=rc_confs, initial=initial)
860 860
861 861 if request.method == 'POST':
862 862 result = mix.parameters
863 863
864 864 if '{}|'.format(request.POST['experiment']) in result:
865 865 messages.error(request, 'Configuration already added')
866 866 else:
867 867 if 'operation' in request.POST:
868 868 operation = MIX_OPERATIONS[request.POST['operation']]
869 869 else:
870 870 operation = ' '
871 871
872 872 mode = MIX_MODES[request.POST['mode']]
873 873
874 874 if result:
875 875 result = '{}-{}|{}|{}|{}|{}'.format(mix.parameters,
876 876 request.POST['experiment'],
877 877 mode,
878 878 operation,
879 879 float(
880 880 request.POST['delay']),
881 881 parse_mask(
882 882 request.POST.getlist('mask'))
883 883 )
884 884 else:
885 885 result = '{}|{}|{}|{}|{}'.format(request.POST['experiment'],
886 886 mode,
887 887 operation,
888 888 float(request.POST['delay']),
889 889 parse_mask(
890 890 request.POST.getlist('mask'))
891 891 )
892 892
893 893 mix.parameters = result
894 894 mix.save()
895 895 mix.update_pulses()
896 896
897 897 initial['result'] = parse_mix_result(result)
898 898 initial['name'] = mix.name
899 899
900 900 form = RCMixConfigurationForm(initial=initial, confs=rc_confs)
901 901
902 902 kwargs = {
903 903 'title': 'Experiment',
904 904 'suptitle': 'Mix Configurations',
905 905 'form': form,
906 906 'extra_button': 'Delete',
907 907 'button': 'Add',
908 908 'cancel': 'Back',
909 909 'previous': experiment.get_absolute_url(),
910 910 'id_exp': id_exp,
911 911
912 912 }
913 913 kwargs['menu_experiments'] = 'active'
914 914
915 915 return render(request, 'experiment_mix.html', kwargs)
916 916
917 917
918 918 @login_required
919 919 def experiment_mix_delete(request, id_exp):
920 920
921 921 conf = RCConfiguration.objects.get(experiment=id_exp, mix=True, type=0)
922 922 values = conf.parameters.split('-')
923 923 conf.parameters = '-'.join(values[:-1])
924 924 conf.save()
925 925
926 926 return redirect('url_mix_experiment', id_exp=id_exp)
927 927
928 928
929 929 def experiment_summary(request, id_exp):
930 930
931 931 experiment = get_object_or_404(Experiment, pk=id_exp)
932 932 configurations = Configuration.objects.filter(
933 933 experiment=experiment, type=0)
934 934
935 935 kwargs = {}
936 936 kwargs['experiment_keys'] = ['radar_system',
937 937 'name', 'freq', 'start_time', 'end_time']
938 938 kwargs['experiment'] = experiment
939 939 kwargs['configurations'] = []
940 940 kwargs['title'] = 'Experiment Summary'
941 941 kwargs['suptitle'] = 'Details'
942 942 kwargs['button'] = 'Verify Parameters'
943 943
944 944 c_vel = 3.0*(10**8) # m/s
945 945 ope_freq = experiment.freq*(10**6) # 1/s
946 946 radar_lambda = c_vel/ope_freq # m
947 947 kwargs['radar_lambda'] = radar_lambda
948 948
949 949 ipp = None
950 950 nsa = 1
951 951 code_id = 0
952 952 tx_line = {}
953 953
954 954 for configuration in configurations.filter(device__device_type__name = 'rc'):
955 955
956 956 if configuration.mix:
957 957 continue
958 958 conf = {'conf': configuration}
959 959 conf['keys'] = []
960 960 conf['NTxs'] = configuration.ntx
961 961 conf['keys'].append('NTxs')
962 962 ipp = configuration.ipp
963 963 conf['IPP'] = ipp
964 964 conf['keys'].append('IPP')
965 965 lines = configuration.get_lines(line_type__name='tx')
966 966
967 967 for tx_line in lines:
968 968 tx_params = json.loads(tx_line.params)
969 969 conf[tx_line.get_name()] = '{} Km'.format(tx_params['pulse_width'])
970 970 conf['keys'].append(tx_line.get_name())
971 971 delays = tx_params['delays']
972 972 if delays not in ('', '0'):
973 973 n = len(delays.split(','))
974 974 taus = '{} Taus: {}'.format(n, delays)
975 975 else:
976 976 taus = '-'
977 977 conf['Taus ({})'.format(tx_line.get_name())] = taus
978 978 conf['keys'].append('Taus ({})'.format(tx_line.get_name()))
979 979 for code_line in configuration.get_lines(line_type__name='codes'):
980 980 code_params = json.loads(code_line.params)
981 981 code_id = code_params['code']
982 982 if tx_line.pk == int(code_params['TX_ref']):
983 983 conf['Code ({})'.format(tx_line.get_name())] = '{}:{}'.format(RCLineCode.objects.get(pk=code_params['code']),
984 984 '-'.join(code_params['codes']))
985 985 conf['keys'].append('Code ({})'.format(tx_line.get_name()))
986 986
987 987 for windows_line in configuration.get_lines(line_type__name='windows'):
988 988 win_params = json.loads(windows_line.params)
989 989 if tx_line.pk == int(win_params['TX_ref']):
990 990 windows = ''
991 991 nsa = win_params['params'][0]['number_of_samples']
992 992 for i, params in enumerate(win_params['params']):
993 993 windows += 'W{}: Ho={first_height} km DH={resolution} km NSA={number_of_samples}<br>'.format(
994 994 i, **params)
995 995 conf['Window'] = mark_safe(windows)
996 996 conf['keys'].append('Window')
997 997
998 998 kwargs['configurations'].append(conf)
999 999
1000 1000 for configuration in configurations.filter(device__device_type__name = 'jars'):
1001 1001
1002 1002 conf = {'conf': configuration}
1003 1003 conf['keys'] = []
1004 1004 conf['Type of Data'] = EXPERIMENT_TYPE[configuration.exp_type][1]
1005 1005 conf['keys'].append('Type of Data')
1006 1006 channels_number = configuration.channels_number
1007 1007 exp_type = configuration.exp_type
1008 1008 fftpoints = configuration.fftpoints
1009 1009 filter_parms = json.loads(configuration.filter_parms)
1010 1010 spectral_number = configuration.spectral_number
1011 1011 acq_profiles = configuration.acq_profiles
1012 1012 cohe_integr = configuration.cohe_integr
1013 1013 profiles_block = configuration.profiles_block
1014 1014
1015 1015 conf['Num of Profiles'] = acq_profiles
1016 1016 conf['keys'].append('Num of Profiles')
1017 1017
1018 1018 conf['Prof per Block'] = profiles_block
1019 1019 conf['keys'].append('Prof per Block')
1020 1020
1021 1021 conf['Blocks per File'] = configuration.raw_data_blocks
1022 1022 conf['keys'].append('Blocks per File')
1023 1023
1024 1024 if exp_type == 0: # Short
1025 1025 bytes_ = 2
1026 1026 b = nsa*2*bytes_*channels_number
1027 1027 else: # Float
1028 1028 bytes_ = 4
1029 1029 channels = channels_number + spectral_number
1030 1030 b = nsa*2*bytes_*fftpoints*channels
1031 1031
1032 1032 codes_num = 7
1033 1033 if code_id == 2:
1034 1034 codes_num = 7
1035 1035 elif code_id == 12:
1036 1036 codes_num = 15
1037 1037
1038 1038 #Jars filter values:
1039 1039
1040 1040 clock = float(filter_parms['clock'])
1041 1041 filter_2 = int(filter_parms['cic_2'])
1042 1042 filter_5 = int(filter_parms['cic_5'])
1043 1043 filter_fir = int(filter_parms['fir'])
1044 1044 Fs_MHz = clock/(filter_2*filter_5*filter_fir)
1045 1045
1046 1046 #Jars values:
1047 1047 if ipp is not None:
1048 1048 IPP_units = ipp/0.15*Fs_MHz
1049 1049 IPP_us = IPP_units / Fs_MHz
1050 1050 IPP_s = IPP_units / (Fs_MHz * (10**6))
1051 1051 Ts = 1/(Fs_MHz*(10**6))
1052 1052
1053 1053 Va = radar_lambda/(4*Ts*cohe_integr)
1054 1054 rate_bh = ((nsa-codes_num)*channels_number*2 *
1055 1055 bytes_/IPP_us)*(36*(10**8)/cohe_integr)
1056 1056 rate_gh = rate_bh/(1024*1024*1024)
1057 1057
1058 1058 conf['Time per Block'] = IPP_s * profiles_block * cohe_integr
1059 1059 conf['keys'].append('Time per Block')
1060 1060 conf['Acq time'] = IPP_s * acq_profiles
1061 1061 conf['keys'].append('Acq time')
1062 1062 conf['Data rate'] = str(rate_gh)+" (GB/h)"
1063 1063 conf['keys'].append('Data rate')
1064 1064 conf['Va (m/s)'] = Va
1065 1065 conf['keys'].append('Va (m/s)')
1066 1066 conf['Vrange (m/s)'] = 3/(2*IPP_s*cohe_integr)
1067 1067 conf['keys'].append('Vrange (m/s)')
1068 1068
1069 1069 kwargs['configurations'].append(conf)
1070 1070 kwargs['menu_experiments'] = 'active'
1071 1071
1072 1072 ###### SIDEBAR ######
1073 1073 kwargs.update(sidebar(experiment=experiment))
1074 1074
1075 1075 return render(request, 'experiment_summary.html', kwargs)
1076 1076
1077 1077
1078 1078 @login_required
1079 1079 def experiment_verify(request, id_exp):
1080 1080
1081 1081 experiment = get_object_or_404(Experiment, pk=id_exp)
1082 1082 experiment_data = experiment.parms_to_dict()
1083 1083 configurations = Configuration.objects.filter(
1084 1084 experiment=experiment, type=0)
1085 1085
1086 1086 kwargs = {}
1087 1087
1088 1088 kwargs['experiment_keys'] = ['template',
1089 1089 'radar_system', 'name', 'start_time', 'end_time']
1090 1090 kwargs['experiment'] = experiment
1091 1091
1092 1092 kwargs['configuration_keys'] = ['name', 'device__ip_address',
1093 1093 'device__port_address', 'device__status']
1094 1094 kwargs['configurations'] = configurations
1095 1095 kwargs['experiment_data'] = experiment_data
1096 1096
1097 1097 kwargs['title'] = 'Verify Experiment'
1098 1098 kwargs['suptitle'] = 'Parameters'
1099 1099
1100 1100 kwargs['button'] = 'Update'
1101 1101
1102 1102 jars_conf = False
1103 1103 rc_conf = False
1104 1104 dds_conf = False
1105 1105
1106 1106 for configuration in configurations:
1107 1107 #-------------------- JARS -----------------------:
1108 1108 if configuration.device.device_type.name == 'jars':
1109 1109 jars_conf = True
1110 1110 jars = configuration
1111 1111 kwargs['jars_conf'] = jars_conf
1112 1112 filter_parms = json.loads(jars.filter_parms)
1113 1113 kwargs['filter_parms'] = filter_parms
1114 1114 #--Sampling Frequency
1115 1115 clock = filter_parms['clock']
1116 1116 filter_2 = filter_parms['cic_2']
1117 1117 filter_5 = filter_parms['cic_5']
1118 1118 filter_fir = filter_parms['fir']
1119 1119 samp_freq_jars = clock/filter_2/filter_5/filter_fir
1120 1120
1121 1121 kwargs['samp_freq_jars'] = samp_freq_jars
1122 1122 kwargs['jars'] = configuration
1123 1123
1124 1124 #--------------------- RC ----------------------:
1125 1125 if configuration.device.device_type.name == 'rc' and not configuration.mix:
1126 1126 rc_conf = True
1127 1127 rc = configuration
1128 1128
1129 1129 rc_parms = configuration.parms_to_dict()
1130 1130
1131 1131 win_lines = rc.get_lines(line_type__name='windows')
1132 1132 if win_lines:
1133 1133 dh = json.loads(win_lines[0].params)['params'][0]['resolution']
1134 1134 #--Sampling Frequency
1135 1135 samp_freq_rc = 0.15/dh
1136 1136 kwargs['samp_freq_rc'] = samp_freq_rc
1137 1137
1138 1138 kwargs['rc_conf'] = rc_conf
1139 1139 kwargs['rc'] = configuration
1140 1140
1141 1141 #-------------------- DDS ----------------------:
1142 1142 if configuration.device.device_type.name == 'dds':
1143 1143 dds_conf = True
1144 1144 dds = configuration
1145 1145 dds_parms = configuration.parms_to_dict()
1146 1146
1147 1147 kwargs['dds_conf'] = dds_conf
1148 1148 kwargs['dds'] = configuration
1149 1149
1150 1150 #------------Validation------------:
1151 1151 #Clock
1152 1152 if dds_conf and rc_conf and jars_conf:
1153 1153 if float(filter_parms['clock']) != float(rc_parms['configurations']['byId'][str(rc.pk)]['clock_in']) and float(rc_parms['configurations']['byId'][str(rc.pk)]['clock_in']) != float(dds_parms['configurations']['byId'][str(dds.pk)]['clock']):
1154 1154 messages.warning(request, "Devices don't have the same clock.")
1155 1155 elif rc_conf and jars_conf:
1156 1156 if float(filter_parms['clock']) != float(rc_parms['configurations']['byId'][str(rc.pk)]['clock_in']):
1157 1157 messages.warning(request, "Devices don't have the same clock.")
1158 1158 elif rc_conf and dds_conf:
1159 1159 if float(rc_parms['configurations']['byId'][str(rc.pk)]['clock_in']) != float(dds_parms['configurations']['byId'][str(dds.pk)]['clock']):
1160 1160 messages.warning(request, "Devices don't have the same clock.")
1161 1161 if float(samp_freq_rc) != float(dds_parms['configurations']['byId'][str(dds.pk)]['frequencyA']):
1162 1162 messages.warning(
1163 1163 request, "Devices don't have the same Frequency A.")
1164 1164
1165 1165 #------------POST METHOD------------:
1166 1166 if request.method == 'POST':
1167 1167 if request.POST['suggest_clock']:
1168 1168 try:
1169 1169 suggest_clock = float(request.POST['suggest_clock'])
1170 1170 except:
1171 1171 messages.warning(request, "Invalid value in CLOCK IN.")
1172 1172 return redirect('url_verify_experiment', id_exp=experiment.id)
1173 1173 else:
1174 1174 suggest_clock = ""
1175 1175 if suggest_clock:
1176 1176 if rc_conf:
1177 1177 rc.clock_in = suggest_clock
1178 1178 rc.save()
1179 1179 if jars_conf:
1180 1180 filter_parms = jars.filter_parms
1181 1181 filter_parms = ast.literal_eval(filter_parms)
1182 1182 filter_parms['clock'] = suggest_clock
1183 1183 jars.filter_parms = json.dumps(filter_parms)
1184 1184 jars.save()
1185 1185 kwargs['filter_parms'] = filter_parms
1186 1186 if dds_conf:
1187 1187 dds.clock = suggest_clock
1188 1188 dds.save()
1189 1189
1190 1190 if request.POST['suggest_frequencyA']:
1191 1191 try:
1192 1192 suggest_frequencyA = float(request.POST['suggest_frequencyA'])
1193 1193 except:
1194 1194 messages.warning(request, "Invalid value in FREQUENCY A.")
1195 1195 return redirect('url_verify_experiment', id_exp=experiment.id)
1196 1196 else:
1197 1197 suggest_frequencyA = ""
1198 1198 if suggest_frequencyA:
1199 1199 if jars_conf:
1200 1200 filter_parms = jars.filter_parms
1201 1201 filter_parms = ast.literal_eval(filter_parms)
1202 1202 filter_parms['fch'] = suggest_frequencyA
1203 1203 jars.filter_parms = json.dumps(filter_parms)
1204 1204 jars.save()
1205 1205 kwargs['filter_parms'] = filter_parms
1206 1206 if dds_conf:
1207 1207 dds.frequencyA_Mhz = request.POST['suggest_frequencyA']
1208 1208 dds.save()
1209 1209
1210 1210 kwargs['menu_experiments'] = 'active'
1211 1211 kwargs.update(sidebar(experiment=experiment))
1212 1212 return render(request, 'experiment_verify.html', kwargs)
1213 1213
1214 1214
1215 1215 def parse_mix_result(s):
1216 1216
1217 1217 values = s.split('-')
1218 1218 html = 'EXP MOD OPE DELAY MASK\r\n'
1219 1219
1220 1220 if not values or values[0] in ('', ' '):
1221 1221 return mark_safe(html)
1222 1222
1223 1223 for i, value in enumerate(values):
1224 1224 if not value:
1225 1225 continue
1226 1226 pk, mode, operation, delay, mask = value.split('|')
1227 1227 conf = RCConfiguration.objects.get(pk=pk)
1228 1228 if i == 0:
1229 1229 html += '{:20.18}{:3}{:4}{:9}km{:>6}\r\n'.format(
1230 1230 conf.name,
1231 1231 mode,
1232 1232 ' ',
1233 1233 delay,
1234 1234 mask)
1235 1235 else:
1236 1236 html += '{:20.18}{:3}{:4}{:9}km{:>6}\r\n'.format(
1237 1237 conf.name,
1238 1238 mode,
1239 1239 operation,
1240 1240 delay,
1241 1241 mask)
1242 1242
1243 1243 return mark_safe(html)
1244 1244
1245 1245
1246 1246 def parse_mask(l):
1247 1247
1248 1248 values = []
1249 1249
1250 1250 for x in range(16):
1251 1251 if '{}'.format(x) in l:
1252 1252 values.append(1)
1253 1253 else:
1254 1254 values.append(0)
1255 1255
1256 1256 values.reverse()
1257 1257
1258 1258 return int(''.join([str(x) for x in values]), 2)
1259 1259
1260 1260
1261 1261 def dev_confs(request):
1262 1262
1263 1263 page = request.GET.get('page')
1264 1264 order = ('programmed_date', )
1265 1265 filters = request.GET.copy()
1266 1266 if 'my configurations' in filters:
1267 1267 filters.pop('my configurations', None)
1268 1268 filters['mine'] = request.user.id
1269 1269 kwargs = get_paginator(Configuration, page, order, filters)
1270 1270 fields = ['tags', 'template', 'historical']
1271 1271 if request.user.is_authenticated:
1272 1272 fields.append('my configurations')
1273 1273 form = FilterForm(initial=request.GET, extra_fields=fields)
1274 1274 kwargs['keys'] = ['name', 'experiment',
1275 1275 'type', 'programmed_date', 'actions']
1276 1276 kwargs['title'] = 'Configuration'
1277 1277 kwargs['suptitle'] = 'List'
1278 1278 kwargs['no_sidebar'] = True
1279 1279 kwargs['form'] = form
1280 1280 kwargs['add_url'] = reverse('url_add_dev_conf', args=[0])
1281 1281 filters = request.GET.copy()
1282 1282 filters.pop('page', None)
1283 1283 kwargs['q'] = urlencode(filters)
1284 1284 kwargs['menu_configurations'] = 'active'
1285 1285
1286 1286 return render(request, 'base_list.html', kwargs)
1287 1287
1288 1288
1289 1289 def dev_conf(request, id_conf):
1290 1290
1291 1291 conf = get_object_or_404(Configuration, pk=id_conf)
1292 1292
1293 1293 return redirect(conf.get_absolute_url())
1294 1294
1295 1295
1296 1296 @login_required
1297 1297 def dev_conf_new(request, id_exp=0, id_dev=0):
1298 1298
1299 1299 if not is_developer(request.user):
1300 1300 messages.error(
1301 1301 request, 'Developer required, to create new configurations')
1302 1302 return redirect('index')
1303 1303
1304 1304 initial = {}
1305 1305 kwargs = {}
1306 1306
1307 1307 if id_exp != 0:
1308 1308 initial['experiment'] = id_exp
1309 1309
1310 1310 if id_dev != 0:
1311 1311 initial['device'] = id_dev
1312 1312
1313 1313 if request.method == 'GET':
1314 1314
1315 1315 if id_dev:
1316 1316 kwargs['button'] = 'Create'
1317 1317 device = Device.objects.get(pk=id_dev)
1318 1318 DevConfForm = CONF_FORMS[device.device_type.name]
1319 1319 initial['name'] = request.GET['name']
1320 1320 form = DevConfForm(initial=initial)
1321 1321 else:
1322 1322 if 'template' in request.GET:
1323 1323 if request.GET['template'] == '0':
1324 1324 choices = [(conf.pk, '{}'.format(conf))
1325 1325 for conf in Configuration.objects.filter(template=True)]
1326 1326 form = NewForm(initial={'create_from': 2},
1327 1327 template_choices=choices)
1328 1328 else:
1329 1329 kwargs['button'] = 'Create'
1330 1330 conf = Configuration.objects.get(
1331 1331 pk=request.GET['template'])
1332 1332 id_dev = conf.device.pk
1333 1333 DevConfForm = CONF_FORMS[conf.device.device_type.name]
1334 1334 form = DevConfForm(instance=conf,
1335 1335 initial={'name': '{}_{:%y%m%d}'.format(conf.name, datetime.now()),
1336 1336 'template': False,
1337 1337 'experiment': id_exp})
1338 1338 elif 'blank' in request.GET:
1339 1339 kwargs['button'] = 'Create'
1340 1340 form = ConfigurationForm(initial=initial)
1341 1341 else:
1342 1342 form = NewForm()
1343 1343
1344 1344 if request.method == 'POST':
1345 1345
1346 1346 device = Device.objects.get(pk=request.POST['device'])
1347 1347 DevConfForm = CONF_FORMS[device.device_type.name]
1348 1348
1349 1349 form = DevConfForm(request.POST)
1350 1350 kwargs['button'] = 'Create'
1351 1351 if form.is_valid():
1352 1352 conf = form.save(commit=False)
1353 1353 conf.author = request.user
1354 1354 conf.save()
1355 1355
1356 1356 if 'template' in request.GET and conf.device.device_type.name == 'rc':
1357 1357 lines = RCLine.objects.filter(
1358 1358 rc_configuration=request.GET['template'])
1359 1359 for line in lines:
1360 1360 line.clone(rc_configuration=conf)
1361 1361
1362 1362 new_lines = conf.get_lines()
1363 1363 for line in new_lines:
1364 1364 line_params = json.loads(line.params)
1365 1365 if 'TX_ref' in line_params:
1366 1366 ref_line = RCLine.objects.get(pk=line_params['TX_ref'])
1367 1367 line_params['TX_ref'] = ['{}'.format(
1368 1368 l.pk) for l in new_lines if l.get_name() == ref_line.get_name()][0]
1369 1369 line.params = json.dumps(line_params)
1370 1370 line.save()
1371 elif conf.device.device_type.name == 'rc':
1372 clk = RCClock(rc_configuration=conf)
1373 clk.save()
1371 1374
1372 1375 return redirect('url_dev_conf', id_conf=conf.pk)
1373 1376
1374 1377 kwargs['id_exp'] = id_exp
1375 1378 kwargs['form'] = form
1376 1379 kwargs['title'] = 'Configuration'
1377 1380 kwargs['suptitle'] = 'New'
1378 1381 kwargs['menu_configurations'] = 'active'
1379 1382
1380 1383 if id_dev != 0:
1381 1384 device = Device.objects.get(pk=id_dev)
1382 1385 kwargs['device'] = device.device_type.name
1383 1386
1384 1387 return render(request, 'dev_conf_edit.html', kwargs)
1385 1388
1386 1389
1387 1390 @login_required
1388 1391 def dev_conf_edit(request, id_conf):
1389 1392
1390 1393 conf = get_object_or_404(Configuration, pk=id_conf)
1391 1394
1392 1395 DevConfForm = CONF_FORMS[conf.device.device_type.name]
1393 1396
1394 1397 if request.method == 'GET':
1395 1398 form = DevConfForm(instance=conf)
1396 1399
1397 1400 if request.method == 'POST':
1398 1401 form = DevConfForm(request.POST, instance=conf)
1399 1402
1400 1403 if form.is_valid():
1401 1404 form.save()
1402 1405 return redirect('url_dev_conf', id_conf=id_conf)
1403 1406
1404 1407 kwargs = {}
1405 1408 kwargs['form'] = form
1406 1409 kwargs['title'] = 'Device Configuration'
1407 1410 kwargs['suptitle'] = 'Edit'
1408 1411 kwargs['button'] = 'Update'
1409 1412 kwargs['menu_configurations'] = 'active'
1410 1413
1411 1414 ###### SIDEBAR ######
1412 1415 kwargs.update(sidebar(conf=conf))
1413 1416
1414 1417 return render(request, '%s_conf_edit.html' % conf.device.device_type.name, kwargs)
1415 1418
1416 1419
1417 1420 @login_required
1418 1421 def dev_conf_start(request, id_conf):
1419 1422
1420 1423 conf = get_object_or_404(Configuration, pk=id_conf)
1421 1424
1422 1425 if conf.start_device():
1423 1426 messages.success(request, conf.message)
1424 1427 else:
1425 1428 messages.error(request, conf.message)
1426 1429
1427 1430 #conf.status_device()
1428 1431
1429 1432 return redirect(conf.get_absolute_url())
1430 1433
1431 1434
1432 1435 @login_required
1433 1436 def dev_conf_stop(request, id_conf):
1434 1437
1435 1438 conf = get_object_or_404(Configuration, pk=id_conf)
1436 1439
1437 1440 if conf.stop_device():
1438 1441 messages.success(request, conf.message)
1439 1442 else:
1440 1443 messages.error(request, conf.message)
1441 1444
1442 1445 #conf.status_device()
1443 1446
1444 1447 return redirect(conf.get_absolute_url())
1445 1448
1446 1449
1447 1450 @login_required
1448 1451 def dev_conf_status(request, id_conf):
1449 1452
1450 1453 conf = get_object_or_404(Configuration, pk=id_conf)
1451 1454
1452 1455 if conf.device.device_type.name == 'abs':
1453 1456 abs = request.user.profile.abs_active
1454 1457 if abs<>conf:
1455 1458 url = '#' if abs is None else abs.get_absolute_url()
1456 1459 label = 'None' if abs is None else abs.label
1457 1460 messages.warning(
1458 1461 request,
1459 1462 mark_safe('The current configuration has not been written in the modules, the active configuration is <a href="{}">{}</a>'.format(
1460 1463 url,
1461 1464 label
1462 1465 ))
1463 1466 )
1464 1467 return redirect(conf.get_absolute_url())
1465 1468
1466 1469 if conf.status_device():
1467 1470 messages.success(request, conf.message)
1468 1471 else:
1469 1472 messages.error(request, conf.message)
1470 1473
1471 1474 return redirect(conf.get_absolute_url())
1472 1475
1473 1476
1474 1477 @login_required
1475 1478 def dev_conf_reset(request, id_conf):
1476 1479
1477 1480 conf = get_object_or_404(Configuration, pk=id_conf)
1478 1481
1479 1482 if conf.reset_device():
1480 1483 messages.success(request, conf.message)
1481 1484 else:
1482 1485 messages.error(request, conf.message)
1483 1486
1484 1487 return redirect(conf.get_absolute_url())
1485 1488
1486 1489
1487 1490 @login_required
1488 1491 def dev_conf_write(request, id_conf):
1489 1492
1490 1493 conf = get_object_or_404(Configuration, pk=id_conf)
1491 1494
1492 1495 if conf.write_device():
1493 1496 messages.success(request, conf.message)
1494 1497 if has_been_modified(conf):
1495 1498 conf.clone(type=1, template=False)
1496 1499 else:
1497 1500 messages.error(request, conf.message)
1498 1501
1499 1502 return redirect(get_object_or_404(Configuration, pk=id_conf).get_absolute_url())
1500 1503
1501 1504
1502 1505 @login_required
1503 1506 def dev_conf_read(request, id_conf):
1504 1507
1505 1508 conf = get_object_or_404(Configuration, pk=id_conf)
1506 1509
1507 1510 DevConfForm = CONF_FORMS[conf.device.device_type.name]
1508 1511
1509 1512 if request.method == 'GET':
1510 1513
1511 1514 parms = conf.read_device()
1512 1515 #conf.status_device()
1513 1516
1514 1517 if not parms:
1515 1518 messages.error(request, conf.message)
1516 1519 return redirect(conf.get_absolute_url())
1517 1520
1518 1521 form = DevConfForm(initial=parms, instance=conf)
1519 1522
1520 1523 if request.method == 'POST':
1521 1524 form = DevConfForm(request.POST, instance=conf)
1522 1525
1523 1526 if form.is_valid():
1524 1527 form.save()
1525 1528 return redirect(conf.get_absolute_url())
1526 1529
1527 1530 messages.error(request, "Parameters could not be saved")
1528 1531
1529 1532 kwargs = {}
1530 1533 kwargs['id_dev'] = conf.id
1531 1534 kwargs['form'] = form
1532 1535 kwargs['title'] = 'Device Configuration'
1533 1536 kwargs['suptitle'] = 'Parameters read from device'
1534 1537 kwargs['button'] = 'Save'
1535 1538
1536 1539 ###### SIDEBAR ######
1537 1540 kwargs.update(sidebar(conf=conf))
1538 1541
1539 1542 return render(request, '%s_conf_edit.html' % conf.device.device_type.name, kwargs)
1540 1543
1541 1544
1542 1545 @login_required
1543 1546 def dev_conf_import(request, id_conf):
1544 1547
1545 1548 conf = get_object_or_404(Configuration, pk=id_conf)
1546 1549 DevConfForm = CONF_FORMS[conf.device.device_type.name]
1547 1550
1548 1551 if request.method == 'GET':
1549 1552 file_form = UploadFileForm()
1550 1553
1551 1554 if request.method == 'POST':
1552 1555 file_form = UploadFileForm(request.POST, request.FILES)
1553 1556
1554 1557 if file_form.is_valid():
1555 1558
1556 1559 data = conf.import_from_file(request.FILES['file'])
1557 1560 parms = Params(data=data).get_conf(
1558 1561 dtype=conf.device.device_type.name)
1559 1562
1560 1563 if parms:
1561 1564
1562 1565 form = DevConfForm(initial=parms, instance=conf)
1563 1566
1564 1567 kwargs = {}
1565 1568 kwargs['id_dev'] = conf.id
1566 1569 kwargs['form'] = form
1567 1570 kwargs['title'] = 'Device Configuration'
1568 1571 kwargs['suptitle'] = 'Parameters imported'
1569 1572 kwargs['button'] = 'Save'
1570 1573 kwargs['action'] = conf.get_absolute_url_edit()
1571 1574 kwargs['previous'] = conf.get_absolute_url()
1572 1575
1573 1576 ###### SIDEBAR ######
1574 1577 kwargs.update(sidebar(conf=conf))
1575 1578
1576 1579 messages.success(
1577 1580 request, "Parameters imported from: '%s'." % request.FILES['file'].name)
1578 1581
1579 1582 return render(request, '%s_conf_edit.html' % conf.device.device_type.name, kwargs)
1580 1583
1581 1584 messages.error(request, "Could not import parameters from file")
1582 1585
1583 1586 kwargs = {}
1584 1587 kwargs['id_dev'] = conf.id
1585 1588 kwargs['title'] = 'Device Configuration'
1586 1589 kwargs['form'] = file_form
1587 1590 kwargs['suptitle'] = 'Importing file'
1588 1591 kwargs['button'] = 'Import'
1589 1592 kwargs['menu_configurations'] = 'active'
1590 1593
1591 1594 kwargs.update(sidebar(conf=conf))
1592 1595
1593 1596 return render(request, 'dev_conf_import.html', kwargs)
1594 1597
1595 1598
1596 1599 @login_required
1597 1600 def dev_conf_export(request, id_conf):
1598 1601
1599 1602 conf = get_object_or_404(Configuration, pk=id_conf)
1600 1603
1601 1604 if request.method == 'GET':
1602 1605 file_form = DownloadFileForm(conf.device.device_type.name)
1603 1606
1604 1607 if request.method == 'POST':
1605 1608 file_form = DownloadFileForm(
1606 1609 conf.device.device_type.name, request.POST)
1607 1610
1608 1611 if file_form.is_valid():
1609 1612 fields = conf.export_to_file(
1610 1613 format=file_form.cleaned_data['format'])
1611 1614 if not fields['content']:
1612 1615 messages.error(request, conf.message)
1613 1616 return redirect(conf.get_absolute_url_export())
1614 1617 response = HttpResponse(content_type=fields['content_type'])
1615 1618 response['Content-Disposition'] = 'attachment; filename="%s"' % fields['filename']
1616 1619 response.write(fields['content'])
1617 1620
1618 1621 return response
1619 1622
1620 1623 messages.error(request, "Could not export parameters")
1621 1624
1622 1625 kwargs = {}
1623 1626 kwargs['id_dev'] = conf.id
1624 1627 kwargs['title'] = 'Device Configuration'
1625 1628 kwargs['form'] = file_form
1626 1629 kwargs['suptitle'] = 'Exporting file'
1627 1630 kwargs['button'] = 'Export'
1628 1631 kwargs['menu_configurations'] = 'active'
1629 1632
1630 1633 return render(request, 'dev_conf_export.html', kwargs)
1631 1634
1632 1635
1633 1636 @login_required
1634 1637 def dev_conf_delete(request, id_conf):
1635 1638
1636 1639 conf = get_object_or_404(Configuration, pk=id_conf)
1637 1640
1638 1641 if request.method == 'POST':
1639 1642 if is_developer(request.user):
1640 1643 conf.delete()
1641 1644 return redirect('url_dev_confs')
1642 1645
1643 1646 messages.error(request, 'Not enough permission to delete this object')
1644 1647 return redirect(conf.get_absolute_url())
1645 1648
1646 1649 kwargs = {
1647 1650 'title': 'Delete',
1648 1651 'suptitle': 'Configuration',
1649 1652 'object': conf,
1650 1653 'delete': True
1651 1654 }
1652 1655 kwargs['menu_configurations'] = 'active'
1653 1656
1654 1657 return render(request, 'confirm.html', kwargs)
1655 1658
1656 1659
1657 1660 def sidebar(**kwargs):
1658 1661
1659 1662 side_data = {}
1660 1663
1661 1664 conf = kwargs.get('conf', None)
1662 1665 experiment = kwargs.get('experiment', None)
1663 1666
1664 1667 if not experiment:
1665 1668 experiment = conf.experiment
1666 1669
1667 1670 if experiment:
1668 1671 side_data['experiment'] = experiment
1669 1672 campaign = experiment.campaign_set.all()
1670 1673 if campaign:
1671 1674 side_data['campaign'] = campaign[0]
1672 1675 experiments = campaign[0].experiments.all().order_by('name')
1673 1676 else:
1674 1677 experiments = [experiment]
1675 1678 configurations = experiment.configuration_set.filter(type=0)
1676 1679 side_data['side_experiments'] = experiments
1677 1680 side_data['side_configurations'] = configurations.order_by(
1678 1681 'device__device_type__name')
1679 1682
1680 1683 return side_data
1681 1684
1682 1685
1683 1686 def get_paginator(model, page, order, filters={}, n=8):
1684 1687
1685 1688 kwargs = {}
1686 1689 query = Q()
1687 1690 if isinstance(filters, QueryDict):
1688 1691 filters = filters.dict()
1689 1692 [filters.pop(key) for key in filters.keys() if filters[key] in ('', ' ')]
1690 1693 filters.pop('page', None)
1691 1694
1692 1695 fields = [f.name for f in model._meta.get_fields()]
1693 1696
1694 1697 if 'template' in filters:
1695 1698 filters['template'] = True
1696 1699 if 'historical' in filters:
1697 1700 filters.pop('historical')
1698 1701 filters['type'] = 1
1699 1702 elif 'type' in fields:
1700 1703 filters['type'] = 0
1701 1704 if 'start_date' in filters:
1702 1705 filters['start_date__gte'] = filters.pop('start_date')
1703 1706 if 'end_date' in filters:
1704 1707 filters['start_date__lte'] = filters.pop('end_date')
1705 1708 if 'tags' in filters:
1706 1709 tags = filters.pop('tags')
1707 1710 if 'tags' in fields:
1708 1711 query = query | Q(tags__icontains=tags)
1709 1712 if 'label' in fields:
1710 1713 query = query | Q(label__icontains=tags)
1711 1714 if 'location' in fields:
1712 1715 query = query | Q(location__name__icontains=tags)
1713 1716 if 'device' in fields:
1714 1717 query = query | Q(device__device_type__name__icontains=tags)
1715 1718 query = query | Q(device__location__name__icontains=tags)
1716 1719 if 'device_type' in fields:
1717 1720 query = query | Q(device_type__name__icontains=tags)
1718 1721
1719 1722 if 'mine' in filters:
1720 1723 filters['author_id'] = filters['mine']
1721 1724 filters.pop('mine')
1722 1725 object_list = model.objects.filter(query, **filters).order_by(*order)
1723 1726 paginator = Paginator(object_list, n)
1724 1727
1725 1728 try:
1726 1729 objects = paginator.page(page)
1727 1730 except PageNotAnInteger:
1728 1731 objects = paginator.page(1)
1729 1732 except EmptyPage:
1730 1733 objects = paginator.page(paginator.num_pages)
1731 1734
1732 1735 kwargs['objects'] = objects
1733 1736 kwargs['offset'] = (int(page)-1)*n if page else 0
1734 1737
1735 1738 return kwargs
1736 1739
1737 1740
1738 1741 def operation(request, id_camp=None):
1739 1742
1740 1743 kwargs = {}
1741 1744 kwargs['title'] = 'Radars Operation'
1742 1745 kwargs['no_sidebar'] = True
1743 1746 kwargs['menu_operation'] = 'active'
1744 1747 campaigns = Campaign.objects.filter(start_date__lte=datetime.now(),
1745 1748 end_date__gte=datetime.now()).order_by('-start_date')
1746 1749
1747 1750 if id_camp:
1748 1751 campaign = get_object_or_404(Campaign, pk=id_camp)
1749 1752 form = OperationForm(
1750 1753 initial={'campaign': campaign.id}, campaigns=campaigns)
1751 1754 kwargs['campaign'] = campaign
1752 1755 else:
1753 1756 # form = OperationForm(campaigns=campaigns)
1754 1757 kwargs['campaigns'] = campaigns
1755 1758 return render(request, 'operation.html', kwargs)
1756 1759
1757 1760 #---Experiment
1758 1761 keys = ['id', 'name', 'start_time', 'end_time', 'status']
1759 1762 kwargs['experiment_keys'] = keys[1:]
1760 1763 kwargs['experiments'] = experiments
1761 1764 #---Radar
1762 1765 kwargs['locations'] = campaign.get_experiments_by_radar()
1763 1766 kwargs['form'] = form
1764 1767
1765 1768 return render(request, 'operation.html', kwargs)
1766 1769
1767 1770
1768 1771 @login_required
1769 1772 def radar_start(request, id_camp, id_radar):
1770 1773
1771 1774 campaign = get_object_or_404(Campaign, pk=id_camp)
1772 1775 experiments = campaign.get_experiments_by_radar(id_radar)[0]['experiments']
1773 1776 now = datetime.now()
1774 1777 for exp in experiments:
1775 1778 start = datetime.combine(datetime.now().date(), exp.start_time)
1776 1779 end = datetime.combine(datetime.now().date(), exp.end_time)
1777 1780 if end < start:
1778 1781 end += timedelta(1)
1779 1782
1780 1783 if exp.status == 2:
1781 1784 messages.warning(
1782 1785 request, 'Experiment {} already running'.format(exp))
1783 1786 continue
1784 1787
1785 1788 if exp.status == 3:
1786 1789 messages.warning(
1787 1790 request, 'Experiment {} already programmed'.format(exp))
1788 1791 continue
1789 1792
1790 1793 if start > campaign.end_date or start < campaign.start_date:
1791 1794 messages.warning(request, 'Experiment {} out of date'.format(exp))
1792 1795 continue
1793 1796
1794 1797 if now > start and now <= end:
1795 1798 exp.status = 3
1796 1799 exp.save()
1797 1800 task = task_start.delay(exp.id)
1798 1801 exp.status = task.wait()
1799 1802 if exp.status == 0:
1800 1803 messages.error(request, 'Experiment {} not start'.format(exp))
1801 1804 if exp.status == 2:
1802 1805 messages.success(request, 'Experiment {} started'.format(exp))
1803 1806 else:
1804 1807 task = task_start.apply_async(
1805 1808 (exp.pk, ), eta=start+timedelta(hours=5))
1806 1809 exp.task = task.id
1807 1810 exp.status = 3
1808 1811 messages.success(
1809 1812 request, 'Experiment {} programmed to start at {}'.format(exp, start))
1810 1813
1811 1814 exp.save()
1812 1815
1813 1816 return HttpResponseRedirect(reverse('url_operation', args=[id_camp]))
1814 1817
1815 1818
1816 1819 @login_required
1817 1820 def radar_stop(request, id_camp, id_radar):
1818 1821
1819 1822 campaign = get_object_or_404(Campaign, pk=id_camp)
1820 1823 experiments = campaign.get_experiments_by_radar(id_radar)[0]['experiments']
1821 1824
1822 1825 for exp in experiments:
1823 1826
1824 1827 if exp.task:
1825 1828 app.control.revoke(exp.task)
1826 1829 if exp.status == 2:
1827 1830 exp.stop()
1828 1831 messages.warning(request, 'Experiment {} stopped'.format(exp))
1829 1832 exp.status = 1
1830 1833 exp.save()
1831 1834
1832 1835 return HttpResponseRedirect(reverse('url_operation', args=[id_camp]))
1833 1836
1834 1837
1835 1838 @login_required
1836 1839 def radar_refresh(request, id_camp, id_radar):
1837 1840
1838 1841 campaign = get_object_or_404(Campaign, pk=id_camp)
1839 1842 experiments = campaign.get_experiments_by_radar(id_radar)[0]['experiments']
1840 1843
1841 1844 for exp in experiments:
1842 1845 exp.get_status()
1843 1846
1844 1847 return HttpResponseRedirect(reverse('url_operation', args=[id_camp]))
1845 1848
1846 1849
1847 1850 def real_time(request):
1848 1851
1849 1852 graphic_path = "/home/fiorella/Pictures/catwbeanie.jpg"
1850 1853
1851 1854 kwargs = {}
1852 1855 kwargs['title'] = 'CLAIRE'
1853 1856 kwargs['suptitle'] = 'Real Time'
1854 1857 kwargs['no_sidebar'] = True
1855 1858 kwargs['graphic_path'] = graphic_path
1856 1859 kwargs['graphic1_path'] = 'http://www.bluemaize.net/im/girls-accessories/shark-beanie-11.jpg'
1857 1860
1858 1861 return render(request, 'real_time.html', kwargs)
1859 1862
1860 1863 def theme(request, theme):
1861 1864
1862 1865 user = request.user
1863 1866 user.profile.theme = theme
1864 1867 user.save()
1865 1868 return redirect('index') No newline at end of file
@@ -1,9 +1,10
1 1 from django.contrib import admin
2 from .models import RCConfiguration, RCLine, RCLineType, RCLineCode
2 from .models import RCConfiguration, RCLine, RCLineType, RCLineCode, RCClock
3 3
4 4 # Register your models here.
5 5
6 6 admin.site.register(RCConfiguration)
7 7 admin.site.register(RCLine)
8 8 admin.site.register(RCLineType)
9 9 admin.site.register(RCLineCode)
10 admin.site.register(RCClock)
@@ -1,384 +1,415
1 1 import os
2 2 import json
3 3
4 4 from django import forms
5 5 from django.utils.safestring import mark_safe
6 6 from apps.main.models import Device
7 7 from apps.main.forms import add_empty_choice
8 from .models import RCConfiguration, RCLine, RCLineType, RCLineCode
8 from .models import RCConfiguration, RCLine, RCLineType, RCLineCode, RCClock
9 9 from .widgets import KmUnitWidget, KmUnitHzWidget, KmUnitDcWidget, UnitKmWidget, DefaultWidget, CodesWidget, HiddenWidget, HCheckboxSelectMultiple
10 10
11 11 def create_choices_from_model(model, conf_id, all_choice=False):
12 12
13 13 if model=='RCLine':
14 14 instance = RCConfiguration.objects.get(pk=conf_id)
15 15 choices = [(line.pk, line.get_name()) for line in instance.get_lines(line_type__name='tx')]
16 16 if all_choice:
17 17 choices = add_empty_choice(choices, label='All')
18 18 else:
19 19 instance = globals()[model]
20 20 choices = instance.objects.all().values_list('pk', 'name')
21 21
22 22 return choices
23 23
24 24
25 25 class ExtFileField(forms.FileField):
26 26 """
27 27 Same as forms.FileField, but you can specify a file extension whitelist.
28 28
29 29 >>> from django.core.files.uploadedfile import SimpleUploadedFile
30 30 >>>
31 31 >>> t = ExtFileField(ext_whitelist=(".pdf", ".txt"))
32 32 >>>
33 33 >>> t.clean(SimpleUploadedFile('filename.pdf', 'Some File Content'))
34 34 >>> t.clean(SimpleUploadedFile('filename.txt', 'Some File Content'))
35 35 >>>
36 36 >>> t.clean(SimpleUploadedFile('filename.exe', 'Some File Content'))
37 37 Traceback (most recent call last):
38 38 ...
39 39 ValidationError: [u'Not allowed filetype!']
40 40 """
41 41 def __init__(self, *args, **kwargs):
42 42 extensions = kwargs.pop("extensions")
43 43 self.extensions = [i.lower() for i in extensions]
44 44
45 45 super(ExtFileField, self).__init__(*args, **kwargs)
46 46
47 47 def clean(self, *args, **kwargs):
48 48 data = super(ExtFileField, self).clean(*args, **kwargs)
49 49 filename = data.name
50 50 ext = os.path.splitext(filename)[1]
51 51 ext = ext.lower()
52 52 if ext not in self.extensions:
53 53 raise forms.ValidationError('Not allowed file type: %s' % ext)
54 54
55 55
56 56 class RCConfigurationForm(forms.ModelForm):
57 57
58 58 def __init__(self, *args, **kwargs):
59 59 super(RCConfigurationForm, self).__init__(*args, **kwargs)
60 60
61 61 instance = getattr(self, 'instance', None)
62 62
63 63 if instance and instance.pk:
64 64
65 65 devices = Device.objects.filter(device_type__name='rc')
66 66 if instance.experiment:
67 67 self.fields['experiment'].widget.attrs['read_only'] = True
68 68 #self.fields['experiment'].widget.choices = [(instance.experiment.id, instance.experiment)]
69 69 self.fields['device'].widget.choices = [(device.id, device) for device in devices]
70 70 self.fields['ipp'].widget = KmUnitHzWidget(attrs={'km2unit':instance.km2unit})
71 71 self.fields['clock'].widget.attrs['readonly'] = True
72 72
73 73 self.fields['time_before'].label = mark_safe(self.fields['time_before'].label)
74 74 self.fields['time_after'].label = mark_safe(self.fields['time_after'].label)
75 75
76 76 if 'initial' in kwargs and 'experiment' in kwargs['initial'] and kwargs['initial']['experiment'] not in (0, '0'):
77 77 self.fields['experiment'].widget.attrs['readonly'] = True
78 78
79 79 class Meta:
80 80 model = RCConfiguration
81 exclude = ('type', 'parameters', 'status', 'total_units', 'mix', 'author', 'hash')
81 exclude = ('type', 'parameters', 'status', 'total_units', 'mix', 'author', 'hash', 'clock_in')
82 82
83 83 def clean(self):
84 84 form_data = super(RCConfigurationForm, self).clean()
85 85
86 86 if 'clock_divider' in form_data:
87 87 if form_data['clock_divider']<1:
88 88 self.add_error('clock_divider', 'Invalid Value')
89 89 #else:
90 90 # if form_data['ipp']*(20./3*(form_data['clock_in']/form_data['clock_divider']))%10!=0:
91 91 # self.add_error('ipp', 'Invalid IPP units={}'.format(form_data['ipp']*(20./3*(form_data['clock_in']/form_data['clock_divider']))))
92 92
93 93 return form_data
94 94
95 95 def save(self, *args, **kwargs):
96 96 conf = super(RCConfigurationForm, self).save(*args, **kwargs)
97 97 conf.total_units = conf.ipp*conf.ntx*conf.km2unit
98 98 conf.save()
99 99 return conf
100 100
101 101
102 102 class RCMixConfigurationForm(forms.Form):
103 103
104 104 clock_in = forms.CharField(widget=forms.HiddenInput())
105 105 clock_divider = forms.CharField(widget=forms.HiddenInput())
106 106 name = forms.CharField()
107 107 experiment = forms.ChoiceField()
108 108 mode = forms.ChoiceField(widget=forms.RadioSelect(),
109 109 choices=[(0, 'Parallel'), (1, 'Sequence')],
110 110 initial=0)
111 111 operation = forms.ChoiceField(widget=forms.RadioSelect(),
112 112 choices=[(0, 'OR'), (1, 'XOR'), (2, 'AND'), (3, 'NAND')],
113 113 initial=1)
114 114 delay = forms.CharField()
115 115 mask = forms.MultipleChoiceField(
116 116 choices=[(0, 'L1'),(1, 'L2'),(2, 'L3'),(3, 'L4'),(4, 'L5'),(5, 'L6'),(6, 'L7'),(7, 'L8'),
117 117 (8, 'L9'),(9, 'L10'),(10, 'L11'),(11, 'L12'),(12, 'L13'),(13, 'L14'),(14, 'L15'),(15, 'L16')],
118 118 widget=HCheckboxSelectMultiple())
119 119 result = forms.CharField(required=False,
120 120 widget=forms.Textarea(attrs={'readonly':True, 'rows':5, 'class':'tabuled'}))
121 121
122 122 def __init__(self, *args, **kwargs):
123 123 confs = kwargs.pop('confs', [])
124 124 if confs:
125 125 km2unit = confs[0].km2unit
126 126 clock_in = confs[0].clock_in
127 127 clock_divider = confs[0].clock_divider
128 128 else:
129 129 km2unit = clock_in = clock_divider = 0
130 130 super(RCMixConfigurationForm, self).__init__(*args, **kwargs)
131 131 self.fields['experiment'].choices = [(conf.pk, '{} | {}'.format(conf.pk, conf.name)) for conf in confs]
132 132 self.fields['delay'].widget = KmUnitWidget(attrs = {'km2unit':km2unit})
133 133 self.fields['clock_in'].initial = clock_in
134 134 self.fields['clock_divider'].initial = clock_divider
135 135
136 136
137 137 class RCLineForm(forms.ModelForm):
138 138
139 139 def __init__(self, *args, **kwargs):
140 140 self.extra_fields = kwargs.pop('extra_fields', [])
141 141 super(RCLineForm, self).__init__(*args, **kwargs)
142 142
143 143 if 'initial' in kwargs and 'line_type' in kwargs['initial']:
144 144 line_type = RCLineType.objects.get(pk=kwargs['initial']['line_type'])
145 145
146 146 if 'code_id' in kwargs['initial']:
147 147 model_initial = kwargs['initial']['code_id']
148 148 else:
149 149 model_initial = 0
150 150
151 151 params = json.loads(line_type.params)
152 152
153 153 for label, value in self.extra_fields.items():
154 154 if label=='params':
155 155 continue
156 156
157 157 if 'model' in params[label]:
158 158 self.fields[label] = forms.ChoiceField(choices=create_choices_from_model(params[label]['model'],
159 159 kwargs['initial']['rc_configuration']),
160 160 initial=model_initial)
161 161
162 162
163 163 else:
164 164 if label=='codes' and 'code_id' in kwargs['initial']:
165 165 self.fields[label] = forms.CharField(initial=RCLineCode.objects.get(pk=kwargs['initial']['code_id']).codes)
166 166 else:
167 167 self.fields[label] = forms.CharField(initial=value['value'])
168 168
169 169 if label=='codes':
170 170 self.fields[label].widget = CodesWidget()
171 171
172 172 if self.data:
173 173 line_type = RCLineType.objects.get(pk=self.data['line_type'])
174 174
175 175 if 'code_id' in self.data:
176 176 model_initial = self.data['code_id']
177 177 else:
178 178 model_initial = 0
179 179
180 180 params = json.loads(line_type.params)
181 181
182 182 for label, value in self.extra_fields.items():
183 183 if label=='params':
184 184 continue
185 185
186 186 if 'model' in params[label]:
187 187 self.fields[label] = forms.ChoiceField(choices=create_choices_from_model(params[label]['model'],
188 188 self.data['rc_configuration']),
189 189 initial=model_initial)
190 190
191 191
192 192 else:
193 193 if label=='codes' and 'code' in self.data:
194 194 self.fields[label] = forms.CharField(initial=self.data['codes'])
195 195 else:
196 196 self.fields[label] = forms.CharField(initial=self.data[label])
197 197
198 198 if label=='codes':
199 199 self.fields[label].widget = CodesWidget()
200 200
201 201
202 202 class Meta:
203 203 model = RCLine
204 204 fields = ('rc_configuration', 'line_type', 'channel')
205 205 widgets = {
206 206 'channel': forms.HiddenInput(),
207 207 }
208 208
209 209
210 210 def clean(self):
211 211
212 212 form_data = self.cleaned_data
213 213 if 'code' in self.data and self.data['TX_ref']=="0":
214 214 self.add_error('TX_ref', 'Choose a valid TX reference')
215 215
216 216 if RCLineType.objects.get(pk=self.data['line_type']).name=='mix':
217 217 self.add_error('line_type', 'Invalid Line type')
218 218
219 219 return form_data
220 220
221 221
222 222 def save(self):
223 223 line = super(RCLineForm, self).save()
224 224
225 225 #auto add channel
226 226 line.channel = RCLine.objects.filter(rc_configuration=line.rc_configuration).count()-1
227 227
228 228 #auto add position for TX, TR & CODE
229 229 if line.line_type.name in ('tx', ):
230 230 line.position = RCLine.objects.filter(rc_configuration=line.rc_configuration, line_type=line.line_type).count()-1
231 231
232 232 #save extra fields in params
233 233 params = {}
234 234 for label, value in self.extra_fields.items():
235 235 if label=='params':
236 236 params['params'] = []
237 237 elif label=='codes':
238 238 params[label] = [s for s in self.data[label].split('\r\n') if s]
239 239 else:
240 240 params[label] = self.data[label]
241 241 line.params = json.dumps(params)
242 242 line.save()
243 243 return
244 244
245 245
246 246 class RCLineViewForm(forms.Form):
247 247
248 248 def __init__(self, *args, **kwargs):
249 249
250 250 extra_fields = kwargs.pop('extra_fields')
251 251 line = kwargs.pop('line')
252 252 subform = kwargs.pop('subform', False)
253 253 super(RCLineViewForm, self).__init__(*args, **kwargs)
254 254
255 255 if subform:
256 256 params = json.loads(line.line_type.params)['params']
257 257 else:
258 258 params = json.loads(line.line_type.params)
259 259
260 260 for label, value in extra_fields.items():
261 261
262 262 if label=='params':
263 263 continue
264 264 if 'ref' in label:
265 265 if value in (0, '0'):
266 266 value = 'All'
267 267 else:
268 268 value = RCLine.objects.get(pk=value).get_name()
269 269 elif label=='code':
270 270 value = RCLineCode.objects.get(pk=value).name
271 271
272 272 self.fields[label] = forms.CharField(initial=value)
273 273
274 274 if 'widget' in params[label]:
275 275 km2unit = line.rc_configuration.km2unit
276 276 if params[label]['widget']=='km':
277 277 self.fields[label].widget = KmUnitWidget(attrs={'line':line, 'km2unit':km2unit, 'disabled':True})
278 278 elif params[label]['widget']=='unit':
279 279 self.fields[label].widget = UnitKmWidget(attrs={'line':line, 'km2unit':km2unit, 'disabled':True})
280 280 elif params[label]['widget']=='dc':
281 281 self.fields[label].widget = KmUnitDcWidget(attrs={'line':line, 'km2unit':km2unit, 'disabled':True})
282 282 elif params[label]['widget']=='codes':
283 283 self.fields[label].widget = CodesWidget(attrs={'line':line, 'km2unit':km2unit, 'disabled':True})
284 284 else:
285 285 self.fields[label].widget = DefaultWidget(attrs={'disabled':True})
286 286
287 287
288 288 class RCLineEditForm(forms.ModelForm):
289 289
290 290 def __init__(self, *args, **kwargs):
291 291
292 292 extra_fields = kwargs.pop('extra_fields', [])
293 293 conf = kwargs.pop('conf', False)
294 294 line = kwargs.pop('line')
295 295 subform = kwargs.pop('subform', False)
296 296
297 297 super(RCLineEditForm, self).__init__(*args, **kwargs)
298 298
299 299 if subform is not False:
300 300 params = json.loads(line.line_type.params)['params']
301 301 count = subform
302 302 else:
303 303 params = json.loads(line.line_type.params)
304 304 count = -1
305 305
306 306 for label, value in extra_fields.items():
307 307
308 308 if label in ('params',):
309 309 continue
310 310 if 'help' in params[label]:
311 311 help_text = params[label]['help']
312 312 else:
313 313 help_text = ''
314 314
315 315 if 'model' in params[label]:
316 316 if line.line_type.name=='tr':
317 317 all_choice = True
318 318 else:
319 319 all_choice = False
320 320 self.fields[label] = forms.ChoiceField(choices=create_choices_from_model(params[label]['model'], conf.id, all_choice=all_choice),
321 321 initial=value,
322 322 widget=forms.Select(attrs={'name':'%s|%s|%s' % (count, line.id, label)}),
323 323 help_text=help_text)
324 324
325 325 else:
326 326 self.fields[label] = forms.CharField(initial=value, help_text=help_text)
327 327
328 328 if label in ('code', ):
329 329 self.fields[label].widget = HiddenWidget(attrs={'name':'%s|%s|%s' % (count, line.id, label)})
330 330
331 331 elif 'widget' in params[label]:
332 332 km2unit = line.rc_configuration.km2unit
333 333 if params[label]['widget']=='km':
334 334 self.fields[label].widget = KmUnitWidget(attrs={'line':line, 'km2unit':km2unit, 'name':'%s|%s|%s' % (count, line.id, label)})
335 335 elif params[label]['widget']=='unit':
336 336 self.fields[label].widget = UnitKmWidget(attrs={'line':line, 'km2unit':km2unit, 'name':'%s|%s|%s' % (count, line.id, label)})
337 337 elif params[label]['widget']=='dc':
338 338 self.fields[label].widget = KmUnitDcWidget(attrs={'line':line, 'km2unit':km2unit, 'name':'%s|%s|%s' % (count, line.id, label)})
339 339 elif params[label]['widget']=='codes':
340 340 self.fields[label].widget = CodesWidget(attrs={'line':line, 'km2unit':km2unit, 'name':'%s|%s|%s' % (count, line.id, label)})
341 341 else:
342 342 self.fields[label].widget = DefaultWidget(attrs={'line':line, 'name':'%s|%s|%s' % (count, line.id, label)})
343 343
344 344
345 345 class Meta:
346 346 model = RCLine
347 347 exclude = ('rc_configuration', 'line_type', 'channel', 'position', 'params', 'pulses')
348 348
349 349
350 350 class RCSubLineEditForm(forms.Form):
351 351
352 352 def __init__(self, *args, **kwargs):
353 353 extra_fields = kwargs.pop('extra_fields')
354 354 count = kwargs.pop('count')
355 355 line = kwargs.pop('line')
356 356 super(RCSubLineEditForm, self).__init__(*args, **kwargs)
357 357 for label, value in extra_fields.items():
358 358 self.fields[label] = forms.CharField(initial=value,
359 359 widget=forms.TextInput(attrs={'name':'%s|%s|%s' % (count, line, label)}))
360 360
361 361
362 362 class RCImportForm(forms.Form):
363 363
364 364 file_name = ExtFileField(extensions=['.racp', '.json', '.dat'])
365 365
366 366
367 367 class RCLineCodesForm(forms.ModelForm):
368 368
369 369 def __init__(self, *args, **kwargs):
370 370 super(RCLineCodesForm, self).__init__(*args, **kwargs)
371 371
372 372 if 'initial' in kwargs:
373 373 self.fields['code'] = forms.ChoiceField(choices=RCLineCode.objects.all().values_list('pk', 'name'),
374 374 initial=kwargs['initial']['code'])
375 375 if 'instance' in kwargs:
376 376 self.fields['code'] = forms.ChoiceField(choices=RCLineCode.objects.all().values_list('pk', 'name'),
377 377 initial=kwargs['instance'].pk)
378 378
379 379 self.fields['codes'].widget = CodesWidget()
380 380
381 381
382 382 class Meta:
383 383 model = RCLineCode
384 384 exclude = ('name',)
385
386 class RCClockForm(forms.ModelForm):
387
388 def __init__(self, *args, **kwargs):
389 super(RCClockForm, self).__init__(*args, **kwargs)
390
391 instance = getattr(self, 'instance', None)
392
393 if instance is not None and instance.mode:
394 self.fields['multiplier'].widget.attrs['readonly'] = True
395 self.fields['divisor'].widget.attrs['readonly'] = True
396 self.fields['reference'].widget.attrs['readonly'] = True
397
398
399 class Meta:
400 model = RCClock
401 exclude = ('rc_configuration',)
402
403 def clean(self):
404
405 form_data = self.cleaned_data
406
407 if form_data['mode'] is True and float(form_data['frequency']) not in (60., 55.):
408 self.add_error('frequency', 'Only 60 and 55 are valid values in auto mode')
409 elif form_data['mode'] is False:
410 if form_data['reference']==0 and not 24<=form_data['multiplier']<=36:
411 self.add_error('multiplier', 'For 25MHz, valid values are between 24 and 36')
412 elif form_data['reference']==1 and not 60<=form_data['multiplier']<=90:
413 self.add_error('multiplier', 'For 10MHz, valid values are between 60 and 90')
414
415 return form_data No newline at end of file
@@ -1,1004 +1,1027
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.core.urlresolvers 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 83 sampling_reference = models.CharField(verbose_name='Sampling Reference', choices=SAMPLING_REFS, default='none', max_length=40)
84 84 control_tx = models.BooleanField(verbose_name='Control Switch TX', default=False)
85 85 control_sw = models.BooleanField(verbose_name='Control Switch SW', default=False)
86 86 total_units = models.PositiveIntegerField(default=0)
87 87 mix = models.BooleanField(default=False)
88 88
89 89 class Meta:
90 90 db_table = 'rc_configurations'
91 91
92 92 def get_absolute_url_plot(self):
93 93 return reverse('url_plot_rc_pulses', args=[str(self.id)])
94 94
95 95 @property
96 96 def ipp_unit(self):
97 97
98 98 return '{} ({})'.format(self.ipp, int(self.ipp*self.km2unit))
99 99
100 100 @property
101 101 def us2unit(self):
102 102
103 103 return self.clock_in/self.clock_divider
104 104
105 105 @property
106 106 def km2unit(self):
107 107
108 108 return 20./3*(self.clock_in/self.clock_divider)
109 109
110 110 def clone(self, **kwargs):
111 111
112 112 lines = self.get_lines()
113 113 self.pk = None
114 114 self.id = None
115 115 for attr, value in kwargs.items():
116 116 setattr(self, attr, value)
117 117 self.save()
118 118
119 119 for line in lines:
120 120 line.clone(rc_configuration=self)
121 121
122 122 new_lines = self.get_lines()
123 123 for line in new_lines:
124 124 line_params = json.loads(line.params)
125 125 if 'TX_ref' in line_params and (line_params['TX_ref'] != '0'):
126 126 ref_line = RCLine.objects.get(pk=line_params['TX_ref'])
127 127 line_params['TX_ref'] = ['{}'.format(l.pk) for l in new_lines if l.get_name()==ref_line.get_name()][0]
128 128 line.params = json.dumps(line_params)
129 129 line.save()
130 130
131 131 return self
132 132
133 133 def get_lines(self, **kwargs):
134 134 '''
135 135 Retrieve configuration lines
136 136 '''
137 137
138 138 return RCLine.objects.filter(rc_configuration=self.pk, **kwargs)
139 139
140 140
141 141 def clean_lines(self):
142 142 '''
143 143 '''
144 144
145 145 empty_line = RCLineType.objects.get(name='none')
146 146
147 147 for line in self.get_lines():
148 148 line.line_type = empty_line
149 149 line.params = '{}'
150 150 line.save()
151 151
152 152 def dict_to_parms(self, params, id=None):
153 153 '''
154 154 '''
155 155
156 156 if id:
157 157 data = Params(params).get_conf(id_conf=id)
158 158 else:
159 159 data = Params(params).get_conf(dtype='rc')
160 160
161 161 # self.name = data['name']
162 162 self.ipp = data['ipp']
163 163 self.ntx = data['ntx']
164 164 self.clock_in = data['clock_in']
165 165 self.clock_divider = data['clock_divider']
166 166 self.clock = data['clock']
167 167 self.time_before = data['time_before']
168 168 self.time_after = data['time_after']
169 169 self.sync = data['sync']
170 170 self.sampling_reference = data['sampling_reference']
171 171 self.total_units = self.ipp*self.ntx*self.km2unit
172 172 self.save()
173 173 self.clean_lines()
174 174
175 175 positions = {'tx':0, 'tr':0}
176 176 for i, id in enumerate(data['lines']):
177 177 line_data = params['lines']['byId'][id]
178 178 line_type = RCLineType.objects.get(name=line_data['line_type'])
179 179 if line_type.name == 'codes':
180 180 code = RCLineCode.objects.get(name=line_data['params']['code'])
181 181 line_data['params']['code'] = code.pk
182 182 if line_type.name == 'tx':
183 183 position = positions['tx']
184 184 positions['tx'] += 1
185 185 elif line_type.name == 'tr':
186 186 position = positions['tr']
187 187 positions['tr'] += 1
188 188 else:
189 189 position = 0
190 190 line, dum = RCLine.objects.update_or_create(
191 191 rc_configuration=self,
192 192 channel=i,
193 193 position=position,
194 194 defaults={
195 195 'line_type': line_type,
196 196 'params': json.dumps(line_data['params'])
197 197 }
198 198 )
199 199
200 200 for i, line in enumerate(self.get_lines()):
201 201 line_params = json.loads(line.params)
202 202 if 'TX_ref' in line_params:
203 203 if line_params['TX_ref'] in (0, '0'):
204 204 line_params['TX_ref'] = '0'
205 205 else:
206 206 ref_id = '{}'.format(line_params['TX_ref'])
207 207 ref_line = params['lines']['byId'][ref_id]
208 208 line_params['TX_ref'] = RCLine.objects.get(
209 209 rc_configuration=self,
210 210 params=json.dumps(ref_line['params'])
211 211 ).pk
212 212 line.params = json.dumps(line_params)
213 213 line.save()
214 214
215 215
216 216 def get_delays(self):
217 217
218 218 pulses = [line.pulses_as_points() for line in self.get_lines()]
219 219 points = [tup for tups in pulses for tup in tups]
220 220 points = set([x for tup in points for x in tup])
221 221 points = list(points)
222 222 points.sort()
223 223
224 224 if points[0]!=0:
225 225 points.insert(0, 0)
226 226
227 227 return [points[i+1]-points[i] for i in range(len(points)-1)]
228 228
229 229
230 230 def get_pulses(self, binary=True):
231 231
232 232 pulses = [line.pulses_as_points() for line in self.get_lines()]
233 233 tuples = [tup for tups in pulses for tup in tups]
234 234 points = set([x for tup in tuples for x in tup])
235 235 points = list(points)
236 236 points.sort()
237 237 states = []
238 238 last = [0 for x in pulses]
239 239
240 240 for x in points:
241 241 dum = []
242 242 for i, tups in enumerate(pulses):
243 243 ups = [tup[0] for tup in tups if tup!=(0,0)]
244 244 dws = [tup[1] for tup in tups if tup!=(0,0)]
245 245 if x in ups:
246 246 dum.append(1)
247 247 elif x in dws:
248 248 dum.append(0)
249 249 else:
250 250 dum.append(last[i])
251 251 states.append(dum)
252 252 last = dum
253 253
254 254 if binary:
255 255 ret = []
256 256 for flips in states:
257 257 flips.reverse()
258 258 ret.append(int(''.join([str(x) for x in flips]), 2))
259 259 states = ret
260 260
261 261 return states[:-1]
262 262
263 263 def add_cmd(self, cmd):
264 264
265 265 if cmd in DAT_CMDS:
266 266 return (255, DAT_CMDS[cmd])
267 267
268 268 def add_data(self, value):
269 269
270 270 return (254, value-1)
271 271
272 272 def parms_to_binary(self, dat=True):
273 273 '''
274 274 Create "dat" stream to be send to CR
275 275 '''
276 276
277 277 data = bytearray()
278 278 # create header
279 279 data.extend(self.add_cmd('DISABLE'))
280 280 data.extend(self.add_cmd('CONTINUE'))
281 281 data.extend(self.add_cmd('RESTART'))
282 282
283 283 if self.control_sw:
284 284 data.extend(self.add_cmd('SW_ONE'))
285 285 else:
286 286 data.extend(self.add_cmd('SW_ZERO'))
287 287
288 288 if self.control_tx:
289 289 data.extend(self.add_cmd('TX_ONE'))
290 290 else:
291 291 data.extend(self.add_cmd('TX_ZERO'))
292 292
293 293 # write divider
294 294 data.extend(self.add_cmd('CLOCK_DIVIDER'))
295 295 data.extend(self.add_data(self.clock_divider))
296 296
297 297 # write delays
298 298 data.extend(self.add_cmd('DELAY_START'))
299 299 # first delay is always zero
300 300 data.extend(self.add_data(1))
301 301
302 302 delays = self.get_delays()
303 303
304 304 for delay in delays:
305 305 while delay>252:
306 306 data.extend(self.add_data(253))
307 307 delay -= 253
308 308 data.extend(self.add_data(int(delay)))
309 309
310 310 # write flips
311 311 data.extend(self.add_cmd('FLIP_START'))
312 312
313 313 states = self.get_pulses(binary=True)
314 314
315 315
316 316 last = 0
317 317 for flip, delay in zip(states, delays):
318 318 data.extend(self.add_data((flip^last)+1))
319 319 last = flip
320 320 while delay>252:
321 321 data.extend(self.add_data(1))
322 322 delay -= 253
323 323
324 324 # write sampling period
325 325 data.extend(self.add_cmd('SAMPLING_PERIOD'))
326 326 wins = self.get_lines(line_type__name='windows')
327 327 if wins:
328 328 win_params = json.loads(wins[0].params)['params']
329 329 if win_params:
330 330 dh = int(win_params[0]['resolution']*self.km2unit)
331 331 else:
332 332 dh = 1
333 333 else:
334 334 dh = 1
335 335 data.extend(self.add_data(dh))
336 336
337 337 # write enable
338 338 data.extend(self.add_cmd('ENABLE'))
339 339
340 340 if not dat:
341 341 return data
342 342
343 343 return '\n'.join(['{}'.format(x) for x in data])
344 344
345 345 def update_pulses(self):
346 346
347 347 for line in self.get_lines():
348 348 line.update_pulses()
349 349
350 350 def plot_pulses2(self, km=False):
351 351
352 352 import matplotlib
353 353 matplotlib.use('Agg')
354 354 import matplotlib.pyplot as plt
355 355 from bokeh.resources import CDN
356 356 from bokeh.embed import components
357 357 from bokeh.mpl import to_bokeh
358 358 from bokeh.models.tools import WheelZoomTool, ResetTool, PanTool, HoverTool, SaveTool
359 359
360 360 lines = self.get_lines()
361 361
362 362 N = len(lines)
363 363 npoints = self.total_units/self.km2unit if km else self.total_units
364 364 fig = plt.figure(figsize=(12, 2+N*0.5))
365 365 ax = fig.add_subplot(111)
366 366 labels = ['IPP']
367 367
368 368 for i, line in enumerate(lines):
369 369 labels.append(line.get_name(channel=True))
370 370 l = ax.plot((0, npoints),(N-i-1, N-i-1))
371 371 points = [(tup[0], tup[1]-tup[0]) for tup in line.pulses_as_points(km=km) if tup!=(0,0)]
372 372 ax.broken_barh(points, (N-i-1, 0.5),
373 373 edgecolor=l[0].get_color(), facecolor='none')
374 374
375 375 n = 0
376 376 f = ((self.ntx+50)/100)*5 if ((self.ntx+50)/100)*10>0 else 2
377 377 for x in np.arange(0, npoints, self.ipp if km else self.ipp*self.km2unit):
378 378 if n%f==0:
379 379 ax.text(x, N, '%s' % n, size=10)
380 380 n += 1
381 381
382 382 labels.reverse()
383 383 ax.set_yticks(range(len(labels)))
384 384 ax.set_yticklabels(labels)
385 385 ax.set_xlabel = 'Units'
386 386 plot = to_bokeh(fig, use_pandas=False)
387 387 plot.tools = [PanTool(dimensions=['width']), WheelZoomTool(dimensions=['width']), ResetTool(), SaveTool()]
388 388 plot.toolbar_location="above"
389 389
390 390 return components(plot, CDN)
391 391
392 392 def plot_pulses(self, km=False):
393 393
394 394 from bokeh.plotting import figure
395 395 from bokeh.resources import CDN
396 396 from bokeh.embed import components
397 397 from bokeh.models import FixedTicker, PrintfTickFormatter
398 398 from bokeh.models.tools import WheelZoomTool, ResetTool, PanTool, HoverTool, SaveTool
399 399 from bokeh.models.sources import ColumnDataSource
400 400
401 401 lines = self.get_lines().reverse()
402 402
403 403 N = len(lines)
404 404 npoints = self.total_units/self.km2unit if km else self.total_units
405 405 ipp = self.ipp if km else self.ipp*self.km2unit
406 406
407 407 hover = HoverTool(tooltips=[("Line", "@name"),
408 408 ("IPP", "@ipp"),
409 409 ("X", "@left")])
410 410
411 411 tools = [PanTool(dimensions=['width']),
412 412 WheelZoomTool(dimensions=['width']),
413 413 hover, SaveTool()]
414 414
415 415 plot = figure(width=1000,
416 416 height=40+N*50,
417 417 y_range = (0, N),
418 418 tools=tools,
419 419 toolbar_location='above',
420 420 toolbar_sticky=False,)
421 421
422 422 plot.xaxis.axis_label = 'Km' if km else 'Units'
423 423 plot.xaxis[0].formatter = PrintfTickFormatter(format='%d')
424 424 plot.yaxis.axis_label = 'Pulses'
425 425 plot.yaxis[0].ticker=FixedTicker(ticks=list(range(N)))
426 426 plot.yaxis[0].formatter = PrintfTickFormatter(format='Line %d')
427 427
428 428 for i, line in enumerate(lines):
429 429
430 430 points = [tup for tup in line.pulses_as_points(km=km) if tup!=(0,0)]
431 431
432 432 source = ColumnDataSource(data = dict(
433 433 bottom = [i for tup in points],
434 434 top = [i+0.5 for tup in points],
435 435 left = [tup[0] for tup in points],
436 436 right = [tup[1] for tup in points],
437 437 ipp = [int(tup[0]/ipp) for tup in points],
438 438 name = [line.get_name() for tup in points]
439 439 ))
440 440
441 441 plot.quad(
442 442 bottom = 'bottom',
443 443 top = 'top',
444 444 left = 'left',
445 445 right = 'right',
446 446 source = source,
447 447 fill_alpha = 0,
448 448 #line_color = 'blue',
449 449 )
450 450
451 451 plot.line([0, npoints], [i, i])#, color='blue')
452 452
453 453 return components(plot, CDN)
454 454
455 455 def request(self, cmd, method='get', **kwargs):
456 456
457 457 req = getattr(requests, method)(self.device.url(cmd), **kwargs)
458 458 payload = req.json()
459 459
460 460 return payload
461 461
462 462 def status_device(self):
463 463
464 464 try:
465 465 self.device.status = 0
466 466 payload = self.request('status')
467 467 if payload['status']=='enable':
468 468 self.device.status = 3
469 469 elif payload['status']=='disable':
470 470 self.device.status = 2
471 471 else:
472 472 self.device.status = 1
473 473 self.device.save()
474 474 self.message = 'RC status: {}'.format(payload['status'])
475 475 return False
476 476 except Exception as e:
477 477 if 'No route to host' not in str(e):
478 478 self.device.status = 4
479 479 self.device.save()
480 480 self.message = 'RC status: {}'.format(str(e))
481 481 return False
482 482
483 483 self.device.save()
484 484 return True
485 485
486 486 def reset_device(self):
487 487
488 488 try:
489 489 payload = self.request('reset', 'post')
490 490 if payload['reset']=='ok':
491 491 self.message = 'RC restarted OK'
492 492 self.device.status = 2
493 493 self.device.save()
494 494 else:
495 495 self.message = 'RC restart fail'
496 496 self.device.status = 4
497 497 self.device.save()
498 498 except Exception as e:
499 499 self.message = 'RC reset: {}'.format(str(e))
500 500 return False
501 501
502 502 return True
503 503
504 504 def stop_device(self):
505 505
506 506 try:
507 507 payload = self.request('stop', 'post')
508 508 self.message = 'RC stop: {}'.format(payload['stop'])
509 509 if payload['stop']=='ok':
510 510 self.device.status = 2
511 511 self.device.save()
512 512 else:
513 513 self.device.status = 4
514 514 self.device.save()
515 515 return False
516 516 except Exception as e:
517 517 if 'No route to host' not in str(e):
518 518 self.device.status = 4
519 519 else:
520 520 self.device.status = 0
521 521 self.message = 'RC stop: {}'.format(str(e))
522 522 self.device.save()
523 523 return False
524 524
525 525 return True
526 526
527 527 def start_device(self):
528 528
529 529 try:
530 530 payload = self.request('start', 'post')
531 531 self.message = 'RC start: {}'.format(payload['start'])
532 532 if payload['start']=='ok':
533 533 self.device.status = 3
534 534 self.device.save()
535 535 else:
536 536 return False
537 537 except Exception as e:
538 538 if 'No route to host' not in str(e):
539 539 self.device.status = 4
540 540 else:
541 541 self.device.status = 0
542 542 self.message = 'RC start: {}'.format(str(e))
543 543 self.device.save()
544 544 return False
545 545
546 546 return True
547 547
548 548 def write_device(self, raw=False):
549 549
550 if not raw:
551 clock = RCClock.objects.get(rc_configuration=self)
552 if clock.mode:
553 data = {'default': clock.frequency}
554 else:
555 data = {'manual': [clock.multiplier, clock.divisor, clock.reference]}
556 payload = self.request('setfreq', 'post', data=json.dumps(data))
557 if payload['command'] <> 'ok':
558 self.message = 'RC write: {}'.format(payload['command'])
559 else:
560 self.message = payload['programming']
561 if payload['programming'] == 'fail':
562 self.message = 'RC write: error programming CGS chip'
563
550 564 values = []
551 565 for pulse, delay in zip(self.get_pulses(), self.get_delays()):
552 566 while delay>65536:
553 567 values.append((pulse, 65535))
554 568 delay -= 65536
555 569 values.append((pulse, delay-1))
556 570 data = bytearray()
557 571 #reset
558 572 data.extend((128, 0))
559 573 #disable
560 574 data.extend((129, 0))
561 575 #SW switch
562 576 if self.control_sw:
563 577 data.extend((130, 2))
564 578 else:
565 579 data.extend((130, 0))
566 580 #divider
567 581 data.extend((131, self.clock_divider-1))
568 582 #enable writing
569 583 data.extend((139, 62))
570 584
571 585 last = 0
572 586 for tup in values:
573 587 vals = pack('<HH', last^tup[0], tup[1])
574 588 last = tup[0]
575 589 data.extend((133, vals[1], 132, vals[0], 133, vals[3], 132, vals[2]))
576 590
577 591 #enable
578 592 data.extend((129, 1))
579 593
580 594 if raw:
581 595 return b64encode(data)
582 596
583 597 try:
584 598 payload = self.request('stop', 'post')
585 599 payload = self.request('reset', 'post')
586 600 #payload = self.request('divider', 'post', data={'divider': self.clock_divider-1})
587 601 #payload = self.request('write', 'post', data=b64encode(bytearray((139, 62))), timeout=20)
588 602 n = len(data)
589 603 x = 0
590 604 #while x < n:
591 605 payload = self.request('write', 'post', data=b64encode(data))
592 606 # x += 1024
593 607
594 608 if payload['write']=='ok':
595 609 self.device.status = 3
596 610 self.device.save()
597 611 self.message = 'RC configured and started'
598 612 else:
599 613 self.device.status = 1
600 614 self.device.save()
601 615 self.message = 'RC write: {}'.format(payload['write'])
602 616 return False
603 617
604 618 #payload = self.request('start', 'post')
605 619
606 620 except Exception as e:
607 621 if 'No route to host' not in str(e):
608 622 self.device.status = 4
609 623 else:
610 624 self.device.status = 0
611 625 self.message = 'RC write: {}'.format(str(e))
612 626 self.device.save()
613 627 return False
614 628
615 629 return True
616 630
617 631
618 632 def get_absolute_url_import(self):
619 633 return reverse('url_import_rc_conf', args=[str(self.id)])
620 634
621 635
622 636 class RCLineCode(models.Model):
623 637
624 638 name = models.CharField(max_length=40)
625 639 bits_per_code = models.PositiveIntegerField(default=0)
626 640 number_of_codes = models.PositiveIntegerField(default=0)
627 641 codes = models.TextField(blank=True, null=True)
628 642
629 643 class Meta:
630 644 db_table = 'rc_line_codes'
631 645 ordering = ('name',)
632 646
633 647 def __str__(self):
634 648 return u'%s' % self.name
635 649
636 650
637 651 class RCLineType(models.Model):
638 652
639 653 name = models.CharField(choices=LINE_TYPES, max_length=40)
640 654 description = models.TextField(blank=True, null=True)
641 655 params = models.TextField(default='[]')
642 656
643 657 class Meta:
644 658 db_table = 'rc_line_types'
645 659
646 660 def __str__(self):
647 661 return u'%s - %s' % (self.name.upper(), self.get_name_display())
648 662
649 663
650 664 class RCLine(models.Model):
651 665
652 666 rc_configuration = models.ForeignKey(RCConfiguration, on_delete=models.CASCADE)
653 667 line_type = models.ForeignKey(RCLineType)
654 668 channel = models.PositiveIntegerField(default=0)
655 669 position = models.PositiveIntegerField(default=0)
656 670 params = models.TextField(default='{}')
657 671 pulses = models.TextField(default='')
658 672
659 673 class Meta:
660 674 db_table = 'rc_lines'
661 675 ordering = ['channel']
662 676
663 677 def __str__(self):
664 678 if self.rc_configuration:
665 679 return u'{}|{} - {}'.format(self.pk, self.get_name(), self.rc_configuration.name)
666 680
667 681 def jsonify(self):
668 682
669 683 data = {}
670 684 data['params'] = json.loads(self.params)
671 685 data['id'] = '{}'.format(self.pk)
672 686 data['line_type'] = self.line_type.name
673 687 data['name'] = self.get_name()
674 688 if data['line_type']=='codes':
675 689 data['params']['code'] = RCLineCode.objects.get(pk=data['params']['code']).name
676 690
677 691 return data
678 692
679 693
680 694 def clone(self, **kwargs):
681 695
682 696 self.pk = None
683 697 self.id = None
684 698
685 699 for attr, value in kwargs.items():
686 700 setattr(self, attr, value)
687 701
688 702 self.save()
689 703
690 704 return self
691 705
692 706 def get_name(self, channel=False):
693 707
694 708 chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
695 709 s = ''
696 710
697 711 if self.line_type.name in ('tx',):
698 712 s = chars[self.position]
699 713 elif self.line_type.name in ('codes', 'windows', 'tr'):
700 714 if 'TX_ref' in json.loads(self.params):
701 715 pk = json.loads(self.params)['TX_ref']
702 716 if pk in (0, '0'):
703 717 s = ','.join(chars[l.position] for l in self.rc_configuration.get_lines(line_type__name='tx'))
704 718 else:
705 719 ref = RCLine.objects.get(pk=pk)
706 720 s = chars[ref.position]
707 721 s = '({})'.format(s)
708 722
709 723 s = '{}{}'.format(self.line_type.name.upper(), s)
710 724
711 725 if channel:
712 726 return '{} {}'.format(s, self.channel)
713 727 else:
714 728 return s
715 729
716 730 def get_lines(self, **kwargs):
717 731
718 732 return RCLine.objects.filter(rc_configuration=self.rc_configuration, **kwargs)
719 733
720 734 def pulses_as_array(self):
721 735
722 736 y = np.zeros(self.rc_configuration.total_units)
723 737
724 738 for tup in ast.literal_eval(self.pulses):
725 739 y[tup[0]:tup[1]] = 1
726 740
727 741 return y.astype(np.int8)
728 742
729 743 def pulses_as_points(self, km=False):
730 744
731 745 if km:
732 746 unit2km = 1/self.rc_configuration.km2unit
733 747 return [(tup[0]*unit2km, tup[1]*unit2km) for tup in ast.literal_eval(self.pulses)]
734 748 else:
735 749 return ast.literal_eval(self.pulses)
736 750
737 751 def get_win_ref(self, params, tx_id, km2unit):
738 752
739 753 ref = self.rc_configuration.sampling_reference
740 754 codes = [line for line in self.get_lines(line_type__name='codes') if int(json.loads(line.params)['TX_ref'])==int(tx_id)]
741 755
742 756 if codes:
743 757 tx_width = float(json.loads(RCLine.objects.get(pk=tx_id).params)['pulse_width'])*km2unit/len(json.loads(codes[0].params)['codes'][0])
744 758 else:
745 759 tx_width = float(json.loads(RCLine.objects.get(pk=tx_id).params)['pulse_width'])*km2unit
746 760
747 761 if ref=='first_baud':
748 762 return int(1 + round((tx_width + 1)/2 + params['first_height']*km2unit - params['resolution']*km2unit))
749 763 elif ref=='sub_baud':
750 764 return np.ceil(1 + params['first_height']*km2unit - params['resolution']*km2unit/2)
751 765 else:
752 766 return 0
753 767
754 768 def update_pulses(self):
755 769 '''
756 770 Update pulses field
757 771 '''
758 772
759 773 km2unit = self.rc_configuration.km2unit
760 774 us2unit = self.rc_configuration.us2unit
761 775 ipp = self.rc_configuration.ipp
762 776 ntx = int(self.rc_configuration.ntx)
763 777 ipp_u = int(ipp*km2unit)
764 778 total = ipp_u*ntx if self.rc_configuration.total_units==0 else self.rc_configuration.total_units
765 779 y = []
766 780
767 781 if self.line_type.name=='tr':
768 782 tr_params = json.loads(self.params)
769 783
770 784 if tr_params['TX_ref'] in ('0', 0):
771 785 txs = self.get_lines(line_type__name='tx')
772 786 else:
773 787 txs = RCLine.objects.filter(pk=tr_params['TX_ref'])
774 788
775 789 for tx in txs:
776 790 params = json.loads(tx.params)
777 791
778 792 if float(params['pulse_width'])==0:
779 793 continue
780 794 delays = [float(d)*km2unit for d in params['delays'].split(',') if d]
781 795 width = float(params['pulse_width'])*km2unit+int(self.rc_configuration.time_before*us2unit)
782 796 before = 0
783 797 after = int(self.rc_configuration.time_after*us2unit)
784 798
785 799 y_tx = self.points(ntx, ipp_u, width,
786 800 delay=delays,
787 801 before=before,
788 802 after=after,
789 803 sync=self.rc_configuration.sync)
790 804
791 805 ranges = params['range'].split(',')
792 806
793 807 if len(ranges)>0 and ranges[0]!='0':
794 808 y_tx = self.mask_ranges(y_tx, ranges)
795 809
796 810 tr_ranges = tr_params['range'].split(',')
797 811
798 812 if len(tr_ranges)>0 and tr_ranges[0]!='0':
799 813 y_tx = self.mask_ranges(y_tx, tr_ranges)
800 814
801 815 y.extend(y_tx)
802 816
803 817 self.pulses = str(y)
804 818 y = self.array_to_points(self.pulses_as_array())
805 819
806 820 elif self.line_type.name=='tx':
807 821 params = json.loads(self.params)
808 822 delays = [float(d)*km2unit for d in params['delays'].split(',') if d]
809 823 width = float(params['pulse_width'])*km2unit
810 824
811 825 if width>0:
812 826 before = int(self.rc_configuration.time_before*us2unit)
813 827 after = 0
814 828
815 829 y = self.points(ntx, ipp_u, width,
816 830 delay=delays,
817 831 before=before,
818 832 after=after,
819 833 sync=self.rc_configuration.sync)
820 834
821 835 ranges = params['range'].split(',')
822 836
823 837 if len(ranges)>0 and ranges[0]!='0':
824 838 y = self.mask_ranges(y, ranges)
825 839
826 840 elif self.line_type.name=='flip':
827 841 n = float(json.loads(self.params)['number_of_flips'])
828 842 width = n*ipp*km2unit
829 843 y = self.points(int((ntx+1)/(2*n)), ipp_u*n*2, width)
830 844
831 845 elif self.line_type.name=='codes':
832 846 params = json.loads(self.params)
833 847 tx = RCLine.objects.get(pk=params['TX_ref'])
834 848 tx_params = json.loads(tx.params)
835 849 delays = [float(d)*km2unit for d in tx_params['delays'].split(',') if d]
836 850 f = int(float(tx_params['pulse_width'])*km2unit/len(params['codes'][0]))
837 851 codes = [(np.fromstring(''.join([s*f for s in code]), dtype=np.uint8)-48).astype(np.int8) for code in params['codes']]
838 852 codes = [self.array_to_points(code) for code in codes]
839 853 n = len(codes)
840 854
841 855 ranges = tx_params['range'].split(',')
842 856 if len(ranges)>0 and ranges[0]!='0':
843 857 dum = self.mask_ranges(tx.pulses_as_points(), ranges)
844 858 else:
845 859 dum = tx.pulses_as_points()
846 860
847 861 for i, tup in enumerate(dum):
848 862 if tup==(0,0): continue
849 863 code = codes[i%n]
850 864 y.extend([(c[0]+tup[0], c[1]+tup[0]) for c in code])
851 865
852 866 elif self.line_type.name=='sync':
853 867 params = json.loads(self.params)
854 868 n = ipp_u*ntx
855 869 if params['invert'] in ('1', 1):
856 870 y = [(n-1, n)]
857 871 else:
858 872 y = [(0, 1)]
859 873
860 874 elif self.line_type.name=='prog_pulses':
861 875 params = json.loads(self.params)
862 876 if int(params['periodic'])==0:
863 877 nntx = 1
864 878 nipp = ipp_u*ntx
865 879 else:
866 880 nntx = ntx
867 881 nipp = ipp_u
868 882
869 883 if 'params' in params and len(params['params'])>0:
870 884 for p in params['params']:
871 885 y_pp = self.points(nntx, nipp,
872 886 p['end']-p['begin'],
873 887 before=p['begin'])
874 888
875 889 y.extend(y_pp)
876 890
877 891 elif self.line_type.name=='windows':
878 892 params = json.loads(self.params)
879 893 if 'params' in params and len(params['params'])>0:
880 894 tx = RCLine.objects.get(pk=params['TX_ref'])
881 895 tx_params = json.loads(tx.params)
882 896 ranges = tx_params['range'].split(',')
883 897 for p in params['params']:
884 898 y_win = self.points(ntx, ipp_u,
885 899 p['resolution']*p['number_of_samples']*km2unit,
886 900 before=int(self.rc_configuration.time_before*us2unit)+p['first_height']*km2unit,
887 901 sync=self.rc_configuration.sync+self.get_win_ref(p, params['TX_ref'], km2unit))
888 902
889 903
890 904 if len(ranges)>0 and ranges[0]!='0':
891 905 y_win = self.mask_ranges(y_win, ranges)
892 906
893 907 y.extend(y_win)
894 908
895 909 elif self.line_type.name=='mix':
896 910 values = self.rc_configuration.parameters.split('-')
897 911 confs = [RCConfiguration.objects.get(pk=value.split('|')[0]) for value in values]
898 912 modes = [value.split('|')[1] for value in values]
899 913 ops = [value.split('|')[2] for value in values]
900 914 delays = [value.split('|')[3] for value in values]
901 915 masks = [value.split('|')[4] for value in values]
902 916 mask = list('{:8b}'.format(int(masks[0])))
903 917 mask.reverse()
904 918 if mask[self.channel] in ('0', '', ' '):
905 919 y = np.zeros(confs[0].total_units, dtype=np.int8)
906 920 else:
907 921 y = confs[0].get_lines(channel=self.channel)[0].pulses_as_array()
908 922
909 923 for i in range(1, len(values)):
910 924 mask = list('{:8b}'.format(int(masks[i])))
911 925 mask.reverse()
912 926
913 927 if mask[self.channel] in ('0', '', ' '):
914 928 continue
915 929 Y = confs[i].get_lines(channel=self.channel)[0].pulses_as_array()
916 930 delay = float(delays[i])*km2unit
917 931
918 932 if modes[i]=='P':
919 933 if delay>0:
920 934 if delay<self.rc_configuration.ipp*km2unit and len(Y)==len(y):
921 935 y_temp = np.empty_like(Y)
922 936 y_temp[:delay] = 0
923 937 y_temp[delay:] = Y[:-delay]
924 938 elif delay+len(Y)>len(y):
925 939 y_new = np.zeros(delay+len(Y), dtype=np.int8)
926 940 y_new[:len(y)] = y
927 941 y = y_new
928 942 y_temp = np.zeros(delay+len(Y), dtype=np.int8)
929 943 y_temp[-len(Y):] = Y
930 944 elif delay+len(Y)==len(y):
931 945 y_temp = np.zeros(delay+len(Y))
932 946 y_temp[-len(Y):] = Y
933 947 elif delay+len(Y)<len(y):
934 948 y_temp = np.zeros(len(y), dtype=np.int8)
935 949 y_temp[delay:delay+len(Y)] = Y
936 950 else:
937 951 y_temp = Y.copy()
938 952
939 953 if ops[i]=='OR':
940 954 y = y | y_temp
941 955 elif ops[i]=='XOR':
942 956 y = y ^ y_temp
943 957 elif ops[i]=='AND':
944 958 y = y & y_temp
945 959 elif ops[i]=='NAND':
946 960 y = y & ~y_temp
947 961 else:
948 962 y = np.concatenate([y, Y])
949 963
950 964 total = len(y)
951 965 y = self.array_to_points(y)
952 966
953 967 else:
954 968 y = []
955 969
956 970 if self.rc_configuration.total_units != total:
957 971 self.rc_configuration.total_units = total
958 972 self.rc_configuration.save()
959 973
960 974 self.pulses = str(y)
961 975 self.save()
962 976
963 977 @staticmethod
964 978 def array_to_points(X):
965 979
966 980 if X.size==0:
967 981 return []
968 982
969 983 d = X[1:]-X[:-1]
970 984
971 985 up = np.where(d==1)[0]
972 986 if X[0]==1:
973 987 up = np.concatenate((np.array([-1]), up))
974 988 up += 1
975 989
976 990 dw = np.where(d==-1)[0]
977 991 if X[-1]==1:
978 992 dw = np.concatenate((dw, np.array([len(X)-1])))
979 993 dw += 1
980 994
981 995 return [(tup[0], tup[1]) for tup in zip(up, dw)]
982 996
983 997 @staticmethod
984 998 def mask_ranges(Y, ranges):
985 999
986 1000 y = [(0, 0) for __ in Y]
987 1001
988 1002 for index in ranges:
989 1003 if '-' in index:
990 1004 args = [int(a) for a in index.split('-')]
991 1005 y[args[0]-1:args[1]] = Y[args[0]-1:args[1]]
992 1006 else:
993 1007 y[int(index)-1] = Y[int(index)-1]
994 1008
995 1009 return y
996 1010
997 1011 @staticmethod
998 1012 def points(ntx, ipp, width, delay=[0], before=0, after=0, sync=0):
999 1013
1000 1014 delays = len(delay)
1001 1015
1002 1016 Y = [(int(ipp*x+before+delay[x%delays]+sync), int(ipp*x+width+before+delay[x%delays]+after+sync)) for x in range(ntx)]
1003 1017
1004 1018 return Y
1019
1020 class RCClock(models.Model):
1021
1022 rc_configuration = models.ForeignKey(RCConfiguration, on_delete=models.CASCADE)
1023 mode = models.BooleanField(default=True, choices=((True, 'Auto'), (False, 'Manual')))
1024 multiplier = models.PositiveIntegerField(default=60)
1025 divisor = models.PositiveIntegerField(default=10)
1026 reference = models.PositiveSmallIntegerField(default=1, choices=((0, 'Internal (25MHz)'), (1, 'External (10MHz)')))
1027 frequency = models.FloatField(default=60.0) No newline at end of file
@@ -1,120 +1,161
1 1 var km_fields = [];
2 2 var unit_fields = [];
3 3 var dc_fields = [];
4 4
5 5
6 6 function str2hz(s){
7 7
8 8 return 150000*Math.pow(parseFloat(s), -1);
9 9 }
10 10
11 11
12 12 function str2unit(s){
13 13 var km2unit = (20/3)*(parseFloat($('#id_clock_in').val())/parseFloat($('#id_clock_divider').val()));
14 14 var ret = "";
15 15 values = s.split(",");
16 16 for (i=0; i<values.length; i++) {
17 17 ret += Math.round(parseFloat(values[i])*km2unit);
18 18 ret += ",";
19 19 }
20 20 return ret.substring(0, ret.length-1);
21 21 }
22 22
23 23
24 24 function str2int(s){
25 25 var ret = "";
26 26 values = s.split(",");
27 27 for (i=0; i<values.length; i++) {
28 28 ret += Math.round(parseFloat(values[i]));
29 29 ret += ",";
30 30 }
31 31 return ret.substring(0, ret.length-1);
32 32 }
33 33
34 34
35 35 function str2km(s){
36 36 var km2unit = (20/3)*(parseFloat($('#id_clock_in').val())/parseFloat($('#id_clock_divider').val()));
37 37 var ret = "";
38 38 values = s.split(",");
39 39 for (i=0; i<values.length; i++) {
40 40 ret += parseFloat(values[i])/km2unit;
41 41 ret += ",";
42 42 }
43 43 return ret.substring(0, ret.length-1);
44 44 }
45 45
46 46 function str2dc(s){
47 47
48 48 return parseFloat(s)*100/parseFloat($('#id_ipp').val())
49 49 }
50 50
51 51
52 52 function updateUnits() {
53 53
54 54 for (j=0; j<km_fields.length; j++){
55 55 label_unit = "#"+km_fields[j]+"_unit";
56 56 label = "#"+km_fields[j];
57 57 $(label_unit).val(str2unit($(label).val()));
58 58 }
59 59 }
60 60
61 61
62 62 function updateDc() {
63 63
64 64 for (j=0; j<dc_fields.length; j++){
65 65 label_dc = "#"+dc_fields[j]+"_dc";
66 66 label = "#"+dc_fields[j];
67 67 $(label_dc).val(str2dc($(label).val()));
68 68 }
69 69 }
70 70
71 71
72 72 function updateWindows(label) {
73 73
74 74 if (label.indexOf("first_height")>0){
75 75 llabel = label.replace("first_height", "last_height");
76 76 rlabel = label.replace("first_height", "resolution");
77 77 nlabel = label.replace("first_height", "number_of_samples");
78 78 value = parseFloat($(label).val())+parseFloat($(rlabel).val())*(parseInt($(nlabel).val())-1);
79 79 $(llabel).val(value);
80 80 }
81 81
82 82 if (label.indexOf("resolution")>0){
83 83 llabel = label.replace("resolution", "last_height");
84 84 flabel = label.replace("resolution", "first_height");
85 85 nlabel = label.replace("resolution", "number_of_samples");
86 86 value = parseFloat($(flabel).val())+parseFloat($(label).val())*(parseInt($(nlabel).val())-1);
87 87 $(llabel).val(value);
88 88 }
89 89
90 90 if (label.indexOf("number_of_samples")>0){
91 91 llabel = label.replace("number_of_samples", "last_height");
92 92 rlabel = label.replace("number_of_samples", "resolution");
93 93 flabel = label.replace("number_of_samples", "first_height");
94 94 value = parseFloat($(flabel).val())+parseFloat($(rlabel).val())*(parseInt($(label).val())-1);
95 95 $(llabel).val(value);
96 96 }
97 97
98 98 if (label.indexOf("last_height")>0){
99 99 flabel = label.replace("last_height", "first_height");
100 100 rlabel = label.replace("last_height", "resolution");
101 101 nlabel = label.replace("last_height", "number_of_samples");
102 102
103 103 nvalue = Math.round((parseFloat($(label).val())-parseFloat($(flabel).val()))/parseFloat($(rlabel).val()))+1;
104 104 $(nlabel).val(nvalue);
105 105 value = parseFloat($(flabel).val())+parseFloat($(rlabel).val())*(nvalue-1);
106 106 $(label).val(value);
107 107 }
108 108
109 109 }
110 110
111 $("#id_clock_in").change(function() {
112 $("#id_clock").val(parseFloat($('#id_clock_in').val())/parseFloat($('#id_clock_divider').val()));
111 function updateClock() {
112 if ($("#id_reference").val()==0){
113 var ref = 25;
114 }else{
115 var ref = 10;
116 }
117 $("#id_frequency").val(parseFloat($('#id_multiplier').val())*ref/parseFloat($('#id_divisor').val()));
118 $("#id_clock").val(parseFloat($('#id_frequency').val())/parseFloat($('#id_clock_divider').val()));
119 updateUnits();
120 }
121
122
123 $("#id_frequency").change(function() {
124 $("#id_clock").val(parseFloat($('#id_frequency').val())/parseFloat($('#id_clock_divider').val()));
113 125 updateUnits();
114 126 });
115 127
116 128 $("#id_clock_divider").change(function() {
117 $("#id_clock").val(parseFloat($('#id_clock_in').val())/parseFloat($('#id_clock_divider').val()));
129 $("#id_clock").val(parseFloat($('#id_frequency').val())/parseFloat($('#id_clock_divider').val()));
118 130 updateUnits();
119 131 });
120 132
133 $("#id_mode").change(function() {
134 if ($("#id_mode").val()=="False"){
135 $('#id_multiplier').removeProp("readonly");
136 $('#id_divisor').removeProp("readonly");
137 $('#id_reference').removeProp("readonly");
138 $('#id_frequency').prop("readonly", true);
139 updateClock();
140 }else{
141 $('#id_frequency').removeProp("readonly");
142 $('#id_multiplier').prop("readonly", true);
143 $('#id_divisor').prop("readonly", true);
144 $('#id_reference').prop("readonly", true);
145 $('#id_reference').val(1)
146 $('#id_frequency').val(60);
147 $("#id_clock").val(parseFloat($('#id_frequency').val())/parseFloat($('#id_clock_divider').val()));
148 }
149 });
150
151 $("#id_multiplier").change(function() {
152 updateClock();
153 });
154
155 $("#id_divisor").change(function() {
156 updateClock();
157 });
158
159 $("#id_reference").change(function() {
160 updateClock();
161 }); No newline at end of file
@@ -1,27 +1,61
1 1 {% extends "dev_conf.html" %}
2 2 {% load static %}
3 3 {% load bootstrap3 %}
4 4 {% load main_tags %}
5 5
6 6 {% block extra-menu-actions %}
7 7 <li><a href="{{ dev_conf.get_absolute_url_plot }}" target="_blank"><span class="glyphicon glyphicon-picture" aria-hidden="true"></span> View Pulses </a></li>
8 8 {% endblock %}
9 9
10 {% block content-detail %}
11
12 <h2>Clock</h2>
13 <table class="table table-bordered">
14 <tr>
15 <th>Mode</th>
16 <td>{{clock.get_mode_display}}</td>
17 </tr>
18 <tr>
19 <th>Reference</th>
20 <td>{{clock.get_reference_display}}</td>
21 </tr>
22 <tr>
23 <th>Frequency</th>
24 <td>{{clock.frequency}}</td>
25 </tr>
26 </table>
27 <div class="clearfix"></div>
28 <h2>RC</h2>
29 <table class="table table-bordered">
30 <tr>
31 <th>Status</th>
32 <td class="text-{{dev_conf.device.status_color}}"><strong>{{dev_conf.device.get_status_display}}</strong></td>
33 </tr>
34
35 {% for key in dev_conf_keys %}
36 <tr>
37 <th>{% get_verbose_field_name dev_conf key %}</th>
38 <td>{{dev_conf|attr:key}}</td>
39 </tr>
40 {% endfor %}
41 </table>
42 {% endblock %}
43
10 44 {% block extra-content %}
11 45
12 46 <div class="clearfix"></div>
13 47 <h2>RC Lines</h2>
14 48 <br>
15 49 <div class="panel-group" id="div_lines" role="tablist" aria-multiselectable="true">
16 50 {% include "rc_lines.html" %}
17 51 </div>
18 52
19 53 {% endblock extra-content%}
20 54
21 55 {% block extra-js%}
22 56 <script type="text/javascript">
23 57 $("#bt_toggle").click(function() {
24 58 $(".panel-collapse").collapse('toggle')
25 59 });
26 60 </script>
27 61 {% endblock %} No newline at end of file
@@ -1,77 +1,81
1 1 {% extends "dev_conf_edit.html" %}
2 2 {% load bootstrap3 %}
3 3 {% load static %}
4 4
5 5 {% block extra-head %}
6 6 <style type="text/css">
7 7 /* show the move cursor as the user moves the mouse over the panel header.*/
8 8 .panel-default { cursor: move; }
9 9 </style>
10 10 <script src="{% static 'js/jquery-ui.min.js' %}"></script>
11 11
12 12 {% endblock %}
13 13
14 14 {% block content %}
15 15 <form class="form" method="post">
16 16 {% csrf_token %}
17 <h2>Clock</h2>
18 {% bootstrap_form form_clock layout='horizontal' size='medium' %}
19 <div style="clear: both;"></div>
20 <h2>RC</h2>
17 21 {% bootstrap_form form layout='horizontal' size='medium' %}
18 22 <div style="clear: both;"></div>
19 <h2>RC Lines</h2><hr>
23 <h2>RC Lines</h2>
20 24 <div class="panel-group" id="div_lines" role="tablist" aria-multiselectable="true">
21 25 {% include "rc_lines.html" %}
22 26 </div>
23 27 <div style="clear: both;"></div>
24 28 <br>
25 29 <div class="pull-right">
26 30 <button type="button" class="btn btn-primary" onclick="{% if previous %}window.location.replace('{{ previous }}');{% else %}history.go(-1);{% endif %}">Cancel</button>
27 31 <button type="button" class="btn btn-primary" id="bt_add_line">Add Line</button>
28 32 <button type="submit" class="btn btn-primary">{{button}}</button>
29 33 </div>
30 34 </form>
31 35 {% endblock %}
32 36
33 37 {% block extra-js%}
34 38
35 39 <script src="{% static 'js/cr.js' %}"></script>
36 40
37 41 <script type="text/javascript">
38 42
39 43 $("#div_lines").on("click", "button[name=bt_remove_line]", function(){
40 44 document.location = "/rc/{{dev_conf.id}}/line/"+$(this).val()+"/delete/";
41 45 });
42 46
43 47 $("#div_lines").on("click", "button[name=bt_remove_subline]", function(){
44 48 document.location = $(this).data('url');
45 49 });
46 50
47 51 $("#div_lines").on("click", "button[name=bt_add_subline]", function(){
48 52 document.location = "/rc/{{dev_conf.id}}/line/"+$(this).val()+"/add_subline/";
49 53 });
50 54
51 55 $("#div_lines").on("click", "button[name=bt_edit_codes]", function(){
52 56 document.location = "/rc/{{dev_conf.id}}/line/"+$(this).val()+"/codes/";
53 57 });
54 58
55 59 $("#bt_add_line").click(function() {
56 60 document.location = "{% url 'url_add_rc_line' dev_conf.id%}";
57 61 });
58 62
59 63 $(".panel-group").sortable({
60 64 //placeholder: "ui-state-highlight",
61 65 update: function( event, ui ) {
62 66 var sorted = $( ".panel-group" ).sortable( "serialize", { key: "item" } );
63 67 var url = "{% url 'url_update_rc_lines_position' dev_conf.id %}";
64 68 var csrf_token = "{{csrf_token}}";
65 69 $.post( url, { 'items': sorted, 'csrfmiddlewaretoken': csrf_token }, function(data){
66 70 $("#div_lines").html(data.html);
67 71 });
68 72 }
69 73 });
70 74
71 75 $("#bt_toggle").click(function() {
72 76 $(".panel-collapse").collapse('toggle')
73 77 });
74 78
75 79 </script>
76 80 {% endblock %}
77 81 No newline at end of file
@@ -1,407 +1,417
1 1
2 2 import json
3 3
4 4 from django.contrib import messages
5 5 from django.utils.safestring import mark_safe
6 6 from django.shortcuts import render, redirect, get_object_or_404, HttpResponse
7 7 from django.contrib.auth.decorators import login_required
8 8
9 9 from apps.main.models import Experiment, Device
10 10 from apps.main.views import sidebar
11 11
12 from .models import RCConfiguration, RCLine, RCLineType, RCLineCode
13 from .forms import RCConfigurationForm, RCLineForm, RCLineViewForm, RCLineEditForm, RCImportForm, RCLineCodesForm
12 from .models import RCConfiguration, RCLine, RCLineType, RCLineCode, RCClock
13 from .forms import RCConfigurationForm, RCLineForm, RCLineViewForm, RCLineEditForm, RCImportForm, RCLineCodesForm, RCClockForm
14 14
15 15
16 16 def conf(request, conf_id):
17 17
18 18 conf = get_object_or_404(RCConfiguration, pk=conf_id)
19 19
20 20 lines = RCLine.objects.filter(rc_configuration=conf).order_by('channel')
21 clk = RCClock.objects.get(rc_configuration=conf)
21 22
22 23 for line in lines:
23 24 params = json.loads(line.params)
24 25 line.form = RCLineViewForm(extra_fields=params, line=line)
25 26 if 'params' in params:
26 27 line.subforms = [RCLineViewForm(extra_fields=fields, line=line, subform=True) for fields in params['params']]
27 28
28 29 kwargs = {}
30 kwargs['clock'] = clk
29 31 kwargs['dev_conf'] = conf
30 32 kwargs['rc_lines'] = lines
31 kwargs['dev_conf_keys'] = ['ipp_unit', 'ntx', 'clock_in', 'clock_divider', 'clock',
33 kwargs['dev_conf_keys'] = ['ipp_unit', 'ntx', 'clock_divider', 'clock',
32 34 'time_before', 'time_after', 'sync', 'sampling_reference',
33 35 'control_tx', 'control_sw']
34 36
35 37 kwargs['title'] = 'Configuration'
36 38 kwargs['suptitle'] = 'Detail'
37 39
38 40 kwargs['button'] = 'Edit Configuration'
39 41 ###### SIDEBAR ######
40 42 kwargs.update(sidebar(conf=conf))
41 43
42 44 return render(request, 'rc_conf.html', kwargs)
43 45
44 46 @login_required
45 47 def conf_edit(request, conf_id):
46 48
47 49 conf = get_object_or_404(RCConfiguration, pk=conf_id)
48
50 clock = RCClock.objects.get(rc_configuration=conf)
49 51 lines = RCLine.objects.filter(rc_configuration=conf).order_by('channel')
50 52
51 53 for line in lines:
52 54 params = json.loads(line.params)
53 55 line.form = RCLineEditForm(conf=conf, line=line, extra_fields=params)
54 56 line.subform = False
55 57
56 58 if 'params' in params:
57 59 line.subforms = [RCLineEditForm(extra_fields=fields, line=line, subform=i) for i, fields in enumerate(params['params'])]
58 60 line.subform = True
59 61
60 62 if request.method=='GET':
61 63
62 64 form = RCConfigurationForm(instance=conf)
65 form_clock = RCClockForm(instance=clock)
63 66
64 67 elif request.method=='POST':
65 68
66 69 line_data = {}
67 70 conf_data = {}
71 clock_data = {}
68 72 extras = []
69 73
70 74 #classified post fields
71 75 for label,value in request.POST.items():
72 76 if label=='csrfmiddlewaretoken':
73 77 continue
74 78
75 79 if label.count('|')==0:
80 if label in ('mode', 'multiplier', 'divisor', 'reference', 'frequency'):
81 clock_data[label] = value
82 else:
76 83 conf_data[label] = value
77 84 continue
78 85
79 86 elif label.split('|')[0]!='-1':
80 87 extras.append(label)
81 88 continue
82 89
83 90 x, pk, name = label.split('|')
84 91
85 92 if name=='codes':
86 93 value = [s for s in value.split('\r\n') if s]
87 94
88 95 if pk in line_data:
89 96 line_data[pk][name] = value
90 97 else:
91 98 line_data[pk] = {name:value}
92 99
93 100 #update conf
94 form = RCConfigurationForm(conf_data, instance=conf)
95 101
96 if form.is_valid():
102 form_clock = RCClockForm(clock_data, instance=clock)
103 form = RCConfigurationForm(conf_data, instance=conf)
97 104
105 if form_clock.is_valid() and form.is_valid():
106 form_clock.save()
98 107 form.save()
99 108
100 109 #update lines fields
101 110 extras.sort()
102 111 for label in extras:
103 112 x, pk, name = label.split('|')
104 113 if pk not in line_data:
105 114 line_data[pk] = {}
106 115 if 'params' not in line_data[pk]:
107 116 line_data[pk]['params'] = []
108 117 if len(line_data[pk]['params'])<int(x)+1:
109 118 line_data[pk]['params'].append({})
110 119 line_data[pk]['params'][int(x)][name] = float(request.POST[label])
111 120
112 121 for pk, params in line_data.items():
113 122 line = RCLine.objects.get(pk=pk)
114 123 if line.line_type.name in ('windows', 'prog_pulses'):
115 124 if 'params' not in params:
116 125 params['params'] = []
117 126 line.params = json.dumps(params)
118 127 line.save()
119 128
120 129 #update pulses field
121 130 conf.update_pulses()
122 131
123 132 messages.success(request, 'RC Configuration successfully updated')
124 133
125 134 return redirect(conf.get_absolute_url())
126 135
127 136 kwargs = {}
128 137 kwargs['dev_conf'] = conf
129 138 kwargs['form'] = form
139 kwargs['form_clock'] = form_clock
130 140 kwargs['rc_lines'] = lines
131 141 kwargs['edit'] = True
132 142
133 143 kwargs['title'] = 'RC Configuration'
134 144 kwargs['suptitle'] = 'Edit'
135 145 kwargs['button'] = 'Update'
136 146
137 147 return render(request, 'rc_conf_edit.html', kwargs)
138 148
139 149
140 150 def add_line(request, conf_id, line_type_id=None, code_id=None):
141 151
142 152 conf = get_object_or_404(RCConfiguration, pk=conf_id)
143 153
144 154 if request.method=='GET':
145 155 if line_type_id:
146 156 line_type = get_object_or_404(RCLineType, pk=line_type_id)
147 157
148 158 if code_id:
149 159 form = RCLineForm(initial={'rc_configuration':conf_id, 'line_type': line_type_id, 'code_id': code_id},
150 160 extra_fields=json.loads(line_type.params))
151 161 else:
152 162 form = RCLineForm(initial={'rc_configuration':conf_id, 'line_type': line_type_id},
153 163 extra_fields=json.loads(line_type.params))
154 164 else:
155 165 line_type = {'id':0}
156 166 form = RCLineForm(initial={'rc_configuration':conf_id})
157 167
158 168 if request.method=='POST':
159 169
160 170 line_type = get_object_or_404(RCLineType, pk=line_type_id)
161 171 form = RCLineForm(request.POST,
162 172 extra_fields=json.loads(line_type.params))
163 173
164 174 if form.is_valid():
165 175 form.save()
166 176 form.instance.update_pulses()
167 177 return redirect('url_edit_rc_conf', conf.id)
168 178
169 179 kwargs = {}
170 180 kwargs['form'] = form
171 181 kwargs['title'] = 'RC Configuration'
172 182 kwargs['suptitle'] = 'Add Line'
173 183 kwargs['button'] = 'Add'
174 184 kwargs['previous'] = conf.get_absolute_url_edit()
175 185 kwargs['dev_conf'] = conf
176 186 kwargs['line_type'] = line_type
177 187
178 188 return render(request, 'rc_add_line.html', kwargs)
179 189
180 190 def edit_codes(request, conf_id, line_id, code_id=None):
181 191
182 192 conf = get_object_or_404(RCConfiguration, pk=conf_id)
183 193 line = get_object_or_404(RCLine, pk=line_id)
184 194 params = json.loads(line.params)
185 195
186 196 if request.method=='GET':
187 197 if code_id:
188 198 code = get_object_or_404(RCLineCode, pk=code_id)
189 199 form = RCLineCodesForm(instance=code)
190 200 else:
191 201 initial = {'code': params['code'],
192 202 'codes': params['codes'] if 'codes' in params else [],
193 203 'number_of_codes': len(params['codes']) if 'codes' in params else 0,
194 204 'bits_per_code': len(params['codes'][0]) if 'codes' in params else 0,
195 205 }
196 206 form = RCLineCodesForm(initial=initial)
197 207
198 208 if request.method=='POST':
199 209 form = RCLineCodesForm(request.POST)
200 210 if form.is_valid():
201 211 params['code'] = request.POST['code']
202 212 params['codes'] = [s for s in request.POST['codes'].split('\r\n') if s]
203 213 line.params = json.dumps(params)
204 214 line.save()
205 215 messages.success(request, 'Line: "%s" has been updated.' % line)
206 216 return redirect('url_edit_rc_conf', conf.id)
207 217
208 218 kwargs = {}
209 219 kwargs['form'] = form
210 220 kwargs['title'] = line
211 221 kwargs['suptitle'] = 'Edit'
212 222 kwargs['button'] = 'Update'
213 223 kwargs['dev_conf'] = conf
214 224 kwargs['previous'] = conf.get_absolute_url_edit()
215 225 kwargs['line'] = line
216 226
217 227 return render(request, 'rc_edit_codes.html', kwargs)
218 228
219 229 def add_subline(request, conf_id, line_id):
220 230
221 231 conf = get_object_or_404(RCConfiguration, pk=conf_id)
222 232 line = get_object_or_404(RCLine, pk=line_id)
223 233
224 234 if request.method == 'POST':
225 235 if line:
226 236 params = json.loads(line.params)
227 237 subparams = json.loads(line.line_type.params)
228 238 if 'params' in subparams:
229 239 dum = {}
230 240 for key, value in subparams['params'].items():
231 241 dum[key] = value['value']
232 242 params['params'].append(dum)
233 243 line.params = json.dumps(params)
234 244 line.save()
235 245 return redirect('url_edit_rc_conf', conf.id)
236 246
237 247 kwargs = {}
238 248
239 249 kwargs['title'] = 'Add new'
240 250 kwargs['suptitle'] = '%s to %s' % (line.line_type.name, line)
241 251
242 252 return render(request, 'confirm.html', kwargs)
243 253
244 254 def remove_line(request, conf_id, line_id):
245 255
246 256 conf = get_object_or_404(RCConfiguration, pk=conf_id)
247 257 line = get_object_or_404(RCLine, pk=line_id)
248 258
249 259 if request.method == 'POST':
250 260 if line:
251 261 try:
252 262 channel = line.channel
253 263 line.delete()
254 264 for ch in range(channel+1, RCLine.objects.filter(rc_configuration=conf).count()+1):
255 265 l = RCLine.objects.get(rc_configuration=conf, channel=ch)
256 266 l.channel = l.channel-1
257 267 l.save()
258 268 messages.success(request, 'Line: "%s" has been deleted.' % line)
259 269 except:
260 270 messages.error(request, 'Unable to delete line: "%s".' % line)
261 271
262 272 return redirect('url_edit_rc_conf', conf.id)
263 273
264 274 kwargs = {}
265 275
266 276 kwargs['object'] = line
267 277 kwargs['delete'] = True
268 278 kwargs['title'] = 'Delete'
269 279 kwargs['suptitle'] = 'Line'
270 280 kwargs['previous'] = conf.get_absolute_url_edit()
271 281 return render(request, 'confirm.html', kwargs)
272 282
273 283
274 284 def remove_subline(request, conf_id, line_id, subline_id):
275 285
276 286 conf = get_object_or_404(RCConfiguration, pk=conf_id)
277 287 line = get_object_or_404(RCLine, pk=line_id)
278 288
279 289 if request.method == 'POST':
280 290 if line:
281 291 params = json.loads(line.params)
282 292 params['params'].remove(params['params'][int(subline_id)-1])
283 293 line.params = json.dumps(params)
284 294 line.save()
285 295
286 296 return redirect('url_edit_rc_conf', conf.id)
287 297
288 298 kwargs = {}
289 299
290 300 kwargs['object'] = line
291 301 kwargs['object_name'] = line.line_type.name
292 302 kwargs['delete_view'] = True
293 303 kwargs['title'] = 'Confirm delete'
294 304
295 305 return render(request, 'confirm.html', kwargs)
296 306
297 307
298 308 def update_lines_position(request, conf_id):
299 309
300 310 conf = get_object_or_404(RCConfiguration, pk=conf_id)
301 311
302 312 if request.method=='POST':
303 313 ch = 0
304 314 for item in request.POST['items'].split('&'):
305 315 line = RCLine.objects.get(pk=item.split('=')[-1])
306 316 line.channel = ch
307 317 line.save()
308 318 ch += 1
309 319
310 320 lines = RCLine.objects.filter(rc_configuration=conf).order_by('channel')
311 321
312 322 for line in lines:
313 323 params = json.loads(line.params)
314 324 line.form = RCLineEditForm(conf=conf, line=line, extra_fields=params)
315 325
316 326 if 'params' in params:
317 327 line.subform = True
318 328 line.subforms = [RCLineEditForm(extra_fields=fields, line=line, subform=i) for i, fields in enumerate(params['params'])]
319 329
320 330 html = render(request, 'rc_lines.html', {'dev_conf':conf, 'rc_lines':lines, 'edit':True})
321 331 data = {'html': html.content.decode('utf8')}
322 332
323 333 return HttpResponse(json.dumps(data), content_type="application/json")
324 334 return redirect('url_edit_rc_conf', conf.id)
325 335
326 336
327 337 def import_file(request, conf_id):
328 338
329 339 conf = get_object_or_404(RCConfiguration, pk=conf_id)
330 340 if request.method=='POST':
331 341 form = RCImportForm(request.POST, request.FILES)
332 342 if form.is_valid():
333 343 try:
334 344 data = conf.import_from_file(request.FILES['file_name'])
335 345 conf.dict_to_parms(data)
336 346 conf.update_pulses()
337 347 messages.success(request, 'Configuration "%s" loaded succesfully' % request.FILES['file_name'])
338 348 return redirect(conf.get_absolute_url_edit())
339 349
340 350 except Exception as e:
341 351 messages.error(request, 'Error parsing file: "%s" - %s' % (request.FILES['file_name'], repr(e)))
342 352 else:
343 353 messages.warning(request, 'Your current configuration will be replaced')
344 354 form = RCImportForm()
345 355
346 356 kwargs = {}
347 357 kwargs['form'] = form
348 358 kwargs['title'] = 'RC Configuration'
349 359 kwargs['suptitle'] = 'Import file'
350 360 kwargs['button'] = 'Upload'
351 361 kwargs['previous'] = conf.get_absolute_url()
352 362
353 363 return render(request, 'rc_import.html', kwargs)
354 364
355 365
356 366 def plot_pulses(request, conf_id):
357 367
358 368 conf = get_object_or_404(RCConfiguration, pk=conf_id)
359 369 km = True if 'km' in request.GET else False
360 370
361 371 script, div = conf.plot_pulses(km=km)
362 372
363 373 kwargs = {}
364 374 kwargs['no_sidebar'] = True
365 375 kwargs['title'] = 'RC Pulses'
366 376 kwargs['suptitle'] = conf.name
367 377 kwargs['div'] = mark_safe(div)
368 378 kwargs['script'] = mark_safe(script)
369 379 kwargs['units'] = conf.km2unit
370 380 kwargs['kms'] = 1/conf.km2unit
371 381
372 382 if km:
373 383 kwargs['km_selected'] = True
374 384
375 385 if 'json' in request.GET:
376 386 return HttpResponse(json.dumps({'div':mark_safe(div), 'script':mark_safe(script)}), content_type="application/json")
377 387 else:
378 388 return render(request, 'rc_pulses.html', kwargs)
379 389
380 390 def plot_pulses2(request, conf_id):
381 391
382 392 conf = get_object_or_404(RCConfiguration, pk=conf_id)
383 393 km = True if 'km' in request.GET else False
384 394
385 395 script, div = conf.plot_pulses2(km=km)
386 396
387 397 kwargs = {}
388 398 kwargs['no_sidebar'] = True
389 399 kwargs['title'] = 'RC Pulses'
390 400 kwargs['suptitle'] = conf.name
391 401 kwargs['div'] = mark_safe(div)
392 402 kwargs['script'] = mark_safe(script)
393 403 kwargs['units'] = conf.km2unit
394 404 kwargs['kms'] = 1/conf.km2unit
395 405
396 406 if km:
397 407 kwargs['km_selected'] = True
398 408
399 409 if 'json' in request.GET:
400 410 return HttpResponse(json.dumps({'div':mark_safe(div), 'script':mark_safe(script)}), content_type="application/json")
401 411 else:
402 412 return render(request, 'rc_pulses.html', kwargs)
403 413
404 414 def conf_raw(request, conf_id):
405 415 conf = get_object_or_404(RCConfiguration, pk=conf_id)
406 416 raw = conf.write_device(raw=True)
407 417 return HttpResponse(raw, content_type='application/json') No newline at end of file
@@ -1,5 +1,9
1 #!/bin/env bash
2 echo "Creating database..."
3 psql -U postgres -c "CREATE USER $POSTGRES_USER WITH PASSWORD '$POSTGRES_PASSWORD';"
4 psql -U postgres -c "CREATE DATABASE $POSTGRES_DB_NAME;"
5 psql -U postgres -c "GRANT ALL PRIVILEGES ON DATABASE $POSTGRES_DB_NAME to $POSTGRES_USER;"
1 #!/bin/bash
2 set -e
3
4 echo "Creating database & user"
5 psql -v --username "postgres" --dbname "postgres" <<-EOSQL
6 CREATE USER $DB_USER WITH PASSWORD '$DB_PASSWORD';
7 CREATE DATABASE $DB_NAME;
8 GRANT ALL PRIVILEGES ON DATABASE $DB_NAME TO $DB_USER;
9 EOSQL
@@ -1,141 +1,141
1 1 """
2 2 Django settings for radarsys project.
3 3
4 4 Generated by 'django-admin startproject' using Django 1.8.6.
5 5
6 6 For more information on this file, see
7 7 https://docs.djangoproject.com/en/1.8/topics/settings/
8 8
9 9 For the full list of settings and their values, see
10 10 https://docs.djangoproject.com/en/1.8/ref/settings/
11 11 """
12 12
13 13 # Build paths inside the project like this: os.path.join(BASE_DIR, ...)
14 14 import os
15 15
16 16 BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
17 17
18 18 # Quick-start development settings - unsuitable for production
19 19 # See https://docs.djangoproject.com/en/1.8/howto/deployment/checklist/
20 20
21 21 # SECURITY WARNING: keep the secret key used in production secret!
22 22 SECRET_KEY = 'xshb$k5fc-+j16)cvyffj&9u__0q3$l!hieh#+tbzqg)*f^km0'
23 23
24 24 # SECURITY WARNING: don't run with debug turned on in production!
25 25 DEBUG = True
26 26
27 27 ALLOWED_HOSTS = ['*']
28 28
29 29 # Application definition
30 30
31 31 INSTALLED_APPS = (
32 32 'django.contrib.admin',
33 33 'django.contrib.auth',
34 34 'django.contrib.contenttypes',
35 35 'django.contrib.sessions',
36 36 'django.contrib.messages',
37 37 'django.contrib.staticfiles',
38 38 'bootstrap3',
39 39 'polymorphic',
40 40 'apps.accounts',
41 41 'apps.main',
42 42 'apps.misc',
43 43 'apps.rc',
44 44 'apps.dds',
45 45 'apps.jars',
46 46 'apps.usrp',
47 47 'apps.abs',
48 48 'apps.cgs',
49 49 )
50 50
51 51 MIDDLEWARE_CLASSES = (
52 52 'django.contrib.sessions.middleware.SessionMiddleware',
53 53 'django.middleware.common.CommonMiddleware',
54 54 'django.middleware.csrf.CsrfViewMiddleware',
55 55 'django.contrib.auth.middleware.AuthenticationMiddleware',
56 56 'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
57 57 'django.contrib.messages.middleware.MessageMiddleware',
58 58 'django.middleware.clickjacking.XFrameOptionsMiddleware',
59 59 'django.middleware.security.SecurityMiddleware',
60 60 )
61 61
62 62 ROOT_URLCONF = 'radarsys.urls'
63 63
64 64 TEMPLATES = [
65 65 {
66 66 'BACKEND': 'django.template.backends.django.DjangoTemplates',
67 67 'DIRS': [os.path.join(BASE_DIR, "templates").replace('\\', '/'),],
68 68 'APP_DIRS': True,
69 69 'OPTIONS': {
70 70 'context_processors': [
71 71 'django.template.context_processors.debug',
72 72 'django.template.context_processors.request',
73 73 'django.contrib.auth.context_processors.auth',
74 74 'django.contrib.messages.context_processors.messages',
75 75 'apps.main.processors.radarsys_globals',
76 76 ],
77 77 },
78 78 },
79 79 ]
80 80
81 81 WSGI_APPLICATION = 'radarsys.wsgi.application'
82 82
83 83
84 84 # Database
85 85 # https://docs.djangoproject.com/en/1.8/ref/settings/#databases
86 86
87 87 DATABASES = {
88 88 # 'default': {
89 89 # 'ENGINE': 'django.db.backends.sqlite3',
90 90 # 'NAME': 'radarsys.sqlite',
91 91 # }
92 92 'default': {
93 93 'ENGINE': 'django.db.backends.postgresql_psycopg2',
94 'NAME': os.environ.get('POSTGRES_DB_NAME', 'radarsys'),
95 'USER': os.environ.get('POSTGRES_USER', 'docker'),
96 'PASSWORD': os.environ.get('POSTGRES_PASSWORD', 'docker'),
97 'HOST': os.environ.get('POSTGRES_PORT_5432_TCP_ADDR', 'postgres'),
98 'PORT': os.environ.get('POSTGRES_PORT_5432_TCP_PORT', ''),
94 'NAME': os.environ.get('DB_NAME', 'radarsys'),
95 'USER': os.environ.get('DB_USER', 'docker'),
96 'PASSWORD': os.environ.get('DB_PASSWORD', 'docker'),
97 'HOST': os.environ.get('POSTGRES_PORT_5432_TCP_ADDR', 'localhost'),
98 'PORT': os.environ.get('POSTGRES_PORT_5432_TCP_PORT', '5400'),
99 99 }
100 100 }
101 101
102 102 # Internationalization
103 103 # https://docs.djangoproject.com/en/1.8/topics/i18n/
104 104
105 105 LANGUAGE_CODE = 'en-us'
106 106
107 TIME_ZONE = os.environ.get('TZ', 'UTC')
107 TIME_ZONE = os.environ.get('TZ', 'America/Lima')
108 108
109 109 USE_I18N = True
110 110
111 111 USE_L10N = True
112 112
113 113 USE_TZ = False
114 114
115 115 # Static files (CSS, JavaScript, Images)
116 116 # https://docs.djangoproject.com/en/1.8/howto/static-files/
117 117
118 118 MEDIA_URL = '/media/'
119 119 MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
120 120
121 121 STATIC_URL = '/static/'
122 122 STATIC_ROOT = os.path.join(BASE_DIR, 'static')
123 123
124 124 STATICFILES_FINDERS = (
125 125 'django.contrib.staticfiles.finders.FileSystemFinder',
126 126 'django.contrib.staticfiles.finders.AppDirectoriesFinder',
127 127 )
128 128
129 129 # Celery stuff
130 130 REDIS_HOST = os.environ.get('REDIS_HOST', '127.0.0.1')
131 REDIS_PORT = os.environ.get('REDIS_PORT', 6379)
131 REDIS_PORT = os.environ.get('REDIS_PORT', 6300)
132 132
133 133 BROKER_TRANSPORT = 'redis'
134 134 BROKER_URL = 'redis://{}:{}/0'.format(REDIS_HOST, REDIS_PORT)
135 135
136 136 CELERY_RESULT_BACKEND = 'redis://{}:{}/0'.format(REDIS_HOST, REDIS_PORT)
137 137 CELERY_BROKER_TRANSPORT = BROKER_URL
138 138 CELERY_ACCEPT_CONTENT = ['application/json']
139 139 CELERY_TASK_SERIALIZER = 'json'
140 140 CELERY_RESULT_SERIALIZER = 'json'
141 141 CELERY_ENABLE_UTC = False No newline at end of file
General Comments 0
You need to be logged in to leave comments. Login now