|
|
import os
|
|
|
from datetime import datetime
|
|
|
import json
|
|
|
import requests
|
|
|
import base64
|
|
|
import struct
|
|
|
from struct import pack
|
|
|
import time
|
|
|
from django.contrib import messages
|
|
|
from django.db import models
|
|
|
from django.urls import reverse
|
|
|
from django.core.validators import MinValueValidator, MaxValueValidator
|
|
|
|
|
|
from apps.main.models import Configuration
|
|
|
|
|
|
MODE_VALUE = (
|
|
|
('position', 'Position'),
|
|
|
('speed', 'Speed'),
|
|
|
('table', 'Table')
|
|
|
)
|
|
|
|
|
|
class PedestalConfiguration(Configuration):
|
|
|
|
|
|
mode = models.CharField(
|
|
|
verbose_name='Mode',
|
|
|
max_length=10,
|
|
|
choices=MODE_VALUE,
|
|
|
null=False,
|
|
|
blank=False
|
|
|
)
|
|
|
|
|
|
axis = models.CharField(
|
|
|
verbose_name="Axis",
|
|
|
max_length=1000,
|
|
|
blank=False,
|
|
|
null=False,
|
|
|
help_text="Please separate the values with commas when using table mode"
|
|
|
)
|
|
|
|
|
|
speed = models.CharField(
|
|
|
verbose_name='Speed [°/s]',
|
|
|
max_length=1000,
|
|
|
blank=True,
|
|
|
null=True
|
|
|
)
|
|
|
|
|
|
angle = models.CharField(
|
|
|
verbose_name="Angle(s) [°]",
|
|
|
max_length=1000,
|
|
|
blank=True,
|
|
|
null=True,
|
|
|
help_text="Please separate the values with commas when using table mode"
|
|
|
)
|
|
|
|
|
|
min_value = models.FloatField(
|
|
|
verbose_name='Min angle [°]',
|
|
|
validators=[MinValueValidator(-5), MaxValueValidator(185)],
|
|
|
blank=True,
|
|
|
null=True
|
|
|
)
|
|
|
|
|
|
max_value = models.FloatField(
|
|
|
verbose_name='Max angle [°]',
|
|
|
validators=[MinValueValidator(-5), MaxValueValidator(185)],
|
|
|
blank=True,
|
|
|
null=True
|
|
|
)
|
|
|
|
|
|
class Meta:
|
|
|
db_table = 'pedestal_configurations'
|
|
|
|
|
|
def __str__(self):
|
|
|
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(',')]
|
|
|
speeds = [float(x.strip()) for x in self.speed.split(',')]
|
|
|
table = [float(x.strip()) for x in self.angle.split(',')]
|
|
|
return u'Table: Axis {}, Speed {}º/s, Steps {}'.format(axis, speeds, table)
|
|
|
|
|
|
@property
|
|
|
def label(self):
|
|
|
return str(self)
|
|
|
|
|
|
def get_absolute_url_plot(self):
|
|
|
return reverse('url_plot_pedestal_pulses', args=[str(self.id)])
|
|
|
|
|
|
def request(self, cmd, method='get', **kwargs):
|
|
|
|
|
|
req = getattr(requests, method)(self.device.url(cmd), **kwargs)
|
|
|
payload = req.json()
|
|
|
|
|
|
return payload
|
|
|
|
|
|
def status_device(self):
|
|
|
|
|
|
try:
|
|
|
payload = requests.get(self.device.url())
|
|
|
|
|
|
if payload:
|
|
|
self.device.status = 1
|
|
|
elif payload['status']=='disable':
|
|
|
self.device.status = 2
|
|
|
else:
|
|
|
self.device.status = 1
|
|
|
self.device.save()
|
|
|
self.message = 'Pedestal status: {}'.format(payload['status'])
|
|
|
return False
|
|
|
except Exception as e:
|
|
|
if 'No route to host' not in str(e):
|
|
|
self.device.status = 4
|
|
|
self.device.save()
|
|
|
self.message = 'Pedestal status: {}'.format(str(e))
|
|
|
return False
|
|
|
|
|
|
self.device.save()
|
|
|
return True
|
|
|
|
|
|
def reset_device(self, axi, angle):
|
|
|
|
|
|
try:
|
|
|
url = self.device.url() + "position?params="
|
|
|
|
|
|
payload_el = {'axis': 'elevation'}
|
|
|
payload_az = {'axis': 'azimuth'}
|
|
|
|
|
|
if axi == 'elevation':
|
|
|
# CORRECT AZ OFFSET
|
|
|
azi = angle - float(os.environ.get('AZ_OFFSET', 26.27))
|
|
|
if azi<0: azi += 360
|
|
|
payload_az['position'] = round(azi, 2)
|
|
|
payload_el['position'] = 0
|
|
|
elif axi == 'azimuth':
|
|
|
payload_el['position'] = angle
|
|
|
payload_az['position'] = 0
|
|
|
else:
|
|
|
payload_el['position'] = 0
|
|
|
payload_az['position'] = 0
|
|
|
|
|
|
json_data_el = json.dumps(payload_el)
|
|
|
json_data_az = json.dumps(payload_az)
|
|
|
|
|
|
base64_table_el = base64.standard_b64encode(json_data_el.encode('ascii'))
|
|
|
base64_table_az = base64.standard_b64encode(json_data_az.encode('ascii'))
|
|
|
|
|
|
time.sleep(0.1)
|
|
|
r = requests.get(url + base64_table_el.decode('ascii'))
|
|
|
time.sleep(0.1)
|
|
|
r = requests.get(url + base64_table_az.decode('ascii'))
|
|
|
|
|
|
if r:
|
|
|
self.device.status = 3
|
|
|
self.device.save()
|
|
|
self.message = 'Pedestal reset'
|
|
|
else:
|
|
|
return False
|
|
|
|
|
|
except Exception as e:
|
|
|
self.message = 'Pedestal reset: {}'.format(str(e))
|
|
|
return False
|
|
|
|
|
|
return True
|
|
|
|
|
|
def stop_device(self):
|
|
|
|
|
|
try:
|
|
|
command = self.device.url() + "stop"
|
|
|
r = requests.get(command)
|
|
|
|
|
|
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])
|
|
|
|
|
|
if r:
|
|
|
self.device.status = 4
|
|
|
self.device.save()
|
|
|
self.message = 'Pedestal stopped'
|
|
|
else:
|
|
|
self.device.status = 4
|
|
|
self.device.save()
|
|
|
return False
|
|
|
except Exception as e:
|
|
|
if 'No route to host' not in str(e):
|
|
|
self.device.status = 4
|
|
|
else:
|
|
|
self.device.status = 0
|
|
|
#self.message = 'Pedestal stop: {}'.format(str(e))
|
|
|
self.message = "Pedestal can't start, please check network/device connection or IP address/port configuration"
|
|
|
self.device.save()
|
|
|
return False
|
|
|
|
|
|
return True
|
|
|
|
|
|
def start_device(self, name_experiment=False):
|
|
|
|
|
|
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))
|
|
|
|
|
|
AX = {'az':'azimuth', 'el':'elevation'}
|
|
|
axis = [AX[x.lower().strip()] for x in self.axis.split(',')]
|
|
|
if len(axis)==1:
|
|
|
axis = axis[0]
|
|
|
|
|
|
try:
|
|
|
if self.mode == 'position':
|
|
|
url = self.device.url() + "position?params="
|
|
|
payload = {'axis': axis, 'position': float(self.angle)}
|
|
|
elif self.mode == 'speed':
|
|
|
url = self.device.url() + "speed?params="
|
|
|
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(",")]
|
|
|
|
|
|
# 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)
|
|
|
|
|
|
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(',')]
|
|
|
|
|
|
if isinstance(axis, str):
|
|
|
axis = [axis]
|
|
|
|
|
|
payload = {
|
|
|
'arraylength': len(speed),
|
|
|
'axis': axis,
|
|
|
'speed': speed,
|
|
|
'bottom': self.min_value,
|
|
|
'top': self.max_value,
|
|
|
'table': coded_table_ascii
|
|
|
}
|
|
|
|
|
|
json_data = json.dumps(payload)
|
|
|
print(json_data)
|
|
|
base64_table = base64.standard_b64encode(json_data.encode('ascii'))
|
|
|
url += base64_table.decode('ascii')
|
|
|
print(url)
|
|
|
r = requests.get(url)
|
|
|
|
|
|
if self.mode == 'table':
|
|
|
payload['table'] = list_of_floats
|
|
|
|
|
|
if name_experiment:
|
|
|
name_experiment = name_experiment.split("@")
|
|
|
dt = datetime.strptime(name_experiment[1], '%Y-%m-%dT%H-%M-%S')
|
|
|
self.clone(experiment=name_experiment[0], experiment_date=dt, type=1)
|
|
|
else:
|
|
|
self.clone(type=1, experiment = 'empty', experiment_date=datetime.now())
|
|
|
|
|
|
if r:
|
|
|
self.device.status = 3
|
|
|
self.device.save()
|
|
|
self.message = 'Pedestal configured and started'
|
|
|
else:
|
|
|
return False
|
|
|
except Exception as e:
|
|
|
if 'No route to host' not in str(e):
|
|
|
self.device.status = 4
|
|
|
else:
|
|
|
self.device.status = 0
|
|
|
#self.message = 'Pedestal start: {}'.format(str(e))
|
|
|
self.message = "Pedestal can't start, please check network/device connection or IP address/port configuration"
|
|
|
self.device.save()
|
|
|
return False
|
|
|
|
|
|
return payload
|
|
|
|
|
|
def get_absolute_url_import(self):
|
|
|
return reverse('url_import_pedestal_conf', args=[str(self.id)])
|