##// END OF EJS Templates
Update models.py files (pedestal and main/generator)
eynilupu -
r402:40436666afd2
parent child
Show More
@@ -1,615 +1,615
1 1
2 2 import os
3 3 import json
4 4 import requests
5 5 import time
6 6 from datetime import datetime
7 7 import base64
8 8
9 9 try:
10 10 from polymorphic.models import PolymorphicModel
11 11 except:
12 12 from polymorphic import PolymorphicModel
13 13
14 14 from django.template.base import kwarg_re
15 15 from django.db import models
16 16 from django.urls import reverse
17 17 from django.core.validators import MinValueValidator, MaxValueValidator
18 18 from django.shortcuts import get_object_or_404
19 19 from django.contrib.auth.models import User
20 20 from django.db.models.signals import post_save
21 21 from django.dispatch import receiver
22 22
23 23 from apps.main.utils import Params
24 24
25 25 DEV_PORTS = {
26 26 'pedestal' : 80,
27 27 'pedestal_dev' : 80,
28 28 'generator' : 80,
29 29 'usrp_rx' : 2000,
30 30 'usrp_tx' : 2000,
31 31 }
32 32
33 33 RADAR_STATES = (
34 34 (0, 'No connected'),
35 35 (1, 'Connected'),
36 36 (2, 'Configured'),
37 37 (3, 'Running'),
38 38 (4, 'Scheduled'),
39 39 )
40 40
41 41 EXPERIMENT_TYPE = (
42 42 (0, 'RAW_DATA'),
43 43 (1, 'PDATA'),
44 44 )
45 45
46 46 DECODE_TYPE = (
47 47 (0, 'None'),
48 48 (1, 'TimeDomain'),
49 49 (2, 'FreqDomain'),
50 50 (3, 'InvFreqDomain'),
51 51 )
52 52
53 53 DEV_STATES = (
54 54 (0, 'Unknown'),
55 55 (1, 'Connected'),
56 56 (2, 'Configured'),
57 57 (3, 'Running'),
58 58 (4, 'Offline'),
59 59 )
60 60
61 61 DEV_TYPES = (
62 62 ('', 'Select a device type'),
63 63 ('pedestal', 'Pedestal Controller'),
64 64 ('pedestal_dev', 'Pedestal Controller Dev Mode'),
65 65 ('generator', 'Pulse Generator'),
66 66 ('usrp_rx', 'Universal Software Radio Peripheral Rx'),
67 67 ('usrp_tx', 'Universal Software Radio Peripheral Tx'),
68 68 )
69 69
70 70 EXP_STATES = (
71 71 (0,'Error'), #RED
72 72 (1,'Cancelled'), #YELLOW
73 73 (2,'Running'), #GREEN
74 74 (3,'Scheduled'), #BLUE
75 75 (4,'Unknown'), #WHITE
76 76 )
77 77
78 78 CONF_TYPES = (
79 79 (0, 'Active'),
80 80 (1, 'Historical'),
81 81 )
82 82
83 83 class Profile(models.Model):
84 84 user = models.OneToOneField(User, on_delete=models.CASCADE)
85 85 theme = models.CharField(max_length=30, default='spacelab')
86 86
87 87
88 88 @receiver(post_save, sender=User)
89 89 def create_user_profile(sender, instance, created, **kwargs):
90 90 if created:
91 91 Profile.objects.create(user=instance)
92 92
93 93 @receiver(post_save, sender=User)
94 94 def save_user_profile(sender, instance, **kwargs):
95 95 instance.profile.save()
96 96
97 97
98 98 class DeviceType(models.Model):
99 99
100 100 name = models.CharField(max_length = 15, choices = DEV_TYPES, default = 'pedestal')
101 101 sequence = models.PositiveSmallIntegerField(default=55)
102 102 description = models.TextField(blank=True, null=True)
103 103
104 104 class Meta:
105 105 db_table = 'db_device_types'
106 106
107 107 def __str__(self):
108 108 return u'%s' % self.name.title()
109 109
110 110 class Device(models.Model):
111 111
112 112 device_type = models.ForeignKey('DeviceType', on_delete=models.CASCADE)
113 113 ip_address = models.GenericIPAddressField(verbose_name = 'IP address', protocol='IPv4', default='0.0.0.0')
114 114 port_address = models.PositiveSmallIntegerField(default=2000)
115 115 description = models.TextField(blank=True, null=True)
116 116 status = models.PositiveSmallIntegerField(default=4, choices=DEV_STATES)
117 117 conf_active = models.PositiveIntegerField(default=0, verbose_name='Current configuration')
118 118
119 119 class Meta:
120 120 db_table = 'db_devices'
121 121
122 122 def __str__(self):
123 123 ret = self.device_type
124 124 return str(ret)
125 125
126 126 @property
127 127 def name(self):
128 128 return str(self)
129 129
130 130 def get_status(self):
131 131 return self.status
132 132
133 133 @property
134 134 def status_color(self):
135 135 color = 'muted'
136 136 if self.status == 0:
137 137 color = "danger"
138 138 elif self.status == 1:
139 139 color = "primary"
140 140 elif self.status == 2:
141 141 color = "info"
142 142 elif self.status == 3:
143 143 color = "success"
144 144
145 145 return color
146 146
147 147 def url(self, path=None):
148 148
149 149 if path:
150 150 return 'http://{}:{}/{}/'.format(self.ip_address, self.port_address, path)
151 151 else:
152 152 return 'http://{}:{}/'.format(self.ip_address, self.port_address)
153 153
154 154 def get_absolute_url(self):
155 155 return reverse('url_device', args=[str(self.id)])
156 156
157 157 def get_absolute_url_edit(self):
158 158 return reverse('url_edit_device', args=[str(self.id)])
159 159
160 160 def get_absolute_url_delete(self):
161 161 return reverse('url_delete_device', args=[str(self.id)])
162 162
163 163 def change_ip(self, ip_address, mask, gateway, dns, **kwargs):
164 164
165 165 if self.device_type.name=='pedestal':
166 166 headers = {'content-type': "application/json",
167 167 'cache-control': "no-cache"}
168 168
169 169 ip = [int(x) for x in ip_address.split('.')]
170 170 dns = [int(x) for x in dns.split('.')]
171 171 gateway = [int(x) for x in gateway.split('.')]
172 172 subnet = [int(x) for x in mask.split('.')]
173 173
174 174 payload = {
175 175 "ip": ip,
176 176 "dns": dns,
177 177 "gateway": gateway,
178 178 "subnet": subnet
179 179 }
180 180
181 181 req = requests.post(self.url('changeip'), data=json.dumps(payload), headers=headers)
182 182 try:
183 183 answer = req.json()
184 184 if answer['changeip']=='ok':
185 185 self.message = '25|IP succesfully changed'
186 186 self.ip_address = ip_address
187 187 self.save()
188 188 else:
189 189 self.message = '30|An error ocuur when changing IP'
190 190 except Exception as e:
191 191 self.message = '40|{}'.format(str(e))
192 192 else:
193 193 self.message = 'Not implemented'
194 194 return False
195 195
196 196 return True
197 197
198 198
199 199 class Experiment(PolymorphicModel):
200 200
201 201 name = models.CharField(max_length=40, default='', unique=True)
202 202 pedestal = models.ForeignKey('pedestal.PedestalConfiguration', null=False, blank=False, on_delete=models.PROTECT, default=None, related_name = "pedestal_conf")
203 203 generator = models.ForeignKey('generator.GeneratorConfiguration', null=False, blank=False, on_delete=models.PROTECT, default=None, related_name = "generator_conf")
204 204 reception_rx = models.ForeignKey('usrp_rx.USRPRXConfiguration', null=False, blank=False, on_delete=models.PROTECT, default=None, related_name = "usrp_rx_CONF")
205 205 transmission_tx = models.ForeignKey('usrp_tx.USRPTXConfiguration', null=False, blank=False, on_delete=models.PROTECT, default=None, related_name = "usrp_tx")
206 206 task = models.CharField(max_length=36, default='', blank=True, null=True)
207 207 status = models.PositiveSmallIntegerField(default=4, choices=EXP_STATES)
208 208 author = models.ForeignKey(User, null=True, blank=True, on_delete=models.CASCADE)
209 209 hash = models.CharField(default='', max_length=64, null=True, blank=True)
210 210 latitude = models.FloatField(null=True, blank=True)
211 211 longitude = models.FloatField(null=True, blank=True)
212 212 heading = models.FloatField(null=True, blank=True)
213 213
214 214 class Meta:
215 215 db_table = 'db_experiments'
216 216 ordering = ('name',)
217 217
218 218 def __str__(self):
219 219 return u'%s' % (self.name)
220 220
221 221 def jsonify(self):
222 222
223 223 data = {}
224 224
225 225 ignored = []
226 226
227 227 for field in self._meta.fields:
228 228 if field.name in ignored:
229 229 continue
230 230 data[field.name] = field.value_from_object(self)
231 231
232 232 data['configurations'] = ['{}'.format(conf.pk) for
233 233 conf in Configuration.objects.filter(experiment=self, type=0)]
234 234
235 235 return data
236 236
237 237 def clone(self, **kwargs):
238 238
239 239 confs = Configuration.objects.filter(experiment=self, type=0)
240 240 self.pk = None
241 241 self.name = '{}_{:%y%m%d}'.format(self.name, datetime.now())
242 242 for attr, value in kwargs.items():
243 243 setattr(self, attr, value)
244 244
245 245 self.save()
246 246
247 247 for conf in confs:
248 248 conf.clone(experiment=self)
249 249
250 250 return self
251 251
252 252
253 253 def generator_start(self):
254 254 try:
255 255 period = self.transmission_tx.ipp*2/0.3
256 256 if self.transmission_tx.enable_2:
257 payload = {"Delay": 0, "periode1": period, "width1": self.transmission_tx.pulse_1, "repeatability1": self.transmission_tx.repetitions_1, "periode2": period, "width2": self.transmission_tx.pulse_2, "repeatability2": self.transmission_tx.repetitions_2, "enable": 1}
257 payload = {"Delay": 1, "periode1": period, "width1": self.transmission_tx.pulse_1, "repeatability1": self.transmission_tx.repetitions_1, "periode2": period, "width2": self.transmission_tx.pulse_2, "repeatability2": self.transmission_tx.repetitions_2, "enable": 1}
258 258 else:
259 payload = {"Delay": 0, "periode1": period, "width1": self.transmission_tx.pulse_1, "repeatability1": 1, "periode2": self.transmission_tx.periode_1, "width2": self.transmission_tx.pulse_1, "repeatability2": 1, "enable": 1}
259 payload = {"Delay": 1, "periode1": period, "width1": self.transmission_tx.pulse_1, "repeatability1": 1, "periode2": period, "width2": self.transmission_tx.pulse_1, "repeatability2": 1, "enable": 1}
260 260
261 261 json_trmode = json.dumps(payload)
262 262
263 263 base64_trmode = base64.standard_b64encode(json_trmode.encode('ascii'))
264 264
265 265 trmode_url = self.generator.device.url() + "trmode?params="
266 266 complete_url_trmode = trmode_url + base64_trmode.decode('ascii')
267 267
268 r = requests.get(complete_url_trmode)
268 requests.get(complete_url_trmode)
269 269 except:
270 270 return False
271 271 return True
272 272
273 273 def start(self):
274 274 '''
275 275 Configure and start experiments's devices
276 276 '''
277 277
278 278 data = {
279 279 'name': '%s_%d' % (self.name, int(time.time())),
280 280 'latitude': self.latitude,
281 281 'longitude': self.longitude,
282 282 'heading': self.heading
283 283 }
284 284
285 285 self.reception_rx.datadir = os.path.join(os.environ['EXPOSE_NAS'], data['name'], 'rawdata')
286 286 self.reception_rx.save()
287 287
288 288 try:
289 289 proc_url = 'http://'+os.environ['PROC_SITE']+'/start'
290 290 data['usrp_rx'] = self.reception_rx.start_device()
291 291 data['pedestal'] = self.pedestal.start_device()
292 292 self.generator_start()
293 293 data['usrp_tx'] = self.transmission_tx.start_device()
294 294 requests.post(proc_url, json=data)
295 295
296 296 except:
297 297 return 0
298 298 return 2
299 299
300 300
301 301 def stop(self):
302 302 '''
303 303 Stop experiments's devices
304 304 PEDESTAL, GENERATOR & USRP's
305 305 '''
306 306
307 307 try:
308 308 proc_url = 'http://'+os.environ['PROC_SITE']+'/stop'
309 309 requests.get(proc_url)
310 310 self.reception_rx.stop_device()
311 311 self.pedestal.stop_device()
312 312 self.generator.stop_device()
313 313 self.transmission_tx.stop_device()
314 314 except:
315 315 return 0
316 316 return 2
317 317
318 318 def get_status(self):
319 319
320 320 if self.status == 3:
321 321 return
322 322
323 323 confs = Configuration.objects.filter(experiment=self, type=0)
324 324
325 325 for conf in confs:
326 326 conf.status_device()
327 327
328 328 total = confs.aggregate(models.Sum('device__status'))['device__status__sum']
329 329
330 330 if total==2*confs.count():
331 331 status = 1
332 332 elif total == 3*confs.count():
333 333 status = 2
334 334 else:
335 335 status = 0
336 336
337 337 self.status = status
338 338 self.save()
339 339
340 340 def status_color(self):
341 341 color = 'muted'
342 342 if self.status == 0:
343 343 color = "danger"
344 344 elif self.status == 1:
345 345 color = "warning"
346 346 elif self.status == 2:
347 347 color = "success"
348 348 elif self.status == 3:
349 349 color = "info"
350 350
351 351 return color
352 352
353 353 def parms_to_dict(self):
354 354
355 355 params = Params({})
356 356 params.add(self.jsonify(), 'experiments')
357 357
358 358 configurations = Configuration.objects.filter(experiment=self, type=0)
359 359
360 360 for conf in configurations:
361 361 params.add(conf.jsonify(), 'configurations')
362 362
363 363 return params.data
364 364
365 365 def dict_to_parms(self, parms, CONF_MODELS, id_exp=None):
366 366
367 367 configurations = Configuration.objects.filter(experiment=self)
368 368
369 369 if id_exp is not None:
370 370 exp_parms = parms['experiments']['byId'][id_exp]
371 371 else:
372 372 exp_parms = parms['experiments']['byId'][parms['experiments']['allIds'][0]]
373 373
374 374 if configurations:
375 375 for configuration in configurations:
376 376 configuration.delete()
377 377
378 378 for id_conf in exp_parms['configurations']:
379 379 conf_parms = parms['configurations']['byId'][id_conf]
380 380 device = Device.objects.filter(device_type__name=conf_parms['device_type'])[0]
381 381 model = CONF_MODELS[conf_parms['device_type']]
382 382 conf = model(
383 383 experiment = self,
384 384 device = device,
385 385 )
386 386 conf.dict_to_parms(parms, id=id_conf)
387 387
388 388
389 389 self.name = '{}-{}'.format(exp_parms['name'], datetime.now().strftime('%y%m%d'))
390 390 self.save()
391 391
392 392 return self
393 393
394 394 def get_absolute_url(self):
395 395 return reverse('url_experiment', args=[str(self.id)])
396 396
397 397 def get_absolute_url_edit(self):
398 398 return reverse('url_edit_experiment', args=[str(self.id)])
399 399
400 400 def get_absolute_url_delete(self):
401 401 return reverse('url_delete_experiment', args=[str(self.id)])
402 402
403 403 def get_absolute_url_import(self):
404 404 return reverse('url_import_experiment', args=[str(self.id)])
405 405
406 406 def get_absolute_url_export(self):
407 407 return reverse('url_export_experiment', args=[str(self.id)])
408 408
409 409 def get_absolute_url_start(self):
410 410 return reverse('url_start_experiment', args=[str(self.id)])
411 411
412 412 def get_absolute_url_stop(self):
413 413 return reverse('url_stop_experiment', args=[str(self.id)])
414 414
415 415
416 416 class Configuration(PolymorphicModel):
417 417
418 418 id = models.AutoField(primary_key=True)
419 419 device = models.ForeignKey('Device', verbose_name='Device', null=True, on_delete=models.CASCADE)
420 420 type = models.PositiveSmallIntegerField(default=0, choices=CONF_TYPES)
421 421 created_date = models.DateTimeField(auto_now_add=True)
422 422 programmed_date = models.DateTimeField(auto_now=True)
423 423 parameters = models.TextField(default='{}')
424 424 author = models.ForeignKey(User, null=True, blank=True,on_delete=models.CASCADE)
425 425 hash = models.CharField(default='', max_length=64, null=True, blank=True)
426 426 message = ""
427 427
428 428 class Meta:
429 429 db_table = 'db_configurations'
430 430 ordering = ('device__device_type__name',)
431 431
432 432 def __str__(self):
433 433
434 434 ret = u'{} '.format(self.device.device_type.name.upper())
435 435
436 436 if 'mix' in [f.name for f in self._meta.get_fields()]:
437 437 if self.mix:
438 438 ret = '{} MIX '.format(self.device.device_type.name.upper())
439 439
440 440 if 'label' in [f.name for f in self._meta.get_fields()]:
441 441 ret += '{}'.format(self.label)
442 442
443 443 return ret
444 444
445 445 @property
446 446 def name(self):
447 447
448 448 return str(self)
449 449
450 450 @property
451 451 def label(self):
452 452
453 453 return str(self)
454 454
455 455 def jsonify(self):
456 456
457 457 data = {}
458 458
459 459 ignored = ('type', 'polymorphic_ctype', 'configuration_ptr',
460 460 'created_date', 'programmed_date', 'device',
461 461 'experiment', 'author')
462 462
463 463 for field in self._meta.fields:
464 464 if field.name in ignored:
465 465 continue
466 466 data[field.name] = field.value_from_object(self)
467 467
468 468 data['device_type'] = self.device.device_type.name
469 469 return data
470 470
471 471 def clone(self, **kwargs):
472 472
473 473 self.pk = None
474 474 self.id = None
475 475 for attr, value in kwargs.items():
476 476 setattr(self, attr, value)
477 477
478 478 self.save()
479 479
480 480 return self
481 481
482 482 def parms_to_dict(self):
483 483
484 484 params = Params({})
485 485 params.add(self.jsonify(), 'configurations')
486 486 return params.data
487 487
488 488 def parms_to_text(self):
489 489
490 490 raise NotImplementedError("This method should be implemented in %s Configuration model" %str(self.device.device_type.name).upper())
491 491
492 492
493 493 def parms_to_binary(self):
494 494
495 495 raise NotImplementedError("This method should be implemented in %s Configuration model" %str(self.device.device_type.name).upper())
496 496
497 497
498 498 def dict_to_parms(self, parameters, id=None):
499 499
500 500 params = Params(parameters)
501 501
502 502 if id:
503 503 data = params.get_conf(id_conf=id)
504 504 else:
505 505 data = params.get_conf(dtype=self.device.device_type.name)
506 506
507 507 for key, value in data.items():
508 508 if key not in ('id', 'device_type'):
509 509 setattr(self, key, value)
510 510
511 511 self.save()
512 512
513 513
514 514 def export_to_file(self, format="json"):
515 515
516 516 content_type = ''
517 517
518 518 if format == 'racp':
519 519 content_type = 'text/plain'
520 520 filename = '%s_%s.%s' %(self.device.device_type.name, self.name, 'racp')
521 521 content = self.parms_to_text(file_format = 'racp')
522 522
523 523 if format == 'text':
524 524 content_type = 'text/plain'
525 525 filename = '%s_%s.%s' %(self.device.device_type.name, self.name, self.device.device_type.name)
526 526 content = self.parms_to_text()
527 527
528 528 if format == 'binary':
529 529 content_type = 'application/octet-stream'
530 530 filename = '%s_%s.bin' %(self.device.device_type.name, self.name)
531 531 content = self.parms_to_binary()
532 532
533 533 if not content_type:
534 534 content_type = 'application/json'
535 535 filename = '%s_%s.json' %(self.device.device_type.name, self.name)
536 536 content = json.dumps(self.parms_to_dict(), indent=2)
537 537
538 538
539 539 fields = {'content_type':content_type,
540 540 'filename':filename,
541 541 'content':content
542 542 }
543 543
544 544 return fields
545 545
546 546 def import_from_file(self, fp):
547 547
548 548 parms = {}
549 549
550 550 path, ext = os.path.splitext(fp.name)
551 551
552 552 if ext == '.json':
553 553 parms = json.load(fp)
554 554
555 555 return parms
556 556
557 557 def status_device(self):
558 558
559 559 self.message = 'Function not supported'
560 560 return False
561 561
562 562
563 563 def stop_device(self):
564 564
565 565 self.message = 'Function not supported'
566 566 return False
567 567
568 568
569 569 def start_device(self):
570 570
571 571 self.message = 'Function not supported'
572 572 return False
573 573
574 574
575 575 def write_device(self):
576 576
577 577 self.message = 'Function not supported'
578 578 return False
579 579
580 580
581 581 def read_device(self):
582 582
583 583 self.message = 'Function not supported'
584 584 return False
585 585
586 586
587 587 def get_absolute_url(self):
588 588 return reverse('url_%s_conf' % self.device.device_type.name, args=[str(self.id)])
589 589
590 590 def get_absolute_url_edit(self):
591 591 return reverse('url_edit_%s_conf' % self.device.device_type.name, args=[str(self.id)])
592 592
593 593 def get_absolute_url_delete(self):
594 594 return reverse('url_delete_dev_conf', args=[str(self.id)])
595 595
596 596 def get_absolute_url_import(self):
597 597 return reverse('url_import_dev_conf', args=[str(self.id)])
598 598
599 599 def get_absolute_url_export(self):
600 600 return reverse('url_export_dev_conf', args=[str(self.id)])
601 601
602 602 def get_absolute_url_write(self):
603 603 return reverse('url_write_dev_conf', args=[str(self.id)])
604 604
605 605 def get_absolute_url_read(self):
606 606 return reverse('url_read_dev_conf', args=[str(self.id)])
607 607
608 608 def get_absolute_url_start(self):
609 609 return reverse('url_start_dev_conf', args=[str(self.id)])
610 610
611 611 def get_absolute_url_stop(self):
612 612 return reverse('url_stop_dev_conf', args=[str(self.id)])
613 613
614 614 def get_absolute_url_status(self):
615 615 return reverse('url_status_dev_conf', args=[str(self.id)])
@@ -1,263 +1,265
1 1 import ast
2 2 import json
3 3 import requests
4 4 import base64
5 5 import struct
6 6 from struct import pack
7 7 import time
8 8 from django.contrib import messages
9 9 from django.db import models
10 10 from django.urls import reverse
11 11 from django.core.validators import MinValueValidator, MaxValueValidator
12 12
13 13 from apps.main.models import Configuration
14 14
15 15 MODE_VALUE = (
16 16 ('position', 'Position'),
17 17 ('speed', 'Speed'),
18 18 ('table', 'Table')
19 19 )
20 20
21 21 class PedestalConfiguration(Configuration):
22 22
23 23 mode = models.CharField(
24 24 verbose_name='Mode',
25 25 max_length=10,
26 26 choices=MODE_VALUE,
27 27 null=False,
28 28 blank=False
29 29 )
30 30
31 31 axis = models.CharField(
32 32 verbose_name="Axis",
33 33 max_length=100,
34 34 default='az',
35 35 blank=False,
36 36 null=False,
37 37 help_text="Please separate the values with commas when using table mode"
38 38 )
39 39
40 40 speed = models.CharField(
41 41 verbose_name='Speed',
42 42 max_length=100,
43 43 blank=False,
44 44 null=False,
45 45 default=6
46 46 )
47 47
48 48 angle = models.CharField(
49 49 verbose_name="Angle(s)",
50 50 max_length=100,
51 51 default='0',
52 52 blank=False,
53 53 null=False,
54 54 help_text="Please separate the values with commas when using table mode"
55 55 )
56 56
57 57 min_value = models.FloatField(
58 58 verbose_name='Min angle',
59 59 validators=[MinValueValidator(-5), MaxValueValidator(185)],
60 60 blank=False,
61 61 null=False,
62 62 default=0
63 63 )
64 64
65 65 max_value = models.FloatField(
66 66 verbose_name='Max angle',
67 67 validators=[MinValueValidator(-5), MaxValueValidator(185)],
68 68 blank=False,
69 69 null=False,
70 70 default=40
71 71 )
72 72
73 73 class Meta:
74 74 db_table = 'pedestal_configurations'
75 75
76 76 def __str__(self):
77 77 if self.mode=='position':
78 78 return u'Position: {}ΒΊ {}'.format(self.angle, self.axis.upper())
79 79 if self.mode=='speed':
80 80 return u'Speed: {}ΒΊ/s {}'.format(self.speed, self.axis.upper())
81 81 if self.mode=='table':
82 82 axis = [x.strip().upper() for x in self.axis.split(',')]
83 83 speeds = [float(x.strip()) for x in self.speed.split(',')]
84 84 table = [float(x.strip()) for x in self.angle.split(',')]
85 85 return u'Table: Axis {}, Speed {}ΒΊ/s, Steps {}'.format(axis, speeds, table)
86 86
87 87 @property
88 88 def label(self):
89 89 return str(self)
90 90
91 91 def get_absolute_url_plot(self):
92 92 return reverse('url_plot_pedestal_pulses', args=[str(self.id)])
93 93
94 94 def request(self, cmd, method='get', **kwargs):
95 95
96 96 req = getattr(requests, method)(self.device.url(cmd), **kwargs)
97 97 payload = req.json()
98 98
99 99 return payload
100 100
101 101 def status_device(self):
102 102
103 103 try:
104 104 payload = requests.get(self.device.url())
105 105
106 106 if payload:
107 107 self.device.status = 1
108 108 elif payload['status']=='disable':
109 109 self.device.status = 2
110 110 else:
111 111 self.device.status = 1
112 112 self.device.save()
113 113 self.message = 'Pedestal status: {}'.format(payload['status'])
114 114 return False
115 115 except Exception as e:
116 116 if 'No route to host' not in str(e):
117 117 self.device.status = 4
118 118 self.device.save()
119 119 self.message = 'Pedestal status: {}'.format(str(e))
120 120 return False
121 121
122 122 self.device.save()
123 123 return True
124 124
125 125 def reset_device(self, axi, angle):
126 126
127 127 try:
128 128 url = self.device.url() + "position?params="
129 129
130 130 payload_el = {'axis': 'elevation'}
131 131 payload_az = {'axis': 'azimuth'}
132 132
133 133 if axi == 'elevation':
134 134 payload_az['position'] = angle
135 135 payload_el['position'] = 0
136 136 elif axi == 'azimuth':
137 137 payload_el['position'] = angle
138 138 payload_az['position'] = 0
139 139 else:
140 140 payload_el['position'] = 0
141 141 payload_az['position'] = 0
142 142
143 143 json_data_el = json.dumps(payload_el)
144 144 json_data_az = json.dumps(payload_az)
145 145
146 146 base64_table_el = base64.standard_b64encode(json_data_el.encode('ascii'))
147 147 base64_table_az = base64.standard_b64encode(json_data_az.encode('ascii'))
148 148
149 time.sleep(0.1)
149 150 r = requests.get(url + base64_table_el.decode('ascii'))
151 time.sleep(0.1)
150 152 r = requests.get(url + base64_table_az.decode('ascii'))
151 153
152 154 if r:
153 155 self.device.status = 3
154 156 self.device.save()
155 157 self.message = 'Pedestal reset'
156 158 else:
157 159 return False
158 160
159 161 except Exception as e:
160 162 self.message = 'Pedestal reset: {}'.format(str(e))
161 163 return False
162 164
163 165 return True
164 166
165 167 def stop_device(self):
166 168
167 169 try:
168 170 command = self.device.url() + "stop"
169 171 r = requests.get(command)
170 172
171 173 if self.mode == 'table':
172 174 AX = {'az':'azimuth', 'el':'elevation'}
173 175 axis = [AX[x.lower().strip()] for x in self.axis.split(',')]
174 176 list_of_floats = [float(x.strip()) for x in self.angle.split(",")]
175 177 self.reset_device(axis[0], list_of_floats[0])
176 178
177 179 if r:
178 180 self.device.status = 4
179 181 self.device.save()
180 182 self.message = 'Pedestal stopped'
181 183 else:
182 184 self.device.status = 4
183 185 self.device.save()
184 186 return False
185 187 except Exception as e:
186 188 if 'No route to host' not in str(e):
187 189 self.device.status = 4
188 190 else:
189 191 self.device.status = 0
190 192 #self.message = 'Pedestal stop: {}'.format(str(e))
191 193 self.message = "Pedestal can't start, please check network/device connection or IP address/port configuration"
192 194 self.device.save()
193 195 return False
194 196
195 197 return True
196 198
197 199 def start_device(self):
198 200
199 201 AX = {'az':'azimuth', 'el':'elevation'}
200 202 axis = [AX[x.lower().strip()] for x in self.axis.split(',')]
201 203 if len(axis)==1:
202 204 axis = axis[0]
203 205
204 206 try:
205 207 if self.mode == 'position':
206 208 url = self.device.url() + "position?params="
207 209 payload = {'axis': axis, 'position': float(self.angle)}
208 210 elif self.mode == 'speed':
209 211 url = self.device.url() + "speed?params="
210 212 payload = {'axis': axis, 'speed': float(self.speed)}
211 213 elif self.mode == 'table':
212 214 url = self.device.url() + "combinedtable?params="
213 215 list_of_floats = [float(x.strip()) for x in self.angle.split(",")]
214 216 byte_table = []
215 217 for x in list_of_floats:
216 218 temp = bytearray(struct.pack("f", x))
217 219 byte_table.append(temp[3])
218 220 byte_table.append(temp[2])
219 221 byte_table.append(temp[1])
220 222 byte_table.append(temp[0])
221 223
222 224 coded_table = base64.standard_b64encode(bytes(byte_table))
223 225 coded_table_ascii = coded_table.decode('ascii')
224 226 speed = [float(x.strip()) for x in self.speed.split(',')]
225 227 payload = {
226 228 'arraylength': len(speed),
227 229 'axis': axis,
228 230 'speed': speed,
229 231 'bottom': self.min_value,
230 232 'top': self.max_value,
231 233 'table': coded_table_ascii
232 234 }
233 235
234 236 json_data = json.dumps(payload)
235 237 print(json_data)
236 238 base64_table = base64.standard_b64encode(json_data.encode('ascii'))
237 239 url += base64_table.decode('ascii')
238 240 print(url)
239 241 r = requests.get(url)
240 242
241 243 if self.mode == 'table':
242 244 payload['table'] = list_of_floats
243 245
244 246 if r:
245 247 self.device.status = 3
246 248 self.device.save()
247 249 self.message = 'Pedestal configured and started'
248 250 else:
249 251 return False
250 252 except Exception as e:
251 253 if 'No route to host' not in str(e):
252 254 self.device.status = 4
253 255 else:
254 256 self.device.status = 0
255 257 #self.message = 'Pedestal start: {}'.format(str(e))
256 258 self.message = "Pedestal can't start, please check network/device connection or IP address/port configuration"
257 259 self.device.save()
258 260 return False
259 261
260 262 return payload
261 263
262 264 def get_absolute_url_import(self):
263 265 return reverse('url_import_pedestal_conf', args=[str(self.id)])
General Comments 0
You need to be logged in to leave comments. Login now