models.py
295 lines
| 9.9 KiB
| text/x-python
|
PythonLexer
r438 | import os | ||
r429 | from datetime import datetime | ||
|
r25 | import json | |
|
r175 | import requests | |
r345 | import base64 | ||
r346 | import struct | ||
|
r185 | from struct import pack | |
r346 | import time | ||
from django.contrib import messages | |||
|
r0 | from django.db import models | |
r335 | from django.urls import reverse | ||
|
r23 | from django.core.validators import MinValueValidator, MaxValueValidator | |
|
r6 | from apps.main.models import Configuration | |
|
r79 | ||
r365 | MODE_VALUE = ( | ||
r368 | ('position', 'Position'), | ||
('speed', 'Speed'), | |||
('table', 'Table') | |||
r345 | ) | ||
|
r6 | ||
r346 | class PedestalConfiguration(Configuration): | ||
|
r172 | ||
r365 | mode = models.CharField( | ||
verbose_name='Mode', | |||
r360 | max_length=10, | ||
r365 | choices=MODE_VALUE, | ||
r345 | null=False, | ||
blank=False | |||
) | |||
r368 | axis = models.CharField( | ||
verbose_name="Axis", | |||
r429 | max_length=1000, | ||
r368 | blank=False, | ||
null=False, | |||
help_text="Please separate the values with commas when using table mode" | |||
) | |||
speed = models.CharField( | |||
r419 | verbose_name='Speed [°/s]', | ||
r429 | max_length=1000, | ||
r407 | blank=True, | ||
null=True | |||
r345 | ) | ||
r368 | angle = models.CharField( | ||
r419 | verbose_name="Angle(s) [°]", | ||
r429 | max_length=1000, | ||
r407 | blank=True, | ||
null=True, | |||
r368 | help_text="Please separate the values with commas when using table mode" | ||
) | |||
min_value = models.FloatField( | |||
r419 | verbose_name='Min angle [°]', | ||
r368 | validators=[MinValueValidator(-5), MaxValueValidator(185)], | ||
r407 | blank=True, | ||
null=True | |||
r368 | ) | ||
max_value = models.FloatField( | |||
r419 | verbose_name='Max angle [°]', | ||
r368 | validators=[MinValueValidator(-5), MaxValueValidator(185)], | ||
r407 | blank=True, | ||
null=True | |||
r345 | ) | ||
|
r6 | ||
class Meta: | |||
r345 | db_table = 'pedestal_configurations' | ||
def __str__(self): | |||
r368 | if self.mode=='position': | ||
return u'Position: {}º {}'.format(self.angle, self.axis.upper()) | |||
if self.mode=='speed': | |||
return u'Speed: {}º/s {}'.format(self.speed, self.axis.upper()) | |||
if self.mode=='table': | |||
axis = [x.strip().upper() for x in self.axis.split(',')] | |||
r390 | speeds = [float(x.strip()) for x in self.speed.split(',')] | ||
table = [float(x.strip()) for x in self.angle.split(',')] | |||
r368 | return u'Table: Axis {}, Speed {}º/s, Steps {}'.format(axis, speeds, table) | ||
@property | |||
def label(self): | |||
return str(self) | |||
|
r172 | ||
|
r79 | def get_absolute_url_plot(self): | |
r345 | return reverse('url_plot_pedestal_pulses', args=[str(self.id)]) | ||
|
r172 | ||
|
r264 | def request(self, cmd, method='get', **kwargs): | |
req = getattr(requests, method)(self.device.url(cmd), **kwargs) | |||
payload = req.json() | |||
return payload | |||
|
r175 | def status_device(self): | |
|
r172 | ||
|
r222 | try: | |
r350 | payload = requests.get(self.device.url()) | ||
r368 | |||
r350 | if payload: | ||
self.device.status = 1 | |||
|
r264 | elif payload['status']=='disable': | |
|
r222 | self.device.status = 2 | |
|
r185 | else: | |
|
r243 | self.device.status = 1 | |
|
r222 | self.device.save() | |
r346 | self.message = 'Pedestal status: {}'.format(payload['status']) | ||
|
r222 | return False | |
|
r185 | except Exception as e: | |
|
r222 | if 'No route to host' not in str(e): | |
self.device.status = 4 | |||
self.device.save() | |||
r346 | self.message = 'Pedestal status: {}'.format(str(e)) | ||
|
r185 | return False | |
|
r243 | ||
self.device.save() | |||
return True | |||
|
r175 | ||
r395 | def reset_device(self, axi, angle): | ||
|
r243 | ||
|
r185 | try: | |
r390 | url = self.device.url() + "position?params=" | ||
r368 | |||
r395 | payload_el = {'axis': 'elevation'} | ||
payload_az = {'axis': 'azimuth'} | |||
if axi == 'elevation': | |||
r438 | # CORRECT AZ OFFSET | ||
azi = angle - float(os.environ.get('AZ_OFFSET', 26.27)) | |||
if azi<0: azi += 360 | |||
payload_az['position'] = round(azi, 2) | |||
r395 | payload_el['position'] = 0 | ||
elif axi == 'azimuth': | |||
payload_el['position'] = angle | |||
payload_az['position'] = 0 | |||
else: | |||
payload_el['position'] = 0 | |||
payload_az['position'] = 0 | |||
r390 | json_data_el = json.dumps(payload_el) | ||
r395 | json_data_az = json.dumps(payload_az) | ||
r390 | base64_table_el = base64.standard_b64encode(json_data_el.encode('ascii')) | ||
r395 | base64_table_az = base64.standard_b64encode(json_data_az.encode('ascii')) | ||
r368 | |||
r402 | time.sleep(0.1) | ||
r368 | r = requests.get(url + base64_table_el.decode('ascii')) | ||
r402 | time.sleep(0.1) | ||
r368 | r = requests.get(url + base64_table_az.decode('ascii')) | ||
r395 | |||
r368 | if r: | ||
self.device.status = 3 | |||
|
r264 | self.device.save() | |
r368 | self.message = 'Pedestal reset' | ||
|
r185 | else: | |
r368 | return False | ||
|
r185 | except Exception as e: | |
r346 | self.message = 'Pedestal reset: {}'.format(str(e)) | ||
|
r185 | return False | |
|
r243 | ||
|
r185 | return True | |
|
r243 | ||
|
r175 | def stop_device(self): | |
|
r172 | ||
|
r185 | try: | |
r346 | command = self.device.url() + "stop" | ||
r = requests.get(command) | |||
r398 | |||
if self.mode == 'table': | |||
AX = {'az':'azimuth', 'el':'elevation'} | |||
axis = [AX[x.lower().strip()] for x in self.axis.split(',')] | |||
list_of_floats = [float(x.strip()) for x in self.angle.split(",")] | |||
self.reset_device(axis[0], list_of_floats[0]) | |||
r346 | if r: | ||
self.device.status = 4 | |||
|
r185 | self.device.save() | |
r346 | self.message = 'Pedestal stopped' | ||
|
r185 | else: | |
self.device.status = 4 | |||
self.device.save() | |||
return False | |||
except Exception as e: | |||
|
r222 | if 'No route to host' not in str(e): | |
self.device.status = 4 | |||
else: | |||
self.device.status = 0 | |||
r350 | #self.message = 'Pedestal stop: {}'.format(str(e)) | ||
self.message = "Pedestal can't start, please check network/device connection or IP address/port configuration" | |||
|
r222 | self.device.save() | |
|
r243 | return False | |
|
r185 | return True | |
|
r172 | ||
r427 | def start_device(self, name_experiment=False): | ||
r350 | |||
r407 | if self.mode == 'table': | ||
if len(self.angle.split(',')) > 1: | |||
list_speed = [] | |||
list_axis = [] | |||
for _ in range(len(self.angle.split(','))): | |||
list_axis.append(self.axis) | |||
list_speed.append(self.speed) | |||
if len(self.axis.split(',')) == 1: | |||
self.axis = ",".join(map(str, list_axis)) | |||
if len(self.speed.split(',')) == 1: | |||
self.speed = ",".join(map(str, list_speed)) | |||
r368 | AX = {'az':'azimuth', 'el':'elevation'} | ||
axis = [AX[x.lower().strip()] for x in self.axis.split(',')] | |||
if len(axis)==1: | |||
axis = axis[0] | |||
r346 | |||
r368 | try: | ||
if self.mode == 'position': | |||
r390 | url = self.device.url() + "position?params=" | ||
r368 | payload = {'axis': axis, 'position': float(self.angle)} | ||
elif self.mode == 'speed': | |||
r390 | url = self.device.url() + "speed?params=" | ||
r368 | payload = {'axis': axis, 'speed': float(self.speed)} | ||
elif self.mode == 'table': | |||
url = self.device.url() + "combinedtable?params=" | |||
list_of_floats = [float(x.strip()) for x in self.angle.split(",")] | |||
r438 | |||
# CORRECT AZ OFFSET | |||
for i, ax in enumerate(axis): | |||
if ax == 'elevation': | |||
azi = list_of_floats[i] - float(os.environ.get('AZ_OFFSET', 26.27)) | |||
if azi<0: azi += 360 | |||
list_of_floats[i] = round(azi, 2) | |||
r368 | byte_table = [] | ||
for x in list_of_floats: | |||
temp = bytearray(struct.pack("f", x)) | |||
byte_table.append(temp[3]) | |||
byte_table.append(temp[2]) | |||
byte_table.append(temp[1]) | |||
byte_table.append(temp[0]) | |||
coded_table = base64.standard_b64encode(bytes(byte_table)) | |||
coded_table_ascii = coded_table.decode('ascii') | |||
speed = [float(x.strip()) for x in self.speed.split(',')] | |||
r413 | |||
if isinstance(axis, str): | |||
axis = [axis] | |||
r374 | payload = { | ||
'arraylength': len(speed), | |||
'axis': axis, | |||
'speed': speed, | |||
r390 | 'bottom': self.min_value, | ||
r374 | 'top': self.max_value, | ||
r409 | 'table': coded_table_ascii | ||
r374 | } | ||
r368 | |||
json_data = json.dumps(payload) | |||
print(json_data) | |||
r357 | base64_table = base64.standard_b64encode(json_data.encode('ascii')) | ||
r368 | url += base64_table.decode('ascii') | ||
print(url) | |||
r = requests.get(url) | |||
r398 | |||
if self.mode == 'table': | |||
payload['table'] = list_of_floats | |||
r346 | |||
r427 | if name_experiment: | ||
name_experiment = name_experiment.split("@") | |||
r432 | dt = datetime.strptime(name_experiment[1], '%Y-%m-%dT%H-%M-%S') | ||
self.clone(experiment=name_experiment[0], experiment_date=dt, type=1) | |||
r427 | else: | ||
r429 | self.clone(type=1, experiment = 'empty', experiment_date=datetime.now()) | ||
r427 | |||
r346 | if r: | ||
|
r185 | self.device.status = 3 | |
self.device.save() | |||
r346 | self.message = 'Pedestal configured and started' | ||
|
r185 | else: | |
return False | |||
except Exception as e: | |||
|
r222 | if 'No route to host' not in str(e): | |
self.device.status = 4 | |||
else: | |||
self.device.status = 0 | |||
r350 | #self.message = 'Pedestal start: {}'.format(str(e)) | ||
self.message = "Pedestal can't start, please check network/device connection or IP address/port configuration" | |||
|
r222 | self.device.save() | |
|
r185 | return False | |
|
r243 | ||
r398 | return payload | ||
|
r172 | ||
|
r264 | def get_absolute_url_import(self): | |
r438 | return reverse('url_import_pedestal_conf', args=[str(self.id)]) |