##// END OF EJS Templates
Scheduler funcional
Renato Huallpa -
r395:cfb0f9955b15
parent child
Show More
@@ -1,35 +1,35
1
1
2 REDIS_HOST=radarsys-redis
2 REDIS_HOST=radarsys-redis
3 REDIS_PORT=6300
3 REDIS_PORT=6300
4 POSTGRES_PORT_5432_TCP_ADDR=radarsys-postgres
4 POSTGRES_PORT_5432_TCP_ADDR=radarsys-postgres
5 POSTGRES_PORT_5432_TCP_PORT=5432
5 POSTGRES_PORT_5432_TCP_PORT=5432
6 #POSTGRES_HOST=postgres
6 #POSTGRES_HOST=postgres
7 POSTGRES_HOST=localhost
7 POSTGRES_HOST=localhost
8 POSTGRES_USER=docker
8 POSTGRES_USER=docker
9 POSTGRES_PASSWORD=docker
9 POSTGRES_PASSWORD=docker
10 POSTGRES_DB=radarsys
10 POSTGRES_DB=radarsys
11
11
12 # DB_NAME=radarsys
12 # DB_NAME=radarsys
13 # DB_USER=docker
13 # DB_USER=docker
14 # DB_PASSWORD=docker
14 # DB_PASSWORD=docker
15 PGDATA=/var/lib/postgresql/data
15 PGDATA=/var/lib/postgresql/data
16 LC_ALL=C.UTF-8
16 LC_ALL=C.UTF-8
17 TZ=America/Lima
17 TZ=America/Lima
18 DOCKER_DATA=/data/dockers/radarsys/
18 DOCKER_DATA=/data/dockers/radarsys/
19 LOCAL_IP=192.168.1.128
19 LOCAL_IP=192.168.1.128
20
20
21 # MQTT_SERVER=10.10.10.200
21 MQTT_SERVER=10.10.10.200
22 MQTT_SERVER = 192.168.100.5
22 # MQTT_SERVER = 192.168.100.5
23 MQTT_PORT = 1883
23 MQTT_PORT = 1883
24 MQTT_KEEPALIVE = 3660
24 MQTT_KEEPALIVE = 3660
25
25
26 MQTT_USER_ATRAD=''
26 MQTT_USER_ATRAD=''
27 MQTT_PASSWORD_ATRAD = ''
27 MQTT_PASSWORD_ATRAD = ''
28 MQTT_TOPIC_ATRAD_RECIEVE = "atrad/test4"
28 MQTT_TOPIC_ATRAD_RECIEVE = "atrad/test4"
29
29
30 MQTT_USER = abs
30 MQTT_USER = abs
31 MQTT_PASSWORD = abs
31 MQTT_PASSWORD = abs
32
32
33 TOPIC_ABS=abs/beams
33 TOPIC_ABS=abs/beams
34 TOPIC_ABS_ACK=abs/beams_ack
34 TOPIC_ABS_ACK=abs/beams_ack
35 TOPIC_ABS_CHANGE=abs/change_beam
35 TOPIC_ABS_CHANGE=abs/change_beam
@@ -1,208 +1,213
1 from django.db import models
1 from django.db import models
2 from apps.main.models import Configuration
2 from apps.main.models import Configuration
3 from apps.main.utils import Params
3 from apps.main.utils import Params
4 from django.core.validators import MinValueValidator, MaxValueValidator
4 from django.core.validators import MinValueValidator, MaxValueValidator
5
5
6 from .files import read_json_file
6 from .files import read_json_file
7 import requests
7 import requests
8
8
9 class ATRADData(models.Model):
9 class ATRADData(models.Model):
10 datetime = models.DateTimeField()
10 datetime = models.DateTimeField()
11
11
12 nstx = models.SmallIntegerField()
12 nstx = models.SmallIntegerField()
13 status = models.SmallIntegerField()
13 status = models.SmallIntegerField()
14 temp_cll = models.SmallIntegerField()
14 temp_cll = models.SmallIntegerField()
15 nboards = models.SmallIntegerField()
15 nboards = models.SmallIntegerField()
16
16
17 tempdvr = models.SmallIntegerField()
17 tempdvr = models.SmallIntegerField()
18 potincdvr = models.SmallIntegerField()
18 potincdvr = models.SmallIntegerField()
19 potretdvr = models.SmallIntegerField()
19 potretdvr = models.SmallIntegerField()
20
20
21 temp1 = models.SmallIntegerField()
21 temp1 = models.SmallIntegerField()
22 potinc1 = models.SmallIntegerField()
22 potinc1 = models.SmallIntegerField()
23 potret1 = models.SmallIntegerField()
23 potret1 = models.SmallIntegerField()
24 temp2 = models.SmallIntegerField()
24 temp2 = models.SmallIntegerField()
25 potinc2 = models.SmallIntegerField()
25 potinc2 = models.SmallIntegerField()
26 potret2 = models.SmallIntegerField()
26 potret2 = models.SmallIntegerField()
27 temp3 = models.SmallIntegerField()
27 temp3 = models.SmallIntegerField()
28 potinc3 = models.SmallIntegerField()
28 potinc3 = models.SmallIntegerField()
29 potret3 = models.SmallIntegerField()
29 potret3 = models.SmallIntegerField()
30 temp4 = models.SmallIntegerField()
30 temp4 = models.SmallIntegerField()
31 potinc4 = models.SmallIntegerField()
31 potinc4 = models.SmallIntegerField()
32 potret4 = models.SmallIntegerField()
32 potret4 = models.SmallIntegerField()
33 temp5 = models.SmallIntegerField()
33 temp5 = models.SmallIntegerField()
34 potinc5 = models.SmallIntegerField()
34 potinc5 = models.SmallIntegerField()
35 potret5 = models.SmallIntegerField()
35 potret5 = models.SmallIntegerField()
36 temp6 = models.SmallIntegerField()
36 temp6 = models.SmallIntegerField()
37 potinc6 = models.SmallIntegerField()
37 potinc6 = models.SmallIntegerField()
38 potret6 = models.SmallIntegerField()
38 potret6 = models.SmallIntegerField()
39
39
40
40
41
41
42 class Meta:
42 class Meta:
43 db_table = 'atrad_datas'
43 db_table = 'atrad_datas'
44
44
45 def __unicode__(self):
45 def __unicode__(self):
46 return u'%s' % (self.name)
46 return u'%s' % (self.name)
47
47
48 class ATRADConfiguration(Configuration):
48 class ATRADConfiguration(Configuration):
49
49
50 topic = models.PositiveIntegerField(verbose_name='Topic',validators=[MaxValueValidator(10)], default = 0)
50 topic = models.PositiveIntegerField(verbose_name='Topic',validators=[MaxValueValidator(10)], default = 0)
51
51
52 def status_device(self):
52 def status_device(self):
53
53
54 ip=self.device.ip_address
54 ip=self.device.ip_address
55 port=self.device.port_address
55 port=self.device.port_address
56
56
57 route = "http://" + str(ip) + ":" + str(port) + "/status/"
57 route = "http://" + str(ip) + ":" + str(port) + "/status/"
58 try:
58 try:
59 r = requests.get(route, timeout=0.7)
59 r = requests.get(route, timeout=0.7)
60 except Exception as e:
60 except Exception as e:
61 self.device.status = 0
61 self.device.status = 0
62 self.device.save()
62 self.device.save()
63 self.message = 'Could not read TX status: ' + str(e)
63 self.message = 'Could not read TX status: ' + str(e)
64 return False
64 return False
65
65
66 response = r.json()
66 response = r.json()
67 self.device.status = response['status']
67 self.device.status = response['status']
68 self.message = response['message']
68 self.message = response['message']
69 self.device.save()
69 self.device.save()
70
70
71 if response['components_status']==0:
71 if response['components_status']==0:
72 return False
72 return False
73
73
74 return True
74 return True
75
75
76
76
77 def start_device(self):
77 def start_device(self):
78
78
79 ip=self.device.ip_address
79 ip=self.device.ip_address
80 port=self.device.port_address
80 port=self.device.port_address
81
81
82 #---Device must be configured
82 #---Device must be configured
83 if not self.device.status == 2:
83 if not self.device.status == 2:
84 self.message = 'TX Device must be configured.'
84 self.message = 'TX Device must be configured.'
85 return False
85 return False
86 #---Frequencies from form
86 #---Frequencies from form
87 post_data = self.parms_to_dict()
87 post_data = self.parms_to_dict()
88 route = "http://" + str(ip) + ":" + str(port) + "/write/"
88 route = "http://" + str(ip) + ":" + str(port) + "/write/"
89
89
90 try:
90 try:
91 r = requests.post(route, post_data, timeout=0.7)
91 r = requests.post(route, post_data, timeout=0.7)
92 except Exception as e:
92 except Exception as e:
93 self.message = "Could not start TX device. "+str(e)
93 self.message = "Could not start TX device. "+str(e)
94 return False
94 return False
95
95
96 response = r.json()
96 response = r.json()
97 if response['status']==1:
97 if response['status']==1:
98 self.device.status = 1
98 self.device.status = 1
99 self.device.save()
99 self.device.save()
100 self.message = response['message']
100 self.message = response['message']
101 return False
101 return False
102
102
103 self.device.status = response['status']
103 self.device.status = response['status']
104 self.device.save()
104 self.device.save()
105 self.message = response['message']
105 self.message = response['message']
106
106
107 return True
107 return True
108
108
109
109
110 def stop_device(self):
110 def stop_device(self):
111
111
112 ip=self.device.ip_address
112 ip=self.device.ip_address
113 port=self.device.port_address
113 port=self.device.port_address
114
114
115 if self.device.status == 2: #Configured
115 if self.device.status == 2: #Configured
116 self.message = 'TX device is already stopped.'
116 self.message = 'TX device is already stopped.'
117 return False
117 return False
118
119 # Se crea el modo ocupado para una vez inicia el STOP
120 self.device.status = 5
121 self.device.save()
122 # Por si se demora deteniendo, que su estado sea busy
118
123
119 post_data = {"topic":0}
124 post_data = {"topic":0}
120 route = "http://" + str(ip) + ":" + str(port) + "/write/"
125 route = "http://" + str(ip) + ":" + str(port) + "/write/"
121
126
122 try:
127 try:
123 r = requests.post(route, post_data, timeout=0.7)
128 r = requests.post(route, post_data, timeout=0.7)
124 except Exception as e:
129 except Exception as e:
125 self.message = "Could not write TX parameters. "+str(e)
130 self.message = "Could not write TX parameters. "+str(e)
126 self.device.status = 0
131 self.device.status = 0
127 self.device.save()
132 self.device.save()
128 return False
133 return False
129
134
130 response = r.json()
135 response = r.json()
131 status = response['status']
136 status = response['status']
132 if status == 1:
137 if status == 1:
133 self.device.status = status
138 self.device.status = status
134 self.device.save()
139 self.device.save()
135 self.message = 'Could not stop TX device.'
140 self.message = 'Could not stop TX device.'
136 return False
141 return False
137
142
138 self.message = 'TX device has been stopped successfully.'
143 self.message = 'TX device has been stopped successfully.'
139 self.device.status = 2
144 self.device.status = 2
140 self.device.save()
145 self.device.save()
141
146
142 return True
147 return True
143
148
144
149
145 def read_device(self):
150 def read_device(self):
146
151
147 ip=self.device.ip_address
152 ip=self.device.ip_address
148 port=self.device.port_address
153 port=self.device.port_address
149
154
150 route = "http://" + str(ip) + ":" + str(port) + "/read/"
155 route = "http://" + str(ip) + ":" + str(port) + "/read/"
151 try:
156 try:
152 frequencies = requests.get(route,timeout=0.7)
157 frequencies = requests.get(route,timeout=0.7)
153 except:
158 except:
154 self.message = "Could not read TX parameters from this device"
159 self.message = "Could not read TX parameters from this device"
155 return None
160 return None
156
161
157 frequencies = frequencies.json()
162 frequencies = frequencies.json()
158 if frequencies:
163 if frequencies:
159 frequencies = frequencies.get("Frequencies")
164 frequencies = frequencies.get("Frequencies")
160 topic = frequencies.get("topic")
165 topic = frequencies.get("topic")
161
166
162 parms = {'topic': topic}
167 parms = {'topic': topic}
163
168
164 self.message = "TX parameters have been successfully read"
169 self.message = "TX parameters have been successfully read"
165 return parms
170 return parms
166 else:
171 else:
167 self.message = "Error reading TX parameters"
172 self.message = "Error reading TX parameters"
168 return None
173 return None
169
174
170
175
171 def write_device(self):
176 def write_device(self):
172
177
173 ip=self.device.ip_address
178 ip=self.device.ip_address
174 port=self.device.port_address
179 port=self.device.port_address
175
180
176 #---Frequencies from form
181 #---Frequencies from form
177 parms = self.parms_to_dict()['configurations']
182 parms = self.parms_to_dict()['configurations']
178 for parm in parms['allIds']:
183 for parm in parms['allIds']:
179 byid = parm
184 byid = parm
180 frequencies = parms['byId'][byid]
185 frequencies = parms['byId'][byid]
181 post_data = {}
186 post_data = {}
182 for data in frequencies:
187 for data in frequencies:
183 if data in ['topic']:
188 if data in ['topic']:
184 post_data[data] = frequencies[data]
189 post_data[data] = frequencies[data]
185
190
186 route = "http://" + str(ip) + ":" + str(port) + "/write/"
191 route = "http://" + str(ip) + ":" + str(port) + "/write/"
187 print (post_data)
192 print (post_data)
188 try:
193 try:
189 r = requests.post(route, post_data, timeout=0.7)
194 r = requests.post(route, post_data, timeout=0.7)
190 except:
195 except:
191 self.message = "Could not write TX parameters"
196 self.message = "Could not write TX parameters"
192 self.device.status = 0
197 self.device.status = 0
193 self.device.save()
198 self.device.save()
194 return False
199 return False
195
200
196 response = r.json()
201 response = r.json()
197 self.message = response['message']
202 self.message = response['message']
198 self.device.status = response['status']
203 self.device.status = response['status']
199 self.device.save()
204 self.device.save()
200
205
201 if self.device.status==1:
206 if self.device.status==1:
202 return False
207 return False
203
208
204 return True
209 return True
205
210
206
211
207 class Meta:
212 class Meta:
208 db_table = 'atrad_configurations' No newline at end of file
213 db_table = 'atrad_configurations'
@@ -1,184 +1,189
1 from django.db import models
1 from django.db import models
2 from apps.main.models import Configuration
2 from apps.main.models import Configuration
3 from apps.main.utils import Params
3 from apps.main.utils import Params
4 from django.core.validators import MinValueValidator, MaxValueValidator
4 from django.core.validators import MinValueValidator, MaxValueValidator
5
5
6 from .files import read_json_file
6 from .files import read_json_file
7 import requests
7 import requests
8 # Create your models here. validators=[MinValueValidator(62.5e6), MaxValueValidator(450e6)]
8 # Create your models here. validators=[MinValueValidator(62.5e6), MaxValueValidator(450e6)]
9
9
10 class CGSConfiguration(Configuration):
10 class CGSConfiguration(Configuration):
11
11
12 freq0 = models.PositiveIntegerField(verbose_name='Frequency 0 (Hz)',validators=[MaxValueValidator(450e6)], default = 60)
12 freq0 = models.PositiveIntegerField(verbose_name='Frequency 0 (Hz)',validators=[MaxValueValidator(450e6)], default = 60)
13 freq1 = models.PositiveIntegerField(verbose_name='Frequency 1 (Hz)',validators=[MaxValueValidator(450e6)], default = 60)
13 freq1 = models.PositiveIntegerField(verbose_name='Frequency 1 (Hz)',validators=[MaxValueValidator(450e6)], default = 60)
14 freq2 = models.PositiveIntegerField(verbose_name='Frequency 2 (Hz)',validators=[MaxValueValidator(450e6)], default = 60)
14 freq2 = models.PositiveIntegerField(verbose_name='Frequency 2 (Hz)',validators=[MaxValueValidator(450e6)], default = 60)
15 freq3 = models.PositiveIntegerField(verbose_name='Frequency 3 (Hz)',validators=[MaxValueValidator(450e6)], default = 60)
15 freq3 = models.PositiveIntegerField(verbose_name='Frequency 3 (Hz)',validators=[MaxValueValidator(450e6)], default = 60)
16
16
17 def verify_frequencies(self):
17 def verify_frequencies(self):
18
18
19 return True
19 return True
20
20
21
21
22 def status_device(self):
22 def status_device(self):
23
23
24 ip=self.device.ip_address
24 ip=self.device.ip_address
25 port=self.device.port_address
25 port=self.device.port_address
26
26
27 route = "http://" + str(ip) + ":" + str(port) + "/status/"
27 route = "http://" + str(ip) + ":" + str(port) + "/status/"
28 try:
28 try:
29 r = requests.get(route, timeout=0.7)
29 r = requests.get(route, timeout=0.7)
30 except Exception as e:
30 except Exception as e:
31 self.device.status = 0
31 self.device.status = 0
32 self.device.save()
32 self.device.save()
33 self.message = 'Could not read CGS status: ' + str(e)
33 self.message = 'Could not read CGS status: ' + str(e)
34 return False
34 return False
35
35
36 response = r.json()
36 response = r.json()
37 self.device.status = response['status']
37 self.device.status = response['status']
38 self.message = response['message']
38 self.message = response['message']
39 self.device.save()
39 self.device.save()
40
40
41 if response['components_status']==0:
41 if response['components_status']==0:
42 return False
42 return False
43
43
44 return True
44 return True
45
45
46
46
47 def start_device(self):
47 def start_device(self):
48
48
49 ip=self.device.ip_address
49 ip=self.device.ip_address
50 port=self.device.port_address
50 port=self.device.port_address
51
51
52 #---Device must be configured
52 #---Device must be configured
53 if not self.device.status == 2:
53 if not self.device.status == 2:
54 self.message = 'CGS Device must be configured.'
54 self.message = 'CGS Device must be configured.'
55 return False
55 return False
56 #---Frequencies from form
56 #---Frequencies from form
57 post_data = self.parms_to_dict()
57 post_data = self.parms_to_dict()
58 route = "http://" + str(ip) + ":" + str(port) + "/write/"
58 route = "http://" + str(ip) + ":" + str(port) + "/write/"
59
59
60 try:
60 try:
61 r = requests.post(route, post_data, timeout=0.7)
61 r = requests.post(route, post_data, timeout=0.7)
62 except Exception as e:
62 except Exception as e:
63 self.message = "Could not start CGS device. "+str(e)
63 self.message = "Could not start CGS device. "+str(e)
64 return False
64 return False
65
65
66 response = r.json()
66 response = r.json()
67 if response['status']==1:
67 if response['status']==1:
68 self.device.status = 1
68 self.device.status = 1
69 self.device.save()
69 self.device.save()
70 self.message = response['message']
70 self.message = response['message']
71 return False
71 return False
72
72
73 self.device.status = response['status']
73 self.device.status = response['status']
74 self.device.save()
74 self.device.save()
75 self.message = response['message']
75 self.message = response['message']
76
76
77 return True
77 return True
78
78
79
79
80 def stop_device(self):
80 def stop_device(self):
81
81
82 ip=self.device.ip_address
82 ip=self.device.ip_address
83 port=self.device.port_address
83 port=self.device.port_address
84
84
85 if self.device.status == 2: #Configured
85 if self.device.status == 2: #Configured
86 self.message = 'CGS device is already stopped.'
86 self.message = 'CGS device is already stopped.'
87 return False
87 return False
88
89 # Se crea el modo ocupado para una vez inicia el STOP
90 self.device.status = 5
91 self.device.save()
92 # Por si se demora deteniendo, que su estado sea busy
88
93
89 post_data = {"freq0":0, "freq1":0, "freq2":0, "freq3":0}
94 post_data = {"freq0":0, "freq1":0, "freq2":0, "freq3":0}
90 route = "http://" + str(ip) + ":" + str(port) + "/write/"
95 route = "http://" + str(ip) + ":" + str(port) + "/write/"
91
96
92 try:
97 try:
93 r = requests.post(route, post_data, timeout=0.7)
98 r = requests.post(route, post_data, timeout=0.7)
94 except Exception as e:
99 except Exception as e:
95 self.message = "Could not write CGS parameters. "+str(e)
100 self.message = "Could not write CGS parameters. "+str(e)
96 self.device.status = 0
101 self.device.status = 0
97 self.device.save()
102 self.device.save()
98 return False
103 return False
99
104
100 response = r.json()
105 response = r.json()
101 status = response['status']
106 status = response['status']
102 if status == 1:
107 if status == 1:
103 self.device.status = status
108 self.device.status = status
104 self.device.save()
109 self.device.save()
105 self.message = 'Could not stop CGS device.'
110 self.message = 'Could not stop CGS device.'
106 return False
111 return False
107
112
108 self.message = 'CGS device has been stopped successfully.'
113 self.message = 'CGS device has been stopped successfully.'
109 self.device.status = 2
114 self.device.status = 2
110 self.device.save()
115 self.device.save()
111
116
112 return True
117 return True
113
118
114
119
115 def read_device(self):
120 def read_device(self):
116
121
117 ip=self.device.ip_address
122 ip=self.device.ip_address
118 port=self.device.port_address
123 port=self.device.port_address
119
124
120 route = "http://" + str(ip) + ":" + str(port) + "/read/"
125 route = "http://" + str(ip) + ":" + str(port) + "/read/"
121 try:
126 try:
122 frequencies = requests.get(route,timeout=0.7)
127 frequencies = requests.get(route,timeout=0.7)
123 except:
128 except:
124 self.message = "Could not read CGS parameters from this device"
129 self.message = "Could not read CGS parameters from this device"
125 return None
130 return None
126
131
127 frequencies = frequencies.json()
132 frequencies = frequencies.json()
128 if frequencies:
133 if frequencies:
129 frequencies = frequencies.get("Frequencies")
134 frequencies = frequencies.get("Frequencies")
130 freq0 = frequencies.get("freq0")
135 freq0 = frequencies.get("freq0")
131 freq1 = frequencies.get("freq1")
136 freq1 = frequencies.get("freq1")
132 freq2 = frequencies.get("freq2")
137 freq2 = frequencies.get("freq2")
133 freq3 = frequencies.get("freq3")
138 freq3 = frequencies.get("freq3")
134
139
135 parms = {'freq0': freq0,
140 parms = {'freq0': freq0,
136 'freq1': freq1,
141 'freq1': freq1,
137 'freq2': freq2,
142 'freq2': freq2,
138 'freq3': freq3}
143 'freq3': freq3}
139
144
140 self.message = "CGS parameters have been successfully read"
145 self.message = "CGS parameters have been successfully read"
141 return parms
146 return parms
142 else:
147 else:
143 self.message = "Error reading CGS parameters"
148 self.message = "Error reading CGS parameters"
144 return None
149 return None
145
150
146
151
147 def write_device(self):
152 def write_device(self):
148
153
149 ip=self.device.ip_address
154 ip=self.device.ip_address
150 port=self.device.port_address
155 port=self.device.port_address
151
156
152 #---Frequencies from form
157 #---Frequencies from form
153 parms = self.parms_to_dict()['configurations']
158 parms = self.parms_to_dict()['configurations']
154 for parm in parms['allIds']:
159 for parm in parms['allIds']:
155 byid = parm
160 byid = parm
156 frequencies = parms['byId'][byid]
161 frequencies = parms['byId'][byid]
157 post_data = {}
162 post_data = {}
158 for data in frequencies:
163 for data in frequencies:
159 if data in ['freq0','freq1','freq2','freq3']:
164 if data in ['freq0','freq1','freq2','freq3']:
160 post_data[data] = frequencies[data]
165 post_data[data] = frequencies[data]
161
166
162 route = "http://" + str(ip) + ":" + str(port) + "/write/"
167 route = "http://" + str(ip) + ":" + str(port) + "/write/"
163 print (post_data)
168 print (post_data)
164 try:
169 try:
165 r = requests.post(route, post_data, timeout=0.7)
170 r = requests.post(route, post_data, timeout=0.7)
166 except:
171 except:
167 self.message = "Could not write CGS parameters"
172 self.message = "Could not write CGS parameters"
168 self.device.status = 0
173 self.device.status = 0
169 self.device.save()
174 self.device.save()
170 return False
175 return False
171
176
172 response = r.json()
177 response = r.json()
173 self.message = response['message']
178 self.message = response['message']
174 self.device.status = response['status']
179 self.device.status = response['status']
175 self.device.save()
180 self.device.save()
176
181
177 if self.device.status==1:
182 if self.device.status==1:
178 return False
183 return False
179
184
180 return True
185 return True
181
186
182
187
183 class Meta:
188 class Meta:
184 db_table = 'cgs_configurations'
189 db_table = 'cgs_configurations'
@@ -1,164 +1,169
1 from django.db import models
1 from django.db import models
2 from apps.main.models import Configuration
2 from apps.main.models import Configuration
3 from apps.main.utils import Params
3 from apps.main.utils import Params
4 # Create your models here.
4 # Create your models here.
5
5
6 from django.core.validators import MinValueValidator, MaxValueValidator
6 from django.core.validators import MinValueValidator, MaxValueValidator
7 from django.core.exceptions import ValidationError
7 from django.core.exceptions import ValidationError
8
8
9 from devices.dds import api, data
9 from devices.dds import api, data
10
10
11 ENABLE_TYPE = (
11 ENABLE_TYPE = (
12 (False, 'Disabled'),
12 (False, 'Disabled'),
13 (True, 'Enabled'),
13 (True, 'Enabled'),
14 )
14 )
15 MOD_TYPES = (
15 MOD_TYPES = (
16 (0, 'Single Tone'),
16 (0, 'Single Tone'),
17 (1, 'FSK'),
17 (1, 'FSK'),
18 (2, 'Ramped FSK'),
18 (2, 'Ramped FSK'),
19 (3, 'Chirp'),
19 (3, 'Chirp'),
20 (4, 'BPSK'),
20 (4, 'BPSK'),
21 )
21 )
22
22
23 class DDSConfiguration(Configuration):
23 class DDSConfiguration(Configuration):
24
24
25 DDS_NBITS = 48
25 DDS_NBITS = 48
26
26
27 clock = models.FloatField(verbose_name='Clock In (MHz)',validators=[MinValueValidator(5), MaxValueValidator(75)], null=True, default=60)
27 clock = models.FloatField(verbose_name='Clock In (MHz)',validators=[MinValueValidator(5), MaxValueValidator(75)], null=True, default=60)
28 multiplier = models.PositiveIntegerField(verbose_name='Multiplier',validators=[MinValueValidator(1), MaxValueValidator(20)], default=4)
28 multiplier = models.PositiveIntegerField(verbose_name='Multiplier',validators=[MinValueValidator(1), MaxValueValidator(20)], default=4)
29
29
30 frequencyA_Mhz = models.DecimalField(verbose_name='Frequency A (MHz)', validators=[MinValueValidator(0), MaxValueValidator(150)], max_digits=19, decimal_places=16, null=True, default=49.9200)
30 frequencyA_Mhz = models.DecimalField(verbose_name='Frequency A (MHz)', validators=[MinValueValidator(0), MaxValueValidator(150)], max_digits=19, decimal_places=16, null=True, default=49.9200)
31 frequencyA = models.BigIntegerField(verbose_name='Frequency A (Decimal)',validators=[MinValueValidator(0), MaxValueValidator(2**DDS_NBITS-1)], blank=True, null=True)
31 frequencyA = models.BigIntegerField(verbose_name='Frequency A (Decimal)',validators=[MinValueValidator(0), MaxValueValidator(2**DDS_NBITS-1)], blank=True, null=True)
32
32
33 frequencyB_Mhz = models.DecimalField(verbose_name='Frequency B (MHz)', validators=[MinValueValidator(0), MaxValueValidator(150)], max_digits=19, decimal_places=16, blank=True, null=True)
33 frequencyB_Mhz = models.DecimalField(verbose_name='Frequency B (MHz)', validators=[MinValueValidator(0), MaxValueValidator(150)], max_digits=19, decimal_places=16, blank=True, null=True)
34 frequencyB = models.BigIntegerField(verbose_name='Frequency B (Decimal)',validators=[MinValueValidator(0), MaxValueValidator(2**DDS_NBITS-1)], blank=True, null=True)
34 frequencyB = models.BigIntegerField(verbose_name='Frequency B (Decimal)',validators=[MinValueValidator(0), MaxValueValidator(2**DDS_NBITS-1)], blank=True, null=True)
35
35
36 phaseA_degrees = models.FloatField(verbose_name='Phase A (Degrees)', validators=[MinValueValidator(0), MaxValueValidator(360)], default=0)
36 phaseA_degrees = models.FloatField(verbose_name='Phase A (Degrees)', validators=[MinValueValidator(0), MaxValueValidator(360)], default=0)
37
37
38 phaseB_degrees = models.FloatField(verbose_name='Phase B (Degrees)', validators=[MinValueValidator(0), MaxValueValidator(360)], blank=True, null=True)
38 phaseB_degrees = models.FloatField(verbose_name='Phase B (Degrees)', validators=[MinValueValidator(0), MaxValueValidator(360)], blank=True, null=True)
39
39
40 modulation = models.PositiveIntegerField(verbose_name='Modulation Type', choices = MOD_TYPES, default = 0)
40 modulation = models.PositiveIntegerField(verbose_name='Modulation Type', choices = MOD_TYPES, default = 0)
41
41
42 amplitude_enabled = models.BooleanField(verbose_name='Amplitude Control', choices=ENABLE_TYPE, default=False)
42 amplitude_enabled = models.BooleanField(verbose_name='Amplitude Control', choices=ENABLE_TYPE, default=False)
43
43
44 amplitudeI = models.PositiveIntegerField(verbose_name='Amplitude CH1',validators=[MinValueValidator(0), MaxValueValidator(2**12-1)], blank=True, null=True)
44 amplitudeI = models.PositiveIntegerField(verbose_name='Amplitude CH1',validators=[MinValueValidator(0), MaxValueValidator(2**12-1)], blank=True, null=True)
45 amplitudeQ = models.PositiveIntegerField(verbose_name='Amplitude CH2',validators=[MinValueValidator(0), MaxValueValidator(2**12-1)], blank=True, null=True)
45 amplitudeQ = models.PositiveIntegerField(verbose_name='Amplitude CH2',validators=[MinValueValidator(0), MaxValueValidator(2**12-1)], blank=True, null=True)
46
46
47
47
48 def get_nbits(self):
48 def get_nbits(self):
49
49
50 return self.DDS_NBITS
50 return self.DDS_NBITS
51
51
52 def clean(self):
52 def clean(self):
53
53
54 if self.modulation in [1,2,3]:
54 if self.modulation in [1,2,3]:
55 if self.frequencyB is None or self.frequencyB_Mhz is None:
55 if self.frequencyB is None or self.frequencyB_Mhz is None:
56 raise ValidationError({
56 raise ValidationError({
57 'frequencyB': 'Frequency modulation has to be defined when FSK or Chirp modulation is selected'
57 'frequencyB': 'Frequency modulation has to be defined when FSK or Chirp modulation is selected'
58 })
58 })
59
59
60 if self.modulation in [4,]:
60 if self.modulation in [4,]:
61 if self.phaseB_degrees is None:
61 if self.phaseB_degrees is None:
62 raise ValidationError({
62 raise ValidationError({
63 'phaseB': 'Phase modulation has to be defined when BPSK modulation is selected'
63 'phaseB': 'Phase modulation has to be defined when BPSK modulation is selected'
64 })
64 })
65
65
66 self.frequencyA_Mhz = data.binary_to_freq(self.frequencyA, self.clock*self.multiplier)
66 self.frequencyA_Mhz = data.binary_to_freq(self.frequencyA, self.clock*self.multiplier)
67 self.frequencyB_Mhz = data.binary_to_freq(self.frequencyB, self.clock*self.multiplier)
67 self.frequencyB_Mhz = data.binary_to_freq(self.frequencyB, self.clock*self.multiplier)
68
68
69 def verify_frequencies(self):
69 def verify_frequencies(self):
70
70
71 return True
71 return True
72
72
73 def parms_to_text(self):
73 def parms_to_text(self):
74
74
75 my_dict = self.parms_to_dict()['configurations']['byId'][str(self.id)]
75 my_dict = self.parms_to_dict()['configurations']['byId'][str(self.id)]
76
76
77 text = data.dict_to_text(my_dict)
77 text = data.dict_to_text(my_dict)
78
78
79 return text
79 return text
80
80
81 def status_device(self):
81 def status_device(self):
82
82
83 try:
83 try:
84 answer = api.status(ip = self.device.ip_address,
84 answer = api.status(ip = self.device.ip_address,
85 port = self.device.port_address)
85 port = self.device.port_address)
86 if 'clock' in answer:
86 if 'clock' in answer:
87 self.device.status = 1
87 self.device.status = 1
88 else:
88 else:
89 self.device.status = answer[0]
89 self.device.status = answer[0]
90 self.message = 'DDS - {}'.format(answer[2:])
90 self.message = 'DDS - {}'.format(answer[2:])
91 except Exception as e:
91 except Exception as e:
92 self.message = str(e)
92 self.message = str(e)
93 self.device.status = 0
93 self.device.status = 0
94
94
95 self.device.save()
95 self.device.save()
96
96
97 if self.device.status in (0, '0'):
97 if self.device.status in (0, '0'):
98 return False
98 return False
99 else:
99 else:
100 return True
100 return True
101
101
102 def reset_device(self):
102 def reset_device(self):
103
103
104 answer = api.reset(ip = self.device.ip_address,
104 answer = api.reset(ip = self.device.ip_address,
105 port = self.device.port_address)
105 port = self.device.port_address)
106
106
107 if answer[0] != "1":
107 if answer[0] != "1":
108 self.message = 'DDS - {}'.format(answer[2:])
108 self.message = 'DDS - {}'.format(answer[2:])
109 return 0
109 return 0
110
110
111 self.message = 'DDS - {}'.format(answer[2:])
111 self.message = 'DDS - {}'.format(answer[2:])
112 return 1
112 return 1
113
113
114 def stop_device(self):
114 def stop_device(self):
115
115
116 # Se crea el modo ocupado para una vez inicia el STOP
117 self.device.status = 5
118 self.device.save()
119 # Por si se demora deteniendo, que su estado sea busy
120
116 try:
121 try:
117 answer = api.disable_rf(ip = self.device.ip_address,
122 answer = api.disable_rf(ip = self.device.ip_address,
118 port = self.device.port_address)
123 port = self.device.port_address)
119
124
120 return self.status_device()
125 return self.status_device()
121
126
122 except Exception as e:
127 except Exception as e:
123 self.message = str(e)
128 self.message = str(e)
124 return False
129 return False
125
130
126 def start_device(self):
131 def start_device(self):
127
132
128 try:
133 try:
129 answer = api.enable_rf(ip = self.device.ip_address,
134 answer = api.enable_rf(ip = self.device.ip_address,
130 port = self.device.port_address)
135 port = self.device.port_address)
131
136
132 return self.status_device()
137 return self.status_device()
133
138
134 except Exception as e:
139 except Exception as e:
135 self.message = str(e)
140 self.message = str(e)
136 return False
141 return False
137
142
138 def read_device(self):
143 def read_device(self):
139
144
140 parms = api.read_config(ip = self.device.ip_address,
145 parms = api.read_config(ip = self.device.ip_address,
141 port = self.device.port_address)
146 port = self.device.port_address)
142 if not parms:
147 if not parms:
143 self.message = "Could not read DDS parameters from this device"
148 self.message = "Could not read DDS parameters from this device"
144 return parms
149 return parms
145
150
146 self.message = ""
151 self.message = ""
147 return parms
152 return parms
148
153
149
154
150 def write_device(self):
155 def write_device(self):
151
156
152 try:
157 try:
153 answer = api.write_config(ip = self.device.ip_address,
158 answer = api.write_config(ip = self.device.ip_address,
154 port = self.device.port_address,
159 port = self.device.port_address,
155 parms = self.parms_to_dict()['configurations']['byId'][str(self.id)])
160 parms = self.parms_to_dict()['configurations']['byId'][str(self.id)])
156
161
157 return self.status_device()
162 return self.status_device()
158
163
159 except Exception as e:
164 except Exception as e:
160 self.message = str(e)
165 self.message = str(e)
161 return False
166 return False
162
167
163 class Meta:
168 class Meta:
164 db_table = 'dds_configurations'
169 db_table = 'dds_configurations'
@@ -1,305 +1,310
1 import ast
1 import ast
2 import json
2 import json
3 import requests
3 import requests
4 import numpy as np
4 import numpy as np
5 from base64 import b64encode
5 from base64 import b64encode
6 from struct import pack
6 from struct import pack
7
7
8 from django.urls import reverse
8 from django.urls import reverse
9 from django.db import models
9 from django.db import models
10 from apps.main.models import Configuration
10 from apps.main.models import Configuration
11 from apps.main.utils import Params
11 from apps.main.utils import Params
12 # Create your models here.
12 # Create your models here.
13
13
14 from django.core.validators import MinValueValidator, MaxValueValidator
14 from django.core.validators import MinValueValidator, MaxValueValidator
15 from django.core.exceptions import ValidationError
15 from django.core.exceptions import ValidationError
16
16
17 from devices.dds_rest import api, data
17 from devices.dds_rest import api, data
18
18
19 ENABLE_TYPE = (
19 ENABLE_TYPE = (
20 (False, 'Disabled'),
20 (False, 'Disabled'),
21 (True, 'Enabled'),
21 (True, 'Enabled'),
22 )
22 )
23 MOD_TYPES = (
23 MOD_TYPES = (
24 (0, 'Single Tone'),
24 (0, 'Single Tone'),
25 (1, 'FSK'),
25 (1, 'FSK'),
26 (2, 'Ramped FSK'),
26 (2, 'Ramped FSK'),
27 (3, 'Chirp'),
27 (3, 'Chirp'),
28 (4, 'BPSK'),
28 (4, 'BPSK'),
29 )
29 )
30
30
31 class DDSRestConfiguration(Configuration):
31 class DDSRestConfiguration(Configuration):
32
32
33 DDS_NBITS = 48
33 DDS_NBITS = 48
34
34
35 clock = models.FloatField(verbose_name='Clock In (MHz)',validators=[MinValueValidator(5), MaxValueValidator(75)], null=True, default=60)
35 clock = models.FloatField(verbose_name='Clock In (MHz)',validators=[MinValueValidator(5), MaxValueValidator(75)], null=True, default=60)
36 multiplier = models.PositiveIntegerField(verbose_name='Multiplier',validators=[MinValueValidator(1), MaxValueValidator(20)], default=4)
36 multiplier = models.PositiveIntegerField(verbose_name='Multiplier',validators=[MinValueValidator(1), MaxValueValidator(20)], default=4)
37
37
38 frequencyA_Mhz = models.DecimalField(verbose_name='Frequency A (MHz)', validators=[MinValueValidator(0), MaxValueValidator(150)], max_digits=19, decimal_places=16, null=True, default=49.9200)
38 frequencyA_Mhz = models.DecimalField(verbose_name='Frequency A (MHz)', validators=[MinValueValidator(0), MaxValueValidator(150)], max_digits=19, decimal_places=16, null=True, default=49.9200)
39 frequencyA = models.BigIntegerField(verbose_name='Frequency A (Decimal)',validators=[MinValueValidator(0), MaxValueValidator(2**DDS_NBITS-1)], blank=True, null=True)
39 frequencyA = models.BigIntegerField(verbose_name='Frequency A (Decimal)',validators=[MinValueValidator(0), MaxValueValidator(2**DDS_NBITS-1)], blank=True, null=True)
40
40
41 frequencyB_Mhz = models.DecimalField(verbose_name='Frequency B (MHz)', validators=[MinValueValidator(0), MaxValueValidator(150)], max_digits=19, decimal_places=16, blank=True, null=True)
41 frequencyB_Mhz = models.DecimalField(verbose_name='Frequency B (MHz)', validators=[MinValueValidator(0), MaxValueValidator(150)], max_digits=19, decimal_places=16, blank=True, null=True)
42 frequencyB = models.BigIntegerField(verbose_name='Frequency B (Decimal)',validators=[MinValueValidator(0), MaxValueValidator(2**DDS_NBITS-1)], blank=True, null=True)
42 frequencyB = models.BigIntegerField(verbose_name='Frequency B (Decimal)',validators=[MinValueValidator(0), MaxValueValidator(2**DDS_NBITS-1)], blank=True, null=True)
43
43
44 delta_frequency_Mhz = models.DecimalField(verbose_name='Delta frequency (MHz)', validators=[MinValueValidator(0), MaxValueValidator(150)], max_digits=19, decimal_places=16, blank=True, null=True)
44 delta_frequency_Mhz = models.DecimalField(verbose_name='Delta frequency (MHz)', validators=[MinValueValidator(0), MaxValueValidator(150)], max_digits=19, decimal_places=16, blank=True, null=True)
45 delta_frequency = models.BigIntegerField(verbose_name='Delta frequency (Decimal)',validators=[MinValueValidator(0), MaxValueValidator(2**DDS_NBITS-1)], blank=True, null=True)
45 delta_frequency = models.BigIntegerField(verbose_name='Delta frequency (Decimal)',validators=[MinValueValidator(0), MaxValueValidator(2**DDS_NBITS-1)], blank=True, null=True)
46
46
47 update_clock_Mhz = models.DecimalField(verbose_name='Update clock (MHz)', validators=[MinValueValidator(0), MaxValueValidator(150)], max_digits=19, decimal_places=16, blank=True, null=True)
47 update_clock_Mhz = models.DecimalField(verbose_name='Update clock (MHz)', validators=[MinValueValidator(0), MaxValueValidator(150)], max_digits=19, decimal_places=16, blank=True, null=True)
48 update_clock = models.BigIntegerField(verbose_name='Update clock (Decimal)',validators=[MinValueValidator(0), MaxValueValidator(2**32-1)], blank=True, null=True)
48 update_clock = models.BigIntegerField(verbose_name='Update clock (Decimal)',validators=[MinValueValidator(0), MaxValueValidator(2**32-1)], blank=True, null=True)
49
49
50 ramp_rate_clock_Mhz = models.DecimalField(verbose_name='Ramp rate clock (MHz)', validators=[MinValueValidator(0), MaxValueValidator(150)], max_digits=19, decimal_places=16, blank=True, null=True)
50 ramp_rate_clock_Mhz = models.DecimalField(verbose_name='Ramp rate clock (MHz)', validators=[MinValueValidator(0), MaxValueValidator(150)], max_digits=19, decimal_places=16, blank=True, null=True)
51 ramp_rate_clock = models.BigIntegerField(verbose_name='Ramp rate clock (Decimal)',validators=[MinValueValidator(0), MaxValueValidator(2**18-1)], blank=True, null=True)
51 ramp_rate_clock = models.BigIntegerField(verbose_name='Ramp rate clock (Decimal)',validators=[MinValueValidator(0), MaxValueValidator(2**18-1)], blank=True, null=True)
52
52
53 phaseA_degrees = models.FloatField(verbose_name='Phase A (Degrees)', validators=[MinValueValidator(0), MaxValueValidator(360)], default=0)
53 phaseA_degrees = models.FloatField(verbose_name='Phase A (Degrees)', validators=[MinValueValidator(0), MaxValueValidator(360)], default=0)
54
54
55 phaseB_degrees = models.FloatField(verbose_name='Phase B (Degrees)', validators=[MinValueValidator(0), MaxValueValidator(360)], blank=True, null=True)
55 phaseB_degrees = models.FloatField(verbose_name='Phase B (Degrees)', validators=[MinValueValidator(0), MaxValueValidator(360)], blank=True, null=True)
56
56
57 modulation = models.PositiveIntegerField(verbose_name='Modulation Type', choices = MOD_TYPES, default = 0)
57 modulation = models.PositiveIntegerField(verbose_name='Modulation Type', choices = MOD_TYPES, default = 0)
58
58
59 amplitude_enabled = models.BooleanField(verbose_name='Amplitude Control', choices=ENABLE_TYPE, default=False)
59 amplitude_enabled = models.BooleanField(verbose_name='Amplitude Control', choices=ENABLE_TYPE, default=False)
60
60
61 amplitudeI = models.PositiveIntegerField(verbose_name='Amplitude CH1',validators=[MinValueValidator(0), MaxValueValidator(2**12-1)], blank=True, null=True)
61 amplitudeI = models.PositiveIntegerField(verbose_name='Amplitude CH1',validators=[MinValueValidator(0), MaxValueValidator(2**12-1)], blank=True, null=True)
62 amplitudeQ = models.PositiveIntegerField(verbose_name='Amplitude CH2',validators=[MinValueValidator(0), MaxValueValidator(2**12-1)], blank=True, null=True)
62 amplitudeQ = models.PositiveIntegerField(verbose_name='Amplitude CH2',validators=[MinValueValidator(0), MaxValueValidator(2**12-1)], blank=True, null=True)
63
63
64
64
65 def get_nbits(self):
65 def get_nbits(self):
66
66
67 return self.DDS_NBITS
67 return self.DDS_NBITS
68
68
69 def clean(self):
69 def clean(self):
70
70
71 if self.modulation in [1,2,3]:
71 if self.modulation in [1,2,3]:
72 if self.frequencyB is None or self.frequencyB_Mhz is None:
72 if self.frequencyB is None or self.frequencyB_Mhz is None:
73 raise ValidationError({
73 raise ValidationError({
74 'frequencyB': 'Frequency modulation has to be defined when FSK or Chirp modulation is selected'
74 'frequencyB': 'Frequency modulation has to be defined when FSK or Chirp modulation is selected'
75 })
75 })
76
76
77 if self.modulation in [4,]:
77 if self.modulation in [4,]:
78 if self.phaseB_degrees is None:
78 if self.phaseB_degrees is None:
79 raise ValidationError({
79 raise ValidationError({
80 'phaseB': 'Phase modulation has to be defined when BPSK modulation is selected'
80 'phaseB': 'Phase modulation has to be defined when BPSK modulation is selected'
81 })
81 })
82
82
83 self.frequencyA_Mhz = data.binary_to_freq(self.frequencyA, self.clock*self.multiplier)
83 self.frequencyA_Mhz = data.binary_to_freq(self.frequencyA, self.clock*self.multiplier)
84 self.frequencyB_Mhz = data.binary_to_freq(self.frequencyB, self.clock*self.multiplier)
84 self.frequencyB_Mhz = data.binary_to_freq(self.frequencyB, self.clock*self.multiplier)
85
85
86 def verify_frequencies(self):
86 def verify_frequencies(self):
87
87
88 return True
88 return True
89
89
90 def parms_to_text(self):
90 def parms_to_text(self):
91
91
92 my_dict = self.parms_to_dict()['configurations']['byId'][str(self.id)]
92 my_dict = self.parms_to_dict()['configurations']['byId'][str(self.id)]
93
93
94 text = data.dict_to_text(my_dict)
94 text = data.dict_to_text(my_dict)
95
95
96 return text
96 return text
97
97
98 def status_device(self):
98 def status_device(self):
99 print("Status ")
99 print("Status ")
100 try:
100 try:
101 self.device.status = 0
101 self.device.status = 0
102 payload = self.request('status')
102 payload = self.request('status')
103 if payload['status']=='generating RF':
103 if payload['status']=='generating RF':
104 self.device.status = 3
104 self.device.status = 3
105 elif payload['status']=='no generating RF':
105 elif payload['status']=='no generating RF':
106 self.device.status = 2
106 self.device.status = 2
107 else:
107 else:
108 self.device.status = 1
108 self.device.status = 1
109 self.device.save()
109 self.device.save()
110 self.message = 'DDS REST status: {}'.format(payload['status'])
110 self.message = 'DDS REST status: {}'.format(payload['status'])
111 return False
111 return False
112 except Exception as e:
112 except Exception as e:
113 if 'No route to host' not in str(e):
113 if 'No route to host' not in str(e):
114 self.device.status = 4
114 self.device.status = 4
115 self.device.save()
115 self.device.save()
116 self.message = 'DDS REST status: {}'.format(str(e))
116 self.message = 'DDS REST status: {}'.format(str(e))
117 return False
117 return False
118
118
119 self.device.save()
119 self.device.save()
120 return True
120 return True
121
121
122 def reset_device(self):
122 def reset_device(self):
123
123
124 try:
124 try:
125 payload = self.request('reset', 'post')
125 payload = self.request('reset', 'post')
126 if payload['reset']=='ok':
126 if payload['reset']=='ok':
127 self.message = 'DDS REST restarted OK'
127 self.message = 'DDS REST restarted OK'
128 self.device.status = 2
128 self.device.status = 2
129 self.device.save()
129 self.device.save()
130 else:
130 else:
131 self.message = 'DDS REST restart fail'
131 self.message = 'DDS REST restart fail'
132 self.device.status = 4
132 self.device.status = 4
133 self.device.save()
133 self.device.save()
134 except Exception as e:
134 except Exception as e:
135 self.message = 'DDS REST reset: {}'.format(str(e))
135 self.message = 'DDS REST reset: {}'.format(str(e))
136 return False
136 return False
137
137
138 return True
138 return True
139
139
140 def stop_device(self):
140 def stop_device(self):
141
141
142 # Se crea el modo ocupado para una vez inicia el STOP
143 self.device.status = 5
144 self.device.save()
145 # Por si se demora deteniendo, que su estado sea busy
146
142 try:
147 try:
143 payload = self.request('stop', 'post',data=json.dumps({'_rf_enable':0}))
148 payload = self.request('stop', 'post',data=json.dumps({'_rf_enable':0}))
144 self.message = 'DDS REST: {}'.format(payload['stop'])
149 self.message = 'DDS REST: {}'.format(payload['stop'])
145 if payload['stop']=='ok':
150 if payload['stop']=='ok':
146 self.device.status = 2
151 self.device.status = 2
147 self.device.save()
152 self.device.save()
148 else:
153 else:
149 self.device.status = 4
154 self.device.status = 4
150 self.device.save()
155 self.device.save()
151 return False
156 return False
152 except Exception as e:
157 except Exception as e:
153 if 'No route to host' not in str(e):
158 if 'No route to host' not in str(e):
154 self.device.status = 4
159 self.device.status = 4
155 else:
160 else:
156 self.device.status = 0
161 self.device.status = 0
157 self.message = 'DDS REST stop: {}'.format(str(e))
162 self.message = 'DDS REST stop: {}'.format(str(e))
158 self.device.save()
163 self.device.save()
159 return False
164 return False
160
165
161 return True
166 return True
162
167
163 def start_device(self):
168 def start_device(self):
164
169
165 try:
170 try:
166 payload = self.request('start', 'post',data=json.dumps({'_rf_enable':1}))
171 payload = self.request('start', 'post',data=json.dumps({'_rf_enable':1}))
167 self.message = 'DDS REST start: {}'.format(payload['start'])
172 self.message = 'DDS REST start: {}'.format(payload['start'])
168 if payload['start']=='ok':
173 if payload['start']=='ok':
169 self.device.status = 3
174 self.device.status = 3
170 self.device.save()
175 self.device.save()
171 else:
176 else:
172 self.device.status = 2
177 self.device.status = 2
173 self.device.save()
178 self.device.save()
174 return False
179 return False
175 except Exception as e:
180 except Exception as e:
176 if 'No route to host' not in str(e):
181 if 'No route to host' not in str(e):
177 self.device.status = 4
182 self.device.status = 4
178 else:
183 else:
179 self.device.status = 0
184 self.device.status = 0
180 self.message = 'DDS REST start: {}'.format(str(e))
185 self.message = 'DDS REST start: {}'.format(str(e))
181 self.device.save()
186 self.device.save()
182 return False
187 return False
183
188
184 return True
189 return True
185
190
186 def read_device(self):
191 def read_device(self):
187
192
188 parms = self.request('read')
193 parms = self.request('read')
189 print(parms)
194 print(parms)
190 if not parms:
195 if not parms:
191 self.message = "Could not read DDS REST parameters from this device"
196 self.message = "Could not read DDS REST parameters from this device"
192 return parms
197 return parms
193
198
194 self.message = ""
199 self.message = ""
195 return parms
200 return parms
196
201
197 def arma_control(self,l_clock,l_multiplier,l_modulation):
202 def arma_control(self,l_clock,l_multiplier,l_modulation):
198 sysclock = l_clock*l_multiplier
203 sysclock = l_clock*l_multiplier
199 pll_range = 0
204 pll_range = 0
200 if(sysclock>=200):
205 if(sysclock>=200):
201 pll_range = 1
206 pll_range = 1
202 l_control = ((l_modulation<<9)+(pll_range<<22)+(l_multiplier<<16)).to_bytes(4,'little')
207 l_control = ((l_modulation<<9)+(pll_range<<22)+(l_multiplier<<16)).to_bytes(4,'little')
203 return l_control
208 return l_control
204
209
205 def conv_phase(self,l_phase):
210 def conv_phase(self,l_phase):
206
211
207 l_phase_2B = int((l_phase*(2**14)/360)).to_bytes(2,'little')
212 l_phase_2B = int((l_phase*(2**14)/360)).to_bytes(2,'little')
208 return l_phase_2B
213 return l_phase_2B
209
214
210 def arma_data_write(self):
215 def arma_data_write(self):
211 #clock = RCClock.objects.get(rc_configuration=self)
216 #clock = RCClock.objects.get(rc_configuration=self)
212 clock = self.clock
217 clock = self.clock
213 print(clock)
218 print(clock)
214 multiplier = self.multiplier
219 multiplier = self.multiplier
215 print(multiplier)
220 print(multiplier)
216 frequencyA_Mhz = self.frequencyA_Mhz
221 frequencyA_Mhz = self.frequencyA_Mhz
217 print(frequencyA_Mhz)
222 print(frequencyA_Mhz)
218 frequencyA = self.frequencyA
223 frequencyA = self.frequencyA
219 print(frequencyA)
224 print(frequencyA)
220 frequencyB_Mhz = self.frequencyB_Mhz
225 frequencyB_Mhz = self.frequencyB_Mhz
221 print(frequencyB_Mhz)
226 print(frequencyB_Mhz)
222 frequencyB = self.frequencyB
227 frequencyB = self.frequencyB
223 print(frequencyB)
228 print(frequencyB)
224 phaseA_degrees = self.phaseA_degrees or 0
229 phaseA_degrees = self.phaseA_degrees or 0
225 print(phaseA_degrees)
230 print(phaseA_degrees)
226 phaseB_degrees = self.phaseB_degrees or 0
231 phaseB_degrees = self.phaseB_degrees or 0
227 print(phaseB_degrees)
232 print(phaseB_degrees)
228 modulation = self.modulation or 0
233 modulation = self.modulation or 0
229 print(modulation)
234 print(modulation)
230 amplitude_enabled = self.amplitude_enabled or 0
235 amplitude_enabled = self.amplitude_enabled or 0
231 print(amplitude_enabled)
236 print(amplitude_enabled)
232 amplitudeI = self.amplitudeI or 0
237 amplitudeI = self.amplitudeI or 0
233 print(amplitudeI)
238 print(amplitudeI)
234 amplitudeQ = self.amplitudeQ or 0
239 amplitudeQ = self.amplitudeQ or 0
235 print(amplitudeQ)
240 print(amplitudeQ)
236 delta_frequency = self.delta_frequency or 0
241 delta_frequency = self.delta_frequency or 0
237 print(delta_frequency)
242 print(delta_frequency)
238 update_clock = self.update_clock or 0
243 update_clock = self.update_clock or 0
239 print(update_clock)
244 print(update_clock)
240 ramp_rate_clock = self.ramp_rate_clock or 0
245 ramp_rate_clock = self.ramp_rate_clock or 0
241 print(ramp_rate_clock)
246 print(ramp_rate_clock)
242 osrr = 0
247 osrr = 0
243 qdac = 0
248 qdac = 0
244 control = self.arma_control(clock,multiplier,modulation)
249 control = self.arma_control(clock,multiplier,modulation)
245 phase1 = self.conv_phase(phaseA_degrees)
250 phase1 = self.conv_phase(phaseA_degrees)
246 phase2 = self.conv_phase(phaseB_degrees)
251 phase2 = self.conv_phase(phaseB_degrees)
247
252
248 cadena_json = {'clock': (b64encode(pack('<f',clock))).decode("UTF-8"),\
253 cadena_json = {'clock': (b64encode(pack('<f',clock))).decode("UTF-8"),\
249 'multiplier': (b64encode(pack('<B',multiplier))).decode("UTF-8"),\
254 'multiplier': (b64encode(pack('<B',multiplier))).decode("UTF-8"),\
250 'frequencyA': (b64encode((frequencyA).to_bytes(6,'little'))).decode("UTF-8"),\
255 'frequencyA': (b64encode((frequencyA).to_bytes(6,'little'))).decode("UTF-8"),\
251 'frequencyB': (b64encode((frequencyB).to_bytes(6,'little'))).decode("UTF-8"),\
256 'frequencyB': (b64encode((frequencyB).to_bytes(6,'little'))).decode("UTF-8"),\
252 'delta_frequency': (b64encode((delta_frequency).to_bytes(6,'little'))).decode("UTF-8"),\
257 'delta_frequency': (b64encode((delta_frequency).to_bytes(6,'little'))).decode("UTF-8"),\
253 'update_clock': (b64encode((update_clock).to_bytes(4,'little'))).decode("UTF-8"),\
258 'update_clock': (b64encode((update_clock).to_bytes(4,'little'))).decode("UTF-8"),\
254 'ramp_rate_clock': (b64encode((ramp_rate_clock).to_bytes(3,'little'))).decode("UTF-8"),\
259 'ramp_rate_clock': (b64encode((ramp_rate_clock).to_bytes(3,'little'))).decode("UTF-8"),\
255 'control': (b64encode(control)).decode("UTF-8"),\
260 'control': (b64encode(control)).decode("UTF-8"),\
256 'amplitudeI': (b64encode((amplitudeI).to_bytes(2,'little'))).decode("UTF-8"),\
261 'amplitudeI': (b64encode((amplitudeI).to_bytes(2,'little'))).decode("UTF-8"),\
257 'amplitudeQ': (b64encode((amplitudeQ).to_bytes(2,'little'))).decode("UTF-8"),\
262 'amplitudeQ': (b64encode((amplitudeQ).to_bytes(2,'little'))).decode("UTF-8"),\
258 '_phase1': (b64encode((phase1))).decode("UTF-8"),\
263 '_phase1': (b64encode((phase1))).decode("UTF-8"),\
259 '_phase2': (b64encode((phase2))).decode("UTF-8"),\
264 '_phase2': (b64encode((phase2))).decode("UTF-8"),\
260 'osrr': (b64encode((osrr).to_bytes(1,'little'))).decode("UTF-8"),\
265 'osrr': (b64encode((osrr).to_bytes(1,'little'))).decode("UTF-8"),\
261 'qdac': (b64encode((qdac).to_bytes(2,'little'))).decode("UTF-8")
266 'qdac': (b64encode((qdac).to_bytes(2,'little'))).decode("UTF-8")
262 }
267 }
263 return cadena_json
268 return cadena_json
264
269
265 def write_device(self, raw=False):
270 def write_device(self, raw=False):
266 print("Ingreso a write")
271 print("Ingreso a write")
267 try:
272 try:
268
273
269 if not raw:
274 if not raw:
270 data = self.arma_data_write()
275 data = self.arma_data_write()
271 print(data)
276 print(data)
272 payload = self.request('write', 'post', data=json.dumps(data))
277 payload = self.request('write', 'post', data=json.dumps(data))
273 print(payload)
278 print(payload)
274 if payload['write'] == 'ok':
279 if payload['write'] == 'ok':
275 self.device.status = 3
280 self.device.status = 3
276 self.device.save()
281 self.device.save()
277 self.message = 'DDS Rest write configured and started'
282 self.message = 'DDS Rest write configured and started'
278 else:
283 else:
279 self.message = payload['programming']
284 self.message = payload['programming']
280 if payload['programming'] == 'fail':
285 if payload['programming'] == 'fail':
281 self.message = 'DDS Rest write: error programming DDS chip'
286 self.message = 'DDS Rest write: error programming DDS chip'
282 if raw:
287 if raw:
283 return b64encode(data)
288 return b64encode(data)
284
289
285
290
286 except Exception as e:
291 except Exception as e:
287 if 'No route to host' not in str(e):
292 if 'No route to host' not in str(e):
288 self.device.status = 4
293 self.device.status = 4
289 else:
294 else:
290 self.device.status = 0
295 self.device.status = 0
291 self.message = 'DDS Rest write: {}'.format(str(e))
296 self.message = 'DDS Rest write: {}'.format(str(e))
292 self.device.save()
297 self.device.save()
293 return False
298 return False
294
299
295 return True
300 return True
296
301
297 def request(self, cmd, method='get', **kwargs):
302 def request(self, cmd, method='get', **kwargs):
298 print("Ingreso a request")
303 print("Ingreso a request")
299 req = getattr(requests, method)(self.device.url(cmd), **kwargs)
304 req = getattr(requests, method)(self.device.url(cmd), **kwargs)
300 payload = req.json()
305 payload = req.json()
301
306
302 return payload
307 return payload
303
308
304 class Meta:
309 class Meta:
305 db_table = 'ddsrest_configurations'
310 db_table = 'ddsrest_configurations'
@@ -1,404 +1,409
1 import json
1 import json
2 import requests
2 import requests
3
3
4 from django.db import models
4 from django.db import models
5 from django.core.validators import MinValueValidator, MaxValueValidator
5 from django.core.validators import MinValueValidator, MaxValueValidator
6 from django.urls import reverse
6 from django.urls import reverse
7
7
8 from apps.main.models import Configuration
8 from apps.main.models import Configuration
9 from apps.main.utils import Params
9 from apps.main.utils import Params
10 from .utils import create_jarsfiles
10 from .utils import create_jarsfiles
11
11
12 # Create your models here.
12 # Create your models here.
13
13
14 EXPERIMENT_TYPE = (
14 EXPERIMENT_TYPE = (
15 (0, 'RAW_DATA'),
15 (0, 'RAW_DATA'),
16 (1, 'PDATA'),
16 (1, 'PDATA'),
17 )
17 )
18
18
19 DATA_TYPE = (
19 DATA_TYPE = (
20 (0, 'SHORT'),
20 (0, 'SHORT'),
21 (1, 'FLOAT'),
21 (1, 'FLOAT'),
22 )
22 )
23
23
24 DECODE_TYPE = (
24 DECODE_TYPE = (
25 (0, 'None'),
25 (0, 'None'),
26 (1, 'TimeDomain'),
26 (1, 'TimeDomain'),
27 (2, 'FreqDomain'),
27 (2, 'FreqDomain'),
28 (3, 'InvFreqDomain'),
28 (3, 'InvFreqDomain'),
29 )
29 )
30
30
31 FILTER = '{"id":1, "clock": 60, "multiplier": 5, "frequency": 49.92, "f_decimal": 721554506, "fir": 2, "cic_2": 12, "cic_5": 25}'
31 FILTER = '{"id":1, "clock": 60, "multiplier": 5, "frequency": 49.92, "f_decimal": 721554506, "fir": 2, "cic_2": 12, "cic_5": 25}'
32
32
33 class JARSFilter(models.Model):
33 class JARSFilter(models.Model):
34
34
35 JARS_NBITS = 32
35 JARS_NBITS = 32
36
36
37 name = models.CharField(verbose_name='Name', max_length=60, unique=True, default='')
37 name = models.CharField(verbose_name='Name', max_length=60, unique=True, default='')
38 clock = models.FloatField(verbose_name='Clock In (MHz)', validators=[
38 clock = models.FloatField(verbose_name='Clock In (MHz)', validators=[
39 MinValueValidator(5), MaxValueValidator(75)], null=True, default=60)
39 MinValueValidator(5), MaxValueValidator(75)], null=True, default=60)
40 multiplier = models.PositiveIntegerField(verbose_name='Multiplier', validators=[
40 multiplier = models.PositiveIntegerField(verbose_name='Multiplier', validators=[
41 MinValueValidator(1), MaxValueValidator(20)], default=5)
41 MinValueValidator(1), MaxValueValidator(20)], default=5)
42 frequency = models.FloatField(verbose_name='Frequency (MHz)', validators=[
42 frequency = models.FloatField(verbose_name='Frequency (MHz)', validators=[
43 MaxValueValidator(150)], null=True, default=49.9200)
43 MaxValueValidator(150)], null=True, default=49.9200)
44 f_decimal = models.BigIntegerField(verbose_name='Frequency (Decimal)', validators=[
44 f_decimal = models.BigIntegerField(verbose_name='Frequency (Decimal)', validators=[
45 MinValueValidator(-9223372036854775808), MaxValueValidator(2**JARS_NBITS-1)], null=True, default=721554505)
45 MinValueValidator(-9223372036854775808), MaxValueValidator(2**JARS_NBITS-1)], null=True, default=721554505)
46 cic_2 = models.PositiveIntegerField(verbose_name='CIC2', validators=[
46 cic_2 = models.PositiveIntegerField(verbose_name='CIC2', validators=[
47 MinValueValidator(2), MaxValueValidator(100)], default=10)
47 MinValueValidator(2), MaxValueValidator(100)], default=10)
48 scale_cic_2 = models.PositiveIntegerField(verbose_name='Scale CIC2', validators=[
48 scale_cic_2 = models.PositiveIntegerField(verbose_name='Scale CIC2', validators=[
49 MinValueValidator(0), MaxValueValidator(6)], default=1)
49 MinValueValidator(0), MaxValueValidator(6)], default=1)
50 cic_5 = models.PositiveIntegerField(verbose_name='CIC5', validators=[
50 cic_5 = models.PositiveIntegerField(verbose_name='CIC5', validators=[
51 MinValueValidator(1), MaxValueValidator(100)], default=1)
51 MinValueValidator(1), MaxValueValidator(100)], default=1)
52 scale_cic_5 = models.PositiveIntegerField(verbose_name='Scale CIC5', validators=[
52 scale_cic_5 = models.PositiveIntegerField(verbose_name='Scale CIC5', validators=[
53 MinValueValidator(0), MaxValueValidator(20)], default=5)
53 MinValueValidator(0), MaxValueValidator(20)], default=5)
54 fir = models.PositiveIntegerField(verbose_name='FIR', validators=[
54 fir = models.PositiveIntegerField(verbose_name='FIR', validators=[
55 MinValueValidator(1), MaxValueValidator(100)], default=6)
55 MinValueValidator(1), MaxValueValidator(100)], default=6)
56 scale_fir = models.PositiveIntegerField(verbose_name='Scale FIR', validators=[
56 scale_fir = models.PositiveIntegerField(verbose_name='Scale FIR', validators=[
57 MinValueValidator(0), MaxValueValidator(7)], default=3)
57 MinValueValidator(0), MaxValueValidator(7)], default=3)
58 number_taps = models.PositiveIntegerField(verbose_name='Number of taps', validators=[
58 number_taps = models.PositiveIntegerField(verbose_name='Number of taps', validators=[
59 MinValueValidator(1), MaxValueValidator(256)], default=4)
59 MinValueValidator(1), MaxValueValidator(256)], default=4)
60 taps = models.CharField(verbose_name='Taps', max_length=1600, default='0')
60 taps = models.CharField(verbose_name='Taps', max_length=1600, default='0')
61
61
62 class Meta:
62 class Meta:
63 db_table = 'jars_filters'
63 db_table = 'jars_filters'
64
64
65 def __unicode__(self):
65 def __unicode__(self):
66 return u'%s' % (self.name)
66 return u'%s' % (self.name)
67
67
68 def jsonify(self):
68 def jsonify(self):
69
69
70 data = {}
70 data = {}
71 ignored = ()
71 ignored = ()
72
72
73 for field in self._meta.fields:
73 for field in self._meta.fields:
74 if field.name in ignored:
74 if field.name in ignored:
75 continue
75 continue
76 data[field.name] = field.value_from_object(self)
76 data[field.name] = field.value_from_object(self)
77
77
78 return data
78 return data
79
79
80 def parms_to_dict(self):
80 def parms_to_dict(self):
81
81
82 parameters = {}
82 parameters = {}
83
83
84 parameters['name'] = self.name
84 parameters['name'] = self.name
85 parameters['clock'] = float(self.clock)
85 parameters['clock'] = float(self.clock)
86 parameters['multiplier'] = int(self.multiplier)
86 parameters['multiplier'] = int(self.multiplier)
87 parameters['frequency'] = float(self.frequency)
87 parameters['frequency'] = float(self.frequency)
88 parameters['f_decimal'] = int(self.frequency)
88 parameters['f_decimal'] = int(self.frequency)
89 parameters['fir'] = int(self.fir)
89 parameters['fir'] = int(self.fir)
90 parameters['cic_2'] = int(self.cic_2)
90 parameters['cic_2'] = int(self.cic_2)
91 parameters['cic_5'] = int(self.cic_5)
91 parameters['cic_5'] = int(self.cic_5)
92
92
93 return parameters
93 return parameters
94
94
95 def dict_to_parms(self, parameters):
95 def dict_to_parms(self, parameters):
96
96
97 self.name = parameters['name']
97 self.name = parameters['name']
98 self.clock = parameters['clock']
98 self.clock = parameters['clock']
99 self.multiplier = parameters['multiplier']
99 self.multiplier = parameters['multiplier']
100 self.frequency = parameters['frequency']
100 self.frequency = parameters['frequency']
101 self.f_decimal = parameters['f_decimal']
101 self.f_decimal = parameters['f_decimal']
102 self.fir = parameters['fir']
102 self.fir = parameters['fir']
103 self.cic_2 = parameters['cic_2']
103 self.cic_2 = parameters['cic_2']
104 self.cic_5 = parameters['cic_5']
104 self.cic_5 = parameters['cic_5']
105
105
106 def dict_to_parms_new(self, parameters):
106 def dict_to_parms_new(self, parameters):
107
107
108 self.name = parameters['name']
108 self.name = parameters['name']
109 self.clock = parameters['clock']
109 self.clock = parameters['clock']
110 self.multiplier = parameters['multiplier']
110 self.multiplier = parameters['multiplier']
111 self.frequency = parameters['frequency']
111 self.frequency = parameters['frequency']
112 self.f_decimal = parameters['f_decimal']
112 self.f_decimal = parameters['f_decimal']
113 self.fir = parameters['fir']
113 self.fir = parameters['fir']
114 self.cic_2 = parameters['cic_2']
114 self.cic_2 = parameters['cic_2']
115 self.cic_5 = parameters['cic_5']
115 self.cic_5 = parameters['cic_5']
116 self.scale_fir = parameters['scale_fir']
116 self.scale_fir = parameters['scale_fir']
117 self.scale_cic_2 = parameters['scale_cic_2']
117 self.scale_cic_2 = parameters['scale_cic_2']
118 self.scale_cic_5 = parameters['scale_cic_5']
118 self.scale_cic_5 = parameters['scale_cic_5']
119 self.number_taps = parameters['number_taps']
119 self.number_taps = parameters['number_taps']
120 self.taps = parameters['taps']
120 self.taps = parameters['taps']
121
121
122 class JARSConfiguration(Configuration):
122 class JARSConfiguration(Configuration):
123
123
124 ADC_RESOLUTION = 8
124 ADC_RESOLUTION = 8
125 PCI_DIO_BUSWIDTH = 32
125 PCI_DIO_BUSWIDTH = 32
126 HEADER_VERSION = 1103
126 HEADER_VERSION = 1103
127 BEGIN_ON_START = True
127 BEGIN_ON_START = True
128 REFRESH_RATE = 1
128 REFRESH_RATE = 1
129
129
130 exp_type = models.PositiveIntegerField(
130 exp_type = models.PositiveIntegerField(
131 verbose_name='Experiment Type', choices=EXPERIMENT_TYPE, default=0)
131 verbose_name='Experiment Type', choices=EXPERIMENT_TYPE, default=0)
132 cards_number = models.PositiveIntegerField(verbose_name='Number of Cards', validators=[
132 cards_number = models.PositiveIntegerField(verbose_name='Number of Cards', validators=[
133 MinValueValidator(1), MaxValueValidator(4)], default=1)
133 MinValueValidator(1), MaxValueValidator(4)], default=1)
134 channels_number = models.PositiveIntegerField(verbose_name='Number of Channels', validators=[
134 channels_number = models.PositiveIntegerField(verbose_name='Number of Channels', validators=[
135 MinValueValidator(1), MaxValueValidator(8)], default=5)
135 MinValueValidator(1), MaxValueValidator(8)], default=5)
136 channels = models.CharField(
136 channels = models.CharField(
137 verbose_name='Channels', max_length=15, default='1,2,3,4,5')
137 verbose_name='Channels', max_length=15, default='1,2,3,4,5')
138 data_type = models.PositiveIntegerField(
138 data_type = models.PositiveIntegerField(
139 verbose_name='Data Type', choices=DATA_TYPE, default=0)
139 verbose_name='Data Type', choices=DATA_TYPE, default=0)
140 raw_data_blocks = models.PositiveIntegerField(
140 raw_data_blocks = models.PositiveIntegerField(
141 verbose_name='Raw Data Blocks', validators=[MaxValueValidator(5000)], default=60)
141 verbose_name='Raw Data Blocks', validators=[MaxValueValidator(5000)], default=60)
142 profiles_block = models.PositiveIntegerField(
142 profiles_block = models.PositiveIntegerField(
143 verbose_name='Profiles Per Block', default=400)
143 verbose_name='Profiles Per Block', default=400)
144 acq_profiles = models.PositiveIntegerField(
144 acq_profiles = models.PositiveIntegerField(
145 verbose_name='Acquired Profiles', default=400)
145 verbose_name='Acquired Profiles', default=400)
146 ftp_interval = models.PositiveIntegerField(
146 ftp_interval = models.PositiveIntegerField(
147 verbose_name='FTP Interval', default=60)
147 verbose_name='FTP Interval', default=60)
148 fftpoints = models.PositiveIntegerField(
148 fftpoints = models.PositiveIntegerField(
149 verbose_name='FFT Points', default=16)
149 verbose_name='FFT Points', default=16)
150 cohe_integr_str = models.PositiveIntegerField(
150 cohe_integr_str = models.PositiveIntegerField(
151 verbose_name='Coh. Int. Stride', validators=[MinValueValidator(1)], default=30)
151 verbose_name='Coh. Int. Stride', validators=[MinValueValidator(1)], default=30)
152 cohe_integr = models.PositiveIntegerField(
152 cohe_integr = models.PositiveIntegerField(
153 verbose_name='Coherent Integrations', validators=[MinValueValidator(1)], default=30)
153 verbose_name='Coherent Integrations', validators=[MinValueValidator(1)], default=30)
154 incohe_integr = models.PositiveIntegerField(
154 incohe_integr = models.PositiveIntegerField(
155 verbose_name='Incoherent Integrations', validators=[MinValueValidator(1)], default=30)
155 verbose_name='Incoherent Integrations', validators=[MinValueValidator(1)], default=30)
156 decode_data = models.PositiveIntegerField(
156 decode_data = models.PositiveIntegerField(
157 verbose_name='Decode Data', choices=DECODE_TYPE, default=0)
157 verbose_name='Decode Data', choices=DECODE_TYPE, default=0)
158 post_coh_int = models.BooleanField(
158 post_coh_int = models.BooleanField(
159 verbose_name='Post Coherent Integration', default=False)
159 verbose_name='Post Coherent Integration', default=False)
160 spectral_number = models.PositiveIntegerField(
160 spectral_number = models.PositiveIntegerField(
161 verbose_name='# Spectral Combinations', validators=[MinValueValidator(1)], default=1)
161 verbose_name='# Spectral Combinations', validators=[MinValueValidator(1)], default=1)
162 spectral = models.CharField(
162 spectral = models.CharField(
163 verbose_name='Combinations', max_length=5000, default='[0, 0],')
163 verbose_name='Combinations', max_length=5000, default='[0, 0],')
164 create_directory = models.BooleanField(
164 create_directory = models.BooleanField(
165 verbose_name='Create Directory Per Day', default=True)
165 verbose_name='Create Directory Per Day', default=True)
166 include_expname = models.BooleanField(
166 include_expname = models.BooleanField(
167 verbose_name='Experiment Name in Directory', default=False)
167 verbose_name='Experiment Name in Directory', default=False)
168 #view_raw_data = models.BooleanField(verbose_name='View Raw Data', default=True)
168 #view_raw_data = models.BooleanField(verbose_name='View Raw Data', default=True)
169 save_ch_dc = models.BooleanField(
169 save_ch_dc = models.BooleanField(
170 verbose_name='Save Channels DC', default=True)
170 verbose_name='Save Channels DC', default=True)
171 save_data = models.BooleanField(verbose_name='Save Data', default=True)
171 save_data = models.BooleanField(verbose_name='Save Data', default=True)
172 filter_parms = models.CharField(
172 filter_parms = models.CharField(
173 max_length=10000, default=FILTER)
173 max_length=10000, default=FILTER)
174 filter = models.ForeignKey(
174 filter = models.ForeignKey(
175 'JARSFilter', verbose_name='Filter', null=True, blank=True, on_delete=models.CASCADE)
175 'JARSFilter', verbose_name='Filter', null=True, blank=True, on_delete=models.CASCADE)
176
176
177 class Meta:
177 class Meta:
178 db_table = 'jars_configurations'
178 db_table = 'jars_configurations'
179
179
180 def filter_resolution(self):
180 def filter_resolution(self):
181 filter_parms = json.loads(self.filter_parms)
181 filter_parms = json.loads(self.filter_parms)
182 clock = float(filter_parms['clock'])
182 clock = float(filter_parms['clock'])
183 cic_2 = filter_parms['cic_2']
183 cic_2 = filter_parms['cic_2']
184 cic_5 = filter_parms['cic_5']
184 cic_5 = filter_parms['cic_5']
185 fir = filter_parms['fir']
185 fir = filter_parms['fir']
186 resolution = round((clock/(cic_2*cic_5*fir)), 2)
186 resolution = round((clock/(cic_2*cic_5*fir)), 2)
187 return resolution
187 return resolution
188
188
189 def dict_to_parms(self, params, id=None):
189 def dict_to_parms(self, params, id=None):
190
190
191 if id is not None:
191 if id is not None:
192 data = Params(params).get_conf(id_conf=id)
192 data = Params(params).get_conf(id_conf=id)
193 else:
193 else:
194 data = Params(params).get_conf(dtype='jars')
194 data = Params(params).get_conf(dtype='jars')
195 data['filter_parms'] = params['filter_parms']
195 data['filter_parms'] = params['filter_parms']
196
196
197 # self.name = data['name']
197 # self.name = data['name']
198 self.exp_type = data['exp_type']
198 self.exp_type = data['exp_type']
199 #----PDATA----
199 #----PDATA----
200 if self.exp_type == 1:
200 if self.exp_type == 1:
201 self.incohe_integr = data['incohe_integr']
201 self.incohe_integr = data['incohe_integr']
202 self.spectral_number = data['spectral_number']
202 self.spectral_number = data['spectral_number']
203 self.spectral = data['spectral']
203 self.spectral = data['spectral']
204 self.fftpoints = data['fftpoints']
204 self.fftpoints = data['fftpoints']
205 self.save_ch_dc = data['save_ch_dc']
205 self.save_ch_dc = data['save_ch_dc']
206 else:
206 else:
207 self.raw_data_blocks = data['raw_data_blocks']
207 self.raw_data_blocks = data['raw_data_blocks']
208 #----PDATA----
208 #----PDATA----
209 self.cards_number = data['cards_number']
209 self.cards_number = data['cards_number']
210 self.channels_number = data['channels_number']
210 self.channels_number = data['channels_number']
211 self.channels = data['channels']
211 self.channels = data['channels']
212 self.data_type = data['data_type']
212 self.data_type = data['data_type']
213 self.profiles_block = data['profiles_block']
213 self.profiles_block = data['profiles_block']
214 self.acq_profiles = data['acq_profiles']
214 self.acq_profiles = data['acq_profiles']
215 self.ftp_interval = data['ftp_interval']
215 self.ftp_interval = data['ftp_interval']
216 self.cohe_integr_str = data['cohe_integr_str']
216 self.cohe_integr_str = data['cohe_integr_str']
217 self.cohe_integr = data['cohe_integr']
217 self.cohe_integr = data['cohe_integr']
218 #----DECODE----
218 #----DECODE----
219 self.decode_data = data['decode_data']
219 self.decode_data = data['decode_data']
220 self.post_coh_int = data['post_coh_int']
220 self.post_coh_int = data['post_coh_int']
221 #----DECODE----
221 #----DECODE----
222 self.create_directory = data['create_directory']
222 self.create_directory = data['create_directory']
223 self.include_expname = data['include_expname']
223 self.include_expname = data['include_expname']
224 self.save_data = data['save_data']
224 self.save_data = data['save_data']
225 self.filter_parms = json.dumps(data['filter_parms'])
225 self.filter_parms = json.dumps(data['filter_parms'])
226
226
227 self.save()
227 self.save()
228
228
229 def parms_to_text(self, file_format='jars'):
229 def parms_to_text(self, file_format='jars'):
230
230
231 data = self.experiment.parms_to_dict()
231 data = self.experiment.parms_to_dict()
232
232
233 for key in data['configurations']['allIds']:
233 for key in data['configurations']['allIds']:
234 if data['configurations']['byId'][key]['device_type'] in ('dds', 'cgs'):
234 if data['configurations']['byId'][key]['device_type'] in ('dds', 'cgs'):
235 data['configurations']['allIds'].remove(key)
235 data['configurations']['allIds'].remove(key)
236 data['configurations']['byId'].pop(key)
236 data['configurations']['byId'].pop(key)
237 elif data['configurations']['byId'][key]['device_type'] == 'jars':
237 elif data['configurations']['byId'][key]['device_type'] == 'jars':
238 data['configurations']['byId'][key] = self.parms_to_dict(
238 data['configurations']['byId'][key] = self.parms_to_dict(
239 )['configurations']['byId'][str(self.pk)]
239 )['configurations']['byId'][str(self.pk)]
240 elif data['configurations']['byId'][key]['device_type'] == 'rc':
240 elif data['configurations']['byId'][key]['device_type'] == 'rc':
241 data['configurations']['byId'][key]['pulses'] = ''
241 data['configurations']['byId'][key]['pulses'] = ''
242 data['configurations']['byId'][key]['delays'] = ''
242 data['configurations']['byId'][key]['delays'] = ''
243 rc_ids = [pk for pk in data['configurations']['allIds']
243 rc_ids = [pk for pk in data['configurations']['allIds']
244 if data['configurations']['byId'][pk]['device_type'] == 'rc']
244 if data['configurations']['byId'][pk]['device_type'] == 'rc']
245 mix_ids = [pk for pk in rc_ids if data['configurations']
245 mix_ids = [pk for pk in rc_ids if data['configurations']
246 ['byId'][pk]['mix']]
246 ['byId'][pk]['mix']]
247
247
248 if mix_ids:
248 if mix_ids:
249 params = data['configurations']['byId'][mix_ids[0]]['parameters']
249 params = data['configurations']['byId'][mix_ids[0]]['parameters']
250 rc = data['configurations']['byId'][params.split(
250 rc = data['configurations']['byId'][params.split(
251 '-')[0].split('|')[0]]
251 '-')[0].split('|')[0]]
252 rc['mix'] = True
252 rc['mix'] = True
253 data['configurations']['byId'][rc['id']] = rc
253 data['configurations']['byId'][rc['id']] = rc
254 elif len(rc_ids) == 0:
254 elif len(rc_ids) == 0:
255 self.message = 'File needs RC configuration'
255 self.message = 'File needs RC configuration'
256 return ''
256 return ''
257
257
258 json_data = json.dumps(data)
258 json_data = json.dumps(data)
259 racp_file, filter_file = create_jarsfiles(json_data)
259 racp_file, filter_file = create_jarsfiles(json_data)
260 if file_format == 'racp':
260 if file_format == 'racp':
261 return racp_file
261 return racp_file
262
262
263 return filter_file
263 return filter_file
264
264
265 def request(self, cmd, method='get', **kwargs):
265 def request(self, cmd, method='get', **kwargs):
266
266
267 req = getattr(requests, method)(self.device.url(cmd), **kwargs)
267 req = getattr(requests, method)(self.device.url(cmd), **kwargs)
268 payload = req.json()
268 payload = req.json()
269 return payload
269 return payload
270
270
271 def status_device(self):
271 def status_device(self):
272
272
273 try:
273 try:
274 payload = self.request('status',
274 payload = self.request('status',
275 params={'name': self.experiment.name})
275 params={'name': self.experiment.name})
276 self.device.status = payload['status']
276 self.device.status = payload['status']
277 self.device.save()
277 self.device.save()
278 self.message = payload['message']
278 self.message = payload['message']
279 except Exception as e:
279 except Exception as e:
280 self.device.status = 0
280 self.device.status = 0
281 self.message = str(e)
281 self.message = str(e)
282 self.device.save()
282 self.device.save()
283 return False
283 return False
284
284
285 return True
285 return True
286
286
287 def stop_device(self):
287 def stop_device(self):
288
288
289 # Se crea el modo ocupado para una vez inicia el STOP
290 self.device.status = 5
291 self.device.save()
292 # Por si se demora deteniendo, que su estado sea busy
293
289 try:
294 try:
290 payload = self.request('stop', 'post')
295 payload = self.request('stop', 'post')
291 self.device.status = payload['status']
296 self.device.status = payload['status']
292 self.device.save()
297 self.device.save()
293 self.message = payload['message']
298 self.message = payload['message']
294 except Exception as e:
299 except Exception as e:
295 self.device.status = 0
300 self.device.status = 0
296 self.message = str(e)
301 self.message = str(e)
297 self.device.save()
302 self.device.save()
298 return False
303 return False
299
304
300 return True
305 return True
301
306
302 def read_device(self):
307 def read_device(self):
303
308
304 try:
309 try:
305 payload = self.request(
310 payload = self.request(
306 'read', params={'name': self.experiment.name})
311 'read', params={'name': self.experiment.name})
307 self.message = 'Configuration loaded'
312 self.message = 'Configuration loaded'
308 except:
313 except:
309 self.device.status = 0
314 self.device.status = 0
310 self.device.save()
315 self.device.save()
311 self.message = 'Could not read JARS configuration.'
316 self.message = 'Could not read JARS configuration.'
312 return False
317 return False
313
318
314 return payload
319 return payload
315
320
316 def write_device(self):
321 def write_device(self):
317
322
318 if self.device.status == 3:
323 if self.device.status == 3:
319 self.message = 'Could not configure device. Software Acquisition is running'
324 self.message = 'Could not configure device. Software Acquisition is running'
320 print('Could not configure device. Software Acquisition is running')
325 print('Could not configure device. Software Acquisition is running')
321 return False
326 return False
322
327
323 data = self.experiment.parms_to_dict()
328 data = self.experiment.parms_to_dict()
324 #print(data)
329 #print(data)
325 for key in data['configurations']['allIds']:
330 for key in data['configurations']['allIds']:
326 if data['configurations']['byId'][key]['device_type'] in ('dds', 'cgs'):
331 if data['configurations']['byId'][key]['device_type'] in ('dds', 'cgs'):
327 data['configurations']['allIds'].remove(key)
332 data['configurations']['allIds'].remove(key)
328 data['configurations']['byId'].pop(key)
333 data['configurations']['byId'].pop(key)
329 elif data['configurations']['byId'][key]['device_type'] == 'rc':
334 elif data['configurations']['byId'][key]['device_type'] == 'rc':
330 data['configurations']['byId'][key]['pulses'] = ''
335 data['configurations']['byId'][key]['pulses'] = ''
331 data['configurations']['byId'][key]['delays'] = ''
336 data['configurations']['byId'][key]['delays'] = ''
332 rc_ids = [pk for pk in data['configurations']['allIds']
337 rc_ids = [pk for pk in data['configurations']['allIds']
333 if data['configurations']['byId'][pk]['device_type'] == 'rc']
338 if data['configurations']['byId'][pk]['device_type'] == 'rc']
334 if len(rc_ids) == 0:
339 if len(rc_ids) == 0:
335 self.message = 'Missing RC configuration'
340 self.message = 'Missing RC configuration'
336 return False
341 return False
337
342
338 json_data = json.dumps(data)
343 json_data = json.dumps(data)
339 print("STATUS:", self.device.status,flush=True)
344 print("STATUS:", self.device.status,flush=True)
340
345
341 try:
346 try:
342 payload = self.request('write', 'post', json=json_data)
347 payload = self.request('write', 'post', json=json_data)
343 self.device.status = payload['status']
348 self.device.status = payload['status']
344 self.message = payload['message']
349 self.message = payload['message']
345 self.device.save()
350 self.device.save()
346 if self.device.status == 1:
351 if self.device.status == 1:
347 return False
352 return False
348
353
349 except Exception as e:
354 except Exception as e:
350 self.device.status = 0
355 self.device.status = 0
351 self.message = str(e)
356 self.message = str(e)
352 self.device.save()
357 self.device.save()
353 return False
358 return False
354 return True
359 return True
355
360
356 def start_device(self):
361 def start_device(self):
357
362
358 try:
363 try:
359 payload = self.request('start', 'post',
364 payload = self.request('start', 'post',
360 json={'name': self.experiment.name})
365 json={'name': self.experiment.name})
361 self.device.status = payload['status']
366 self.device.status = payload['status']
362 self.message = payload['message']
367 self.message = payload['message']
363 self.device.save()
368 self.device.save()
364 if self.device.status == 1:
369 if self.device.status == 1:
365 return False
370 return False
366
371
367 except Exception as e:
372 except Exception as e:
368 self.device.status = 0
373 self.device.status = 0
369 self.message = str(e)
374 self.message = str(e)
370 self.device.save()
375 self.device.save()
371 return False
376 return False
372 return True
377 return True
373
378
374 def get_log(self):
379 def get_log(self):
375
380
376 payload = None
381 payload = None
377
382
378 try:
383 try:
379 payload = requests.get(self.device.url('get_log'), params={
384 payload = requests.get(self.device.url('get_log'), params={
380 'name': self.experiment.name})
385 'name': self.experiment.name})
381 except:
386 except:
382 self.device.status = 0
387 self.device.status = 0
383 self.device.save()
388 self.device.save()
384 self.message = 'Jars API is not running.'
389 self.message = 'Jars API is not running.'
385 return False
390 return False
386
391
387 self.message = 'Jars API is running'
392 self.message = 'Jars API is running'
388
393
389 return payload
394 return payload
390
395
391 def update_from_file(self, filename):
396 def update_from_file(self, filename):
392
397
393 f = JARSFile(filename)
398 f = JARSFile(filename)
394 self.dict_to_parms(f.data)
399 self.dict_to_parms(f.data)
395 self.save()
400 self.save()
396
401
397 def get_absolute_url_import(self):
402 def get_absolute_url_import(self):
398 return reverse('url_import_jars_conf', args=[str(self.id)])
403 return reverse('url_import_jars_conf', args=[str(self.id)])
399
404
400 def get_absolute_url_read(self):
405 def get_absolute_url_read(self):
401 return reverse('url_read_jars_conf', args=[str(self.id)])
406 return reverse('url_read_jars_conf', args=[str(self.id)])
402
407
403 def get_absolute_url_log(self):
408 def get_absolute_url_log(self):
404 return reverse('url_get_jars_log', args=[str(self.id)])
409 return reverse('url_get_jars_log', args=[str(self.id)])
@@ -1,856 +1,856
1
1
2 import os
2 import os
3 import json
3 import json
4 import requests
4 import requests
5 import time
5 import time
6 from datetime import datetime
6 from datetime import datetime
7
7
8 try:
8 try:
9 from polymorphic.models import PolymorphicModel
9 from polymorphic.models import PolymorphicModel
10 except:
10 except:
11 from polymorphic import PolymorphicModel
11 from polymorphic import PolymorphicModel
12
12
13 from django.template.base import kwarg_re
13 from django.template.base import kwarg_re
14 from django.db import models
14 from django.db import models
15 from django.urls import reverse
15 from django.urls import reverse
16 from django.core.validators import MinValueValidator, MaxValueValidator
16 from django.core.validators import MinValueValidator, MaxValueValidator
17 from django.shortcuts import get_object_or_404
17 from django.shortcuts import get_object_or_404
18 from django.contrib.auth.models import User
18 from django.contrib.auth.models import User
19 from django.db.models.signals import post_save
19 from django.db.models.signals import post_save
20 from django.dispatch import receiver
20 from django.dispatch import receiver
21
21
22 from apps.main.utils import Params
22 from apps.main.utils import Params
23 from apps.rc.utils import RCFile
23 from apps.rc.utils import RCFile
24 from apps.jars.utils import RacpFile
24 from apps.jars.utils import RacpFile
25 from devices.dds import api as dds_api
25 from devices.dds import api as dds_api
26 from devices.dds import data as dds_data
26 from devices.dds import data as dds_data
27
27
28
28
29 DEV_PORTS = {
29 DEV_PORTS = {
30 'rc' : 2000,
30 'rc' : 2000,
31 'dds' : 2000,
31 'dds' : 2000,
32 'jars' : 2000,
32 'jars' : 2000,
33 'usrp' : 2000,
33 'usrp' : 2000,
34 'cgs' : 8080,
34 'cgs' : 8080,
35 'abs' : 8080,
35 'abs' : 8080,
36 'dds_rest': 80
36 'dds_rest': 80
37 }
37 }
38
38
39 RADAR_STATES = (
39 RADAR_STATES = (
40 (0, 'No connected'),
40 (0, 'No connected'),
41 (1, 'Connected'),
41 (1, 'Connected'),
42 (2, 'Configured'),
42 (2, 'Configured'),
43 (3, 'Running'),
43 (3, 'Running'),
44 (4, 'Scheduled'),
44 (4, 'Scheduled'),
45 )
45 )
46
46
47 EXPERIMENT_TYPE = (
47 EXPERIMENT_TYPE = (
48 (0, 'RAW_DATA'),
48 (0, 'RAW_DATA'),
49 (1, 'PDATA'),
49 (1, 'PDATA'),
50 )
50 )
51
51
52 DECODE_TYPE = (
52 DECODE_TYPE = (
53 (0, 'None'),
53 (0, 'None'),
54 (1, 'TimeDomain'),
54 (1, 'TimeDomain'),
55 (2, 'FreqDomain'),
55 (2, 'FreqDomain'),
56 (3, 'InvFreqDomain'),
56 (3, 'InvFreqDomain'),
57 )
57 )
58
58
59 DEV_STATES = (
59 DEV_STATES = (
60 (0, 'No connected'),
60 (0, 'No connected'),
61 (1, 'Connected'),
61 (1, 'Connected'),
62 (2, 'Configured'),
62 (2, 'Configured'),
63 (3, 'Running'),
63 (3, 'Running'),
64 (4, 'Unknown'),
64 (4, 'Unknown'),
65 (5, 'Busy')
65 (5, 'Busy')
66 )
66 )
67
67
68 DEV_TYPES = (
68 DEV_TYPES = (
69 ('', 'Select a device type'),
69 ('', 'Select a device type'),
70 ('rc', 'Radar Controller'),
70 ('rc', 'Radar Controller'),
71 ('dds', 'Direct Digital Synthesizer'),
71 ('dds', 'Direct Digital Synthesizer'),
72 ('jars', 'Jicamarca Radar Acquisition System'),
72 ('jars', 'Jicamarca Radar Acquisition System'),
73 ('usrp', 'Universal Software Radio Peripheral'),
73 ('usrp', 'Universal Software Radio Peripheral'),
74 ('cgs', 'Clock Generator System'),
74 ('cgs', 'Clock Generator System'),
75 ('abs', 'Automatic Beam Switching'),
75 ('abs', 'Automatic Beam Switching'),
76 ('dds_rest', 'Direct Digital Synthesizer_REST'),
76 ('dds_rest', 'Direct Digital Synthesizer_REST'),
77 ('atrad', 'Transmitter ATRAD'),
77 ('atrad', 'Transmitter ATRAD'),
78 )
78 )
79
79
80 EXP_STATES = (
80 EXP_STATES = (
81 (0,'Error'), #RED
81 (0,'Error'), #RED
82 (1,'Cancelled'), #YELLOW
82 (1,'Cancelled'), #YELLOW
83 (2,'Running'), #GREEN
83 (2,'Running'), #GREEN
84 (3,'Scheduled'), #BLUE
84 (3,'Scheduled'), #BLUE
85 (4,'Unknown'), #WHITE
85 (4,'Unknown'), #WHITE
86 (5,'Busy'),
86 )
87 )
87
88
88 CONF_TYPES = (
89 CONF_TYPES = (
89 (0, 'Active'),
90 (0, 'Active'),
90 (1, 'Historical'),
91 (1, 'Historical'),
91 )
92 )
92
93
93 class Profile(models.Model):
94 class Profile(models.Model):
94 user = models.OneToOneField(User, on_delete=models.CASCADE)
95 user = models.OneToOneField(User, on_delete=models.CASCADE)
95 theme = models.CharField(max_length=30, default='spacelab')
96 theme = models.CharField(max_length=30, default='spacelab')
96
97
97
98
98 @receiver(post_save, sender=User)
99 @receiver(post_save, sender=User)
99 def create_user_profile(sender, instance, created, **kwargs):
100 def create_user_profile(sender, instance, created, **kwargs):
100 if created:
101 if created:
101 Profile.objects.create(user=instance)
102 Profile.objects.create(user=instance)
102
103
103 @receiver(post_save, sender=User)
104 @receiver(post_save, sender=User)
104 def save_user_profile(sender, instance, **kwargs):
105 def save_user_profile(sender, instance, **kwargs):
105 instance.profile.save()
106 instance.profile.save()
106
107
107
108
108 class Location(models.Model):
109 class Location(models.Model):
109
110
110 name = models.CharField(max_length = 30)
111 name = models.CharField(max_length = 30)
111 description = models.TextField(blank=True, null=True)
112 description = models.TextField(blank=True, null=True)
112
113
113 class Meta:
114 class Meta:
114 db_table = 'db_location'
115 db_table = 'db_location'
115
116
116 def __str__(self):
117 def __str__(self):
117 return u'%s' % self.name
118 return u'%s' % self.name
118
119
119 def get_absolute_url(self):
120 def get_absolute_url(self):
120 return reverse('url_location', args=[str(self.id)])
121 return reverse('url_location', args=[str(self.id)])
121
122
122
123
123 class DeviceType(models.Model):
124 class DeviceType(models.Model):
124
125
125 name = models.CharField(max_length = 10, choices = DEV_TYPES, default = 'dds_rest')
126 name = models.CharField(max_length = 10, choices = DEV_TYPES, default = 'dds_rest')
126 sequence = models.PositiveSmallIntegerField(default=55)
127 sequence = models.PositiveSmallIntegerField(default=55)
127 description = models.TextField(blank=True, null=True)
128 description = models.TextField(blank=True, null=True)
128
129
129 class Meta:
130 class Meta:
130 db_table = 'db_device_types'
131 db_table = 'db_device_types'
131
132
132 def __str__(self):
133 def __str__(self):
133 return u'%s' % self.get_name_display()
134 return u'%s' % self.get_name_display()
134
135
135 class Device(models.Model):
136 class Device(models.Model):
136
137
137 device_type = models.ForeignKey('DeviceType', on_delete=models.CASCADE)
138 device_type = models.ForeignKey('DeviceType', on_delete=models.CASCADE)
138 location = models.ForeignKey('Location', on_delete=models.CASCADE)
139 location = models.ForeignKey('Location', on_delete=models.CASCADE)
139 ip_address = models.GenericIPAddressField(protocol='IPv4', default='0.0.0.0')
140 ip_address = models.GenericIPAddressField(protocol='IPv4', default='0.0.0.0')
140 port_address = models.PositiveSmallIntegerField(default=2000)
141 port_address = models.PositiveSmallIntegerField(default=2000)
141 description = models.TextField(blank=True, null=True)
142 description = models.TextField(blank=True, null=True)
142 status = models.PositiveSmallIntegerField(default=4, choices=DEV_STATES)
143 status = models.PositiveSmallIntegerField(default=4, choices=DEV_STATES)
143 conf_active = models.PositiveIntegerField(default=0, verbose_name='Current configuration')
144 conf_active = models.PositiveIntegerField(default=0, verbose_name='Current configuration')
144
145
145 class Meta:
146 class Meta:
146 db_table = 'db_devices'
147 db_table = 'db_devices'
147
148
148 def __str__(self):
149 def __str__(self):
149 ret = u'{} [{}]'.format(self.device_type.name.upper(), self.location.name)
150 ret = u'{} [{}]'.format(self.device_type.name.upper(), self.location.name)
150
151
151 return ret
152 return ret
152
153
153 @property
154 @property
154 def name(self):
155 def name(self):
155 return str(self)
156 return str(self)
156
157
157 def get_status(self):
158 def get_status(self):
158 return self.status
159 return self.status
159
160
160 @property
161 @property
161 def status_color(self):
162 def status_color(self):
162 color = 'muted'
163 color = 'muted'
163 if self.status == 0:
164 if self.status == 0:
164 color = "danger"
165 color = "danger"
165 elif self.status == 1:
166 elif self.status == 1:
166 color = "warning"
167 color = "warning"
167 elif self.status == 2:
168 elif self.status == 2:
168 color = "info"
169 color = "info"
169 elif self.status == 3:
170 elif self.status == 3:
170 color = "success"
171 color = "success"
171
172
172 return color
173 return color
173
174
174 def url(self, path=None):
175 def url(self, path=None):
175
176
176 if path:
177 if path:
177 return 'http://{}:{}/{}/'.format(self.ip_address, self.port_address, path)
178 return 'http://{}:{}/{}/'.format(self.ip_address, self.port_address, path)
178 else:
179 else:
179 return 'http://{}:{}/'.format(self.ip_address, self.port_address)
180 return 'http://{}:{}/'.format(self.ip_address, self.port_address)
180
181
181 def get_absolute_url(self):
182 def get_absolute_url(self):
182 return reverse('url_device', args=[str(self.id)])
183 return reverse('url_device', args=[str(self.id)])
183
184
184 def get_absolute_url_edit(self):
185 def get_absolute_url_edit(self):
185 return reverse('url_edit_device', args=[str(self.id)])
186 return reverse('url_edit_device', args=[str(self.id)])
186
187
187 def get_absolute_url_delete(self):
188 def get_absolute_url_delete(self):
188 return reverse('url_delete_device', args=[str(self.id)])
189 return reverse('url_delete_device', args=[str(self.id)])
189
190
190 def change_ip(self, ip_address, mask, gateway, dns, **kwargs):
191 def change_ip(self, ip_address, mask, gateway, dns, **kwargs):
191
192
192 if self.device_type.name=='dds':
193 if self.device_type.name=='dds':
193 try:
194 try:
194 answer = dds_api.change_ip(ip = self.ip_address,
195 answer = dds_api.change_ip(ip = self.ip_address,
195 port = self.port_address,
196 port = self.port_address,
196 new_ip = ip_address,
197 new_ip = ip_address,
197 mask = mask,
198 mask = mask,
198 gateway = gateway)
199 gateway = gateway)
199 if answer[0]=='1':
200 if answer[0]=='1':
200 self.message = '25|DDS - {}'.format(answer)
201 self.message = '25|DDS - {}'.format(answer)
201 self.ip_address = ip_address
202 self.ip_address = ip_address
202 self.save()
203 self.save()
203 else:
204 else:
204 self.message = '30|DDS - {}'.format(answer)
205 self.message = '30|DDS - {}'.format(answer)
205 return False
206 return False
206 except Exception as e:
207 except Exception as e:
207 self.message = '40|{}'.format(str(e))
208 self.message = '40|{}'.format(str(e))
208 return False
209 return False
209
210
210 elif self.device_type.name=='rc':
211 elif self.device_type.name=='rc':
211 headers = {'content-type': "application/json",
212 headers = {'content-type': "application/json",
212 'cache-control': "no-cache"}
213 'cache-control': "no-cache"}
213
214
214 ip = [int(x) for x in ip_address.split('.')]
215 ip = [int(x) for x in ip_address.split('.')]
215 dns = [int(x) for x in dns.split('.')]
216 dns = [int(x) for x in dns.split('.')]
216 gateway = [int(x) for x in gateway.split('.')]
217 gateway = [int(x) for x in gateway.split('.')]
217 subnet = [int(x) for x in mask.split('.')]
218 subnet = [int(x) for x in mask.split('.')]
218
219
219 payload = {
220 payload = {
220 "ip": ip,
221 "ip": ip,
221 "dns": dns,
222 "dns": dns,
222 "gateway": gateway,
223 "gateway": gateway,
223 "subnet": subnet
224 "subnet": subnet
224 }
225 }
225
226
226 req = requests.post(self.url('changeip'), data=json.dumps(payload), headers=headers)
227 req = requests.post(self.url('changeip'), data=json.dumps(payload), headers=headers)
227 try:
228 try:
228 answer = req.json()
229 answer = req.json()
229 if answer['changeip']=='ok':
230 if answer['changeip']=='ok':
230 self.message = '25|IP succesfully changed'
231 self.message = '25|IP succesfully changed'
231 self.ip_address = ip_address
232 self.ip_address = ip_address
232 self.save()
233 self.save()
233 else:
234 else:
234 self.message = '30|An error ocuur when changing IP'
235 self.message = '30|An error ocuur when changing IP'
235 except Exception as e:
236 except Exception as e:
236 self.message = '40|{}'.format(str(e))
237 self.message = '40|{}'.format(str(e))
237 else:
238 else:
238 self.message = 'Not implemented'
239 self.message = 'Not implemented'
239 return False
240 return False
240
241
241 return True
242 return True
242
243
243
244
244 class Campaign(models.Model):
245 class Campaign(models.Model):
245
246
246 template = models.BooleanField(default=False)
247 template = models.BooleanField(default=False)
247 name = models.CharField(max_length=60, unique=True)
248 name = models.CharField(max_length=60, unique=True)
248 start_date = models.DateTimeField(blank=True, null=True)
249 start_date = models.DateTimeField(blank=True, null=True)
249 end_date = models.DateTimeField(blank=True, null=True)
250 end_date = models.DateTimeField(blank=True, null=True)
250 tags = models.CharField(max_length=40, blank=True, null=True)
251 tags = models.CharField(max_length=40, blank=True, null=True)
251 description = models.TextField(blank=True, null=True)
252 description = models.TextField(blank=True, null=True)
252 experiments = models.ManyToManyField('Experiment', blank=True)
253 experiments = models.ManyToManyField('Experiment', blank=True)
253 author = models.ForeignKey(User, null=True, blank=True,on_delete=models.CASCADE)
254 author = models.ForeignKey(User, null=True, blank=True,on_delete=models.CASCADE)
254
255
255 class Meta:
256 class Meta:
256 db_table = 'db_campaigns'
257 db_table = 'db_campaigns'
257 ordering = ('name',)
258 ordering = ('name',)
258
259
259 def __str__(self):
260 def __str__(self):
260 if self.template:
261 if self.template:
261 return u'{} (template)'.format(self.name)
262 return u'{} (template)'.format(self.name)
262 else:
263 else:
263 return u'{}'.format(self.name)
264 return u'{}'.format(self.name)
264
265
265 def jsonify(self):
266 def jsonify(self):
266
267
267 data = {}
268 data = {}
268
269
269 ignored = ('template')
270 ignored = ('template')
270
271
271 for field in self._meta.fields:
272 for field in self._meta.fields:
272 if field.name in ignored:
273 if field.name in ignored:
273 continue
274 continue
274 data[field.name] = field.value_from_object(self)
275 data[field.name] = field.value_from_object(self)
275
276
276 data['start_date'] = data['start_date'].strftime('%Y-%m-%d')
277 data['start_date'] = data['start_date'].strftime('%Y-%m-%d')
277 data['end_date'] = data['end_date'].strftime('%Y-%m-%d')
278 data['end_date'] = data['end_date'].strftime('%Y-%m-%d')
278
279
279 return data
280 return data
280
281
281 def parms_to_dict(self):
282 def parms_to_dict(self):
282
283
283 params = Params({})
284 params = Params({})
284 params.add(self.jsonify(), 'campaigns')
285 params.add(self.jsonify(), 'campaigns')
285
286
286 for exp in Experiment.objects.filter(campaign = self):
287 for exp in Experiment.objects.filter(campaign = self):
287 params.add(exp.jsonify(), 'experiments')
288 params.add(exp.jsonify(), 'experiments')
288 configurations = Configuration.objects.filter(experiment=exp, type=0)
289 configurations = Configuration.objects.filter(experiment=exp, type=0)
289
290
290 for conf in configurations:
291 for conf in configurations:
291 params.add(conf.jsonify(), 'configurations')
292 params.add(conf.jsonify(), 'configurations')
292 if conf.device.device_type.name=='rc':
293 if conf.device.device_type.name=='rc':
293 for line in conf.get_lines():
294 for line in conf.get_lines():
294 params.add(line.jsonify(), 'lines')
295 params.add(line.jsonify(), 'lines')
295
296
296 return params.data
297 return params.data
297
298
298 def dict_to_parms(self, parms, CONF_MODELS):
299 def dict_to_parms(self, parms, CONF_MODELS):
299
300
300 experiments = Experiment.objects.filter(campaign = self)
301 experiments = Experiment.objects.filter(campaign = self)
301
302
302 if experiments:
303 if experiments:
303 for experiment in experiments:
304 for experiment in experiments:
304 experiment.delete()
305 experiment.delete()
305
306
306 for id_exp in parms['experiments']['allIds']:
307 for id_exp in parms['experiments']['allIds']:
307 exp_parms = parms['experiments']['byId'][id_exp]
308 exp_parms = parms['experiments']['byId'][id_exp]
308 dum = (datetime.now() - datetime(1970, 1, 1)).total_seconds()
309 dum = (datetime.now() - datetime(1970, 1, 1)).total_seconds()
309 exp = Experiment(name='{}'.format(dum))
310 exp = Experiment(name='{}'.format(dum))
310 exp.save()
311 exp.save()
311 exp.dict_to_parms(parms, CONF_MODELS, id_exp=id_exp)
312 exp.dict_to_parms(parms, CONF_MODELS, id_exp=id_exp)
312 self.experiments.add(exp)
313 self.experiments.add(exp)
313
314
314 camp_parms = parms['campaigns']['byId'][parms['campaigns']['allIds'][0]]
315 camp_parms = parms['campaigns']['byId'][parms['campaigns']['allIds'][0]]
315
316
316 self.name = '{}-{}'.format(camp_parms['name'], datetime.now().strftime('%y%m%d'))
317 self.name = '{}-{}'.format(camp_parms['name'], datetime.now().strftime('%y%m%d'))
317 self.start_date = camp_parms['start_date']
318 self.start_date = camp_parms['start_date']
318 self.end_date = camp_parms['end_date']
319 self.end_date = camp_parms['end_date']
319 self.tags = camp_parms['tags']
320 self.tags = camp_parms['tags']
320 self.save()
321 self.save()
321
322
322 return self
323 return self
323
324
324 def get_experiments_by_radar(self, radar=None):
325 def get_experiments_by_radar(self, radar=None):
325
326
326 ret = []
327 ret = []
327 if radar:
328 if radar:
328 locations = Location.objects.filter(pk=radar)
329 locations = Location.objects.filter(pk=radar)
329 else:
330 else:
330 locations = set([e.location for e in self.experiments.all()])
331 locations = set([e.location for e in self.experiments.all()])
331
332
332 for loc in locations:
333 for loc in locations:
333 dum = {}
334 dum = {}
334 dum['name'] = loc.name
335 dum['name'] = loc.name
335 dum['id'] = loc.pk
336 dum['id'] = loc.pk
336 dum['experiments'] = [e for e in self.experiments.all() if e.location==loc]
337 dum['experiments'] = [e for e in self.experiments.all() if e.location==loc]
337 ret.append(dum)
338 ret.append(dum)
338 return ret
339 return ret
339
340
340 def get_absolute_url(self):
341 def get_absolute_url(self):
341 return reverse('url_campaign', args=[str(self.id)])
342 return reverse('url_campaign', args=[str(self.id)])
342
343
343 def get_absolute_url_edit(self):
344 def get_absolute_url_edit(self):
344 return reverse('url_edit_campaign', args=[str(self.id)])
345 return reverse('url_edit_campaign', args=[str(self.id)])
345
346
346 def get_absolute_url_delete(self):
347 def get_absolute_url_delete(self):
347 return reverse('url_delete_campaign', args=[str(self.id)])
348 return reverse('url_delete_campaign', args=[str(self.id)])
348
349
349 def get_absolute_url_export(self):
350 def get_absolute_url_export(self):
350 return reverse('url_export_campaign', args=[str(self.id)])
351 return reverse('url_export_campaign', args=[str(self.id)])
351
352
352 def get_absolute_url_import(self):
353 def get_absolute_url_import(self):
353 return reverse('url_import_campaign', args=[str(self.id)])
354 return reverse('url_import_campaign', args=[str(self.id)])
354
355
355
356
356 class RunningExperiment(models.Model):
357 class RunningExperiment(models.Model):
357 radar = models.OneToOneField('Location', on_delete=models.CASCADE)
358 radar = models.OneToOneField('Location', on_delete=models.CASCADE)
358 running_experiment = models.ManyToManyField('Experiment', blank = True)
359 running_experiment = models.ManyToManyField('Experiment', blank = True)
359 status = models.PositiveSmallIntegerField(default=0, choices=RADAR_STATES)
360 status = models.PositiveSmallIntegerField(default=0, choices=RADAR_STATES)
360
361
361
362
362 class Experiment(models.Model):
363 class Experiment(models.Model):
363
364
364 template = models.BooleanField(default=False)
365 template = models.BooleanField(default=False)
365 name = models.CharField(max_length=40, default='', unique=True)
366 name = models.CharField(max_length=40, default='', unique=True)
366 location = models.ForeignKey('Location', null=True, blank=True, on_delete=models.CASCADE)
367 location = models.ForeignKey('Location', null=True, blank=True, on_delete=models.CASCADE)
367 freq = models.FloatField(verbose_name='Operating Freq. (MHz)', validators=[MinValueValidator(1), MaxValueValidator(10000)], default=49.9200)
368 freq = models.FloatField(verbose_name='Operating Freq. (MHz)', validators=[MinValueValidator(1), MaxValueValidator(10000)], default=49.9200)
368 start_time = models.TimeField(default='00:00:00')
369 start_time = models.TimeField(default='00:00:00')
369 end_time = models.TimeField(default='23:59:59')
370 end_time = models.TimeField(default='23:59:59')
370 task = models.CharField(max_length=36, default='', blank=True, null=True)
371 task = models.CharField(max_length=36, default='', blank=True, null=True)
371 status = models.PositiveSmallIntegerField(default=4, choices=EXP_STATES)
372 status = models.PositiveSmallIntegerField(default=4, choices=EXP_STATES)
372 author = models.ForeignKey(User, null=True, blank=True,on_delete=models.CASCADE)
373 author = models.ForeignKey(User, null=True, blank=True,on_delete=models.CASCADE)
373 hash = models.CharField(default='', max_length=64, null=True, blank=True)
374 hash = models.CharField(default='', max_length=64, null=True, blank=True)
374
375
375 class Meta:
376 class Meta:
376 db_table = 'db_experiments'
377 db_table = 'db_experiments'
377 ordering = ('template', 'name')
378 ordering = ('template', 'name')
378
379
379 def __str__(self):
380 def __str__(self):
380 if self.template:
381 if self.template:
381 return u'%s (template)' % (self.name)
382 return u'%s (template)' % (self.name)
382 else:
383 else:
383 return u'%s' % (self.name)
384 return u'%s' % (self.name)
384
385
385 def jsonify(self):
386 def jsonify(self):
386
387
387 data = {}
388 data = {}
388
389
389 ignored = ('template')
390 ignored = ('template')
390
391
391 for field in self._meta.fields:
392 for field in self._meta.fields:
392 if field.name in ignored:
393 if field.name in ignored:
393 continue
394 continue
394 data[field.name] = field.value_from_object(self)
395 data[field.name] = field.value_from_object(self)
395
396
396 data['start_time'] = data['start_time'].strftime('%H:%M:%S')
397 data['start_time'] = data['start_time'].strftime('%H:%M:%S')
397 data['end_time'] = data['end_time'].strftime('%H:%M:%S')
398 data['end_time'] = data['end_time'].strftime('%H:%M:%S')
398 data['location'] = self.location.name
399 data['location'] = self.location.name
399 data['configurations'] = ['{}'.format(conf.pk) for
400 data['configurations'] = ['{}'.format(conf.pk) for
400 conf in Configuration.objects.filter(experiment=self, type=0)]
401 conf in Configuration.objects.filter(experiment=self, type=0)]
401
402
402 return data
403 return data
403
404
404 @property
405 @property
405 def radar_system(self):
406 def radar_system(self):
406 return self.location
407 return self.location
407
408
408 def clone(self, **kwargs):
409 def clone(self, **kwargs):
409
410
410 confs = Configuration.objects.filter(experiment=self, type=0)
411 confs = Configuration.objects.filter(experiment=self, type=0)
411 self.pk = None
412 self.pk = None
412 self.name = '{}_{:%y%m%d%H%M%S}'.format(self.name, datetime.now())
413 self.name = '{}_{:%y%m%d%H%M%S}'.format(self.name, datetime.now())
413 for attr, value in kwargs.items():
414 for attr, value in kwargs.items():
414 setattr(self, attr, value)
415 setattr(self, attr, value)
415
416
416 self.save()
417 self.save()
417
418
418 for conf in confs:
419 for conf in confs:
419 conf.clone(experiment=self, template=False)
420 conf.clone(experiment=self, template=False)
420
421
421 return self
422 return self
422
423
423 def start(self):
424 def start(self):
424 '''
425 '''
425 Configure and start experiments's devices
426 Configure and start experiments's devices
426 ABS-CGS-DDS-RC-JARS
427 ABS-CGS-DDS-RC-JARS
427 '''
428 '''
428 self.status=5 #Busy
429 self.status=5 #Busy
429 self.save()
430 self.save()
430 # print("Guardando STATUS: {}".format(self.status))
431 print("Realizando operaciΓ³n. \nEXPERIMENT STATUS : {}".format(self.status))
431
432
432 confs = []
433 confs = []
433 allconfs = Configuration.objects.filter(experiment=self, type = 0).order_by('-device__device_type__sequence')
434 allconfs = Configuration.objects.filter(experiment=self, type = 0).order_by('-device__device_type__sequence')
434 rc_mix = [conf for conf in allconfs if conf.device.device_type.name=='rc' and conf.mix]
435 rc_mix = [conf for conf in allconfs if conf.device.device_type.name=='rc' and conf.mix]
435 if rc_mix:
436 if rc_mix:
436 for conf in allconfs:
437 for conf in allconfs:
437 if conf.device.device_type.name == 'rc' and not conf.mix:
438 if conf.device.device_type.name == 'rc' and not conf.mix:
438 continue
439 continue
439 confs.append(conf)
440 confs.append(conf)
440 else:
441 else:
441 confs = allconfs
442 confs = allconfs
442
443
443
444
444 for conf in confs:
445 for conf in confs:
445 print("conf->",conf)
446 print(conf.device)
447 print(conf.device.status)
448 print("--------------",flush=True)
446 print("--------------",flush=True)
447 print("STATUS: {}".format(conf.device.status))
449 print("Stop ",conf.name,flush=True)
448 print("Stop ",conf.name,flush=True)
450 if conf.stop_device() ==False:
449 if conf.stop_device() ==False:
451 print("FallΓ³ Stop ",conf.name)
450 print("FallΓ³ Stop ",conf.name)
452 print("Cancelando CampaΓ±a...",flush=True)
451 print("Cancelando CampaΓ±a...",flush=True)
453 return 0
452 return 0
454 print("Write ",conf.name,flush=True)
453 print("Write ",conf.name,flush=True)
455 if conf.write_device() ==False:
454 if conf.write_device() ==False:
456 print("FallΓ³ Write ",conf.name)
455 print("FallΓ³ Write ",conf.name)
457 print("Cancelando CampaΓ±a...",flush=True)
456 print("Cancelando CampaΓ±a...",flush=True)
458 return 0
457 return 0
459 print("Save",conf.name,flush=True)
458 print("Save",conf.name,flush=True)
460 conf.device.conf_active = conf.pk
459 conf.device.conf_active = conf.pk
461 conf.device.save()
460 conf.device.save()
462 print("Start",conf.name,flush=True)
461 print("Start",conf.name,flush=True)
463 if conf.start_device()==False:
462 if conf.start_device()==False:
464 print("FallΓ³ Start ",conf.name)
463 print("FallΓ³ Start ",conf.name)
465 print("Cancelando CampaΓ±a...",flush=True)
464 print("Cancelando CampaΓ±a...",flush=True)
466 return 0
465 return 0
467 print("--- CONFIGURACIΓ“N EXITOSA ---",flush=True)
466 print("--- CONFIGURACIΓ“N EXITOSA ---",flush=True)
468 time.sleep(1)
467 time.sleep(1)
469
468
470 return 2
469 return 2
471
470
472
471
473 def stop(self):
472 def stop(self):
474 '''
473 '''
475 Stop experiments's devices
474 Stop experiments's devices
476 DDS-JARS-RC-CGS-ABS
475 DDS-JARS-RC-CGS-ABS
477 '''
476 '''
478
477
479 confs = Configuration.objects.filter(experiment=self, type = 0).order_by('device__device_type__sequence')
478 confs = Configuration.objects.filter(experiment=self, type = 0).order_by('device__device_type__sequence')
480 confs = confs.exclude(device__device_type__name='cgs')
479 confs = confs.exclude(device__device_type__name='cgs')
481 try:
480 try:
482 for conf in confs:
481 for conf in confs:
483 conf.stop_device()
482 conf.stop_device()
484 except:
483 except:
485 return 0
484 return 0
486 return 1
485 return 1
487
486
488 def get_status(self):
487 def get_status(self):
489
488
490 if self.status == 3:
489 if self.status == 3:
491 return
490 return
492
491
493 confs = Configuration.objects.filter(experiment=self, type=0)
492 confs = Configuration.objects.filter(experiment=self, type=0)
494
493
495 for conf in confs:
494 for conf in confs:
496 conf.status_device()
495 conf.status_device()
497
496
498 total = confs.aggregate(models.Sum('device__status'))['device__status__sum']
497 total = confs.aggregate(models.Sum('device__status'))['device__status__sum']
499
498
500 if total==2*confs.count():
499 if total==2*confs.count():
501 status = 1
500 status = 1
502 elif total == 3*confs.count():
501 elif total == 3*confs.count():
503 status = 2
502 status = 2
504 else:
503 else:
505 status = 0
504 status = 0
506
505
507 self.status = status
506 self.status = status
508 self.save()
507 self.save()
509
508
510 def status_color(self):
509 def status_color(self):
511 color = 'muted'
510 color = 'muted'
512 if self.status == 0:
511 if self.status == 0:
513 color = "danger"
512 color = "danger"
514 elif self.status == 1:
513 elif self.status == 1:
515 color = "warning"
514 color = "warning"
516 elif self.status == 2:
515 elif self.status == 2:
517 color = "success"
516 color = "success"
518 elif self.status == 3:
517 elif self.status == 3:
519 color = "info"
518 color = "info"
520
519
521 return color
520 return color
522
521
523 def parms_to_dict(self):
522 def parms_to_dict(self):
524
523
525 params = Params({})
524 params = Params({})
526 params.add(self.jsonify(), 'experiments')
525 params.add(self.jsonify(), 'experiments')
527
526
528 configurations = Configuration.objects.filter(experiment=self, type=0)
527 configurations = Configuration.objects.filter(experiment=self, type=0)
529
528
530 for conf in configurations:
529 for conf in configurations:
531 params.add(conf.jsonify(), 'configurations')
530 params.add(conf.jsonify(), 'configurations')
532 if conf.device.device_type.name=='rc':
531 if conf.device.device_type.name=='rc':
533 for line in conf.get_lines():
532 for line in conf.get_lines():
534 params.add(line.jsonify(), 'lines')
533 params.add(line.jsonify(), 'lines')
535
534
536 return params.data
535 return params.data
537
536
538 def dict_to_parms(self, parms, CONF_MODELS, id_exp=None):
537 def dict_to_parms(self, parms, CONF_MODELS, id_exp=None):
539
538
540 configurations = Configuration.objects.filter(experiment=self)
539 configurations = Configuration.objects.filter(experiment=self)
541
540
542 if id_exp is not None:
541 if id_exp is not None:
543 exp_parms = parms['experiments']['byId'][id_exp]
542 exp_parms = parms['experiments']['byId'][id_exp]
544 else:
543 else:
545 exp_parms = parms['experiments']['byId'][parms['experiments']['allIds'][0]]
544 exp_parms = parms['experiments']['byId'][parms['experiments']['allIds'][0]]
546
545
547 if configurations:
546 if configurations:
548 for configuration in configurations:
547 for configuration in configurations:
549 configuration.delete()
548 configuration.delete()
550
549
551 for id_conf in exp_parms['configurations']:
550 for id_conf in exp_parms['configurations']:
552 conf_parms = parms['configurations']['byId'][id_conf]
551 conf_parms = parms['configurations']['byId'][id_conf]
553 device = Device.objects.filter(device_type__name=conf_parms['device_type'])[0]
552 device = Device.objects.filter(device_type__name=conf_parms['device_type'])[0]
554 model = CONF_MODELS[conf_parms['device_type']]
553 model = CONF_MODELS[conf_parms['device_type']]
555 conf = model(
554 conf = model(
556 experiment = self,
555 experiment = self,
557 device = device,
556 device = device,
558 )
557 )
559 conf.dict_to_parms(parms, id=id_conf)
558 conf.dict_to_parms(parms, id=id_conf)
560
559
561
560
562 location, created = Location.objects.get_or_create(name=exp_parms['location'])
561 location, created = Location.objects.get_or_create(name=exp_parms['location'])
563 self.name = '{}-{}'.format(exp_parms['name'], datetime.now().strftime('%y%m%d'))
562 self.name = '{}-{}'.format(exp_parms['name'], datetime.now().strftime('%y%m%d'))
564 self.location = location
563 self.location = location
565 self.start_time = exp_parms['start_time']
564 self.start_time = exp_parms['start_time']
566 self.end_time = exp_parms['end_time']
565 self.end_time = exp_parms['end_time']
567 self.save()
566 self.save()
568
567
569 return self
568 return self
570
569
571 def get_absolute_url(self):
570 def get_absolute_url(self):
572 return reverse('url_experiment', args=[str(self.id)])
571 return reverse('url_experiment', args=[str(self.id)])
573
572
574 def get_absolute_url_edit(self):
573 def get_absolute_url_edit(self):
575 return reverse('url_edit_experiment', args=[str(self.id)])
574 return reverse('url_edit_experiment', args=[str(self.id)])
576
575
577 def get_absolute_url_delete(self):
576 def get_absolute_url_delete(self):
578 return reverse('url_delete_experiment', args=[str(self.id)])
577 return reverse('url_delete_experiment', args=[str(self.id)])
579
578
580 def get_absolute_url_import(self):
579 def get_absolute_url_import(self):
581 return reverse('url_import_experiment', args=[str(self.id)])
580 return reverse('url_import_experiment', args=[str(self.id)])
582
581
583 def get_absolute_url_export(self):
582 def get_absolute_url_export(self):
584 return reverse('url_export_experiment', args=[str(self.id)])
583 return reverse('url_export_experiment', args=[str(self.id)])
585
584
586 def get_absolute_url_start(self):
585 def get_absolute_url_start(self):
587 return reverse('url_start_experiment', args=[str(self.id)])
586 return reverse('url_start_experiment', args=[str(self.id)])
588
587
589 def get_absolute_url_stop(self):
588 def get_absolute_url_stop(self):
590 return reverse('url_stop_experiment', args=[str(self.id)])
589 return reverse('url_stop_experiment', args=[str(self.id)])
591
590
592
591
593 class Configuration(PolymorphicModel):
592 class Configuration(PolymorphicModel):
594
593
595 template = models.BooleanField(default=False)
594 template = models.BooleanField(default=False)
596 # name = models.CharField(verbose_name="Configuration Name", max_length=40, default='')
595 # name = models.CharField(verbose_name="Configuration Name", max_length=40, default='')
597 device = models.ForeignKey('Device', verbose_name='Device', null=True, on_delete=models.CASCADE)
596 device = models.ForeignKey('Device', verbose_name='Device', null=True, on_delete=models.CASCADE)
598 label = models.CharField(verbose_name="Label", max_length=40, default='', blank=True, null=True)
597 label = models.CharField(verbose_name="Label", max_length=40, default='', blank=True, null=True)
599 experiment = models.ForeignKey('Experiment', verbose_name='Experiment', null=True, blank=True, on_delete=models.CASCADE)
598 experiment = models.ForeignKey('Experiment', verbose_name='Experiment', null=True, blank=True, on_delete=models.CASCADE)
600 type = models.PositiveSmallIntegerField(default=0, choices=CONF_TYPES)
599 type = models.PositiveSmallIntegerField(default=0, choices=CONF_TYPES)
601 created_date = models.DateTimeField(auto_now_add=True)
600 created_date = models.DateTimeField(auto_now_add=True)
602 programmed_date = models.DateTimeField(auto_now=True)
601 programmed_date = models.DateTimeField(auto_now=True)
603 parameters = models.TextField(default='{}')
602 parameters = models.TextField(default='{}')
604 author = models.ForeignKey(User, null=True, blank=True,on_delete=models.CASCADE)
603 author = models.ForeignKey(User, null=True, blank=True,on_delete=models.CASCADE)
605 hash = models.CharField(default='', max_length=64, null=True, blank=True)
604 hash = models.CharField(default='', max_length=64, null=True, blank=True)
606 message = ""
605 message = ""
607
606
608 class Meta:
607 class Meta:
609 db_table = 'db_configurations'
608 db_table = 'db_configurations'
610 ordering = ('device__device_type__name',)
609 ordering = ('device__device_type__name',)
611
610
612 def __str__(self):
611 def __str__(self):
613
612
614 ret = u'{} '.format(self.device.device_type.name.upper())
613 ret = u'{} '.format(self.device.device_type.name.upper())
615
614
616 if 'mix' in [f.name for f in self._meta.get_fields()]:
615 if 'mix' in [f.name for f in self._meta.get_fields()]:
617 if self.mix:
616 if self.mix:
618 ret = '{} MIX '.format(self.device.device_type.name.upper())
617 ret = '{} MIX '.format(self.device.device_type.name.upper())
619
618
620 if 'label' in [f.name for f in self._meta.get_fields()]:
619 if 'label' in [f.name for f in self._meta.get_fields()]:
621 ret += '{}'.format(self.label)
620 ret += '{}'.format(self.label)
622
621
623 if self.template:
622 if self.template:
624 ret += ' (template)'
623 ret += ' (template)'
625
624
626 return ret
625 return ret
627
626
628 @property
627 @property
629 def name(self):
628 def name(self):
630
629
631 return str(self)
630 return str(self)
632
631
633 def jsonify(self):
632 def jsonify(self):
634
633
635 data = {}
634 data = {}
636
635
637 ignored = ('type', 'polymorphic_ctype', 'configuration_ptr',
636 ignored = ('type', 'polymorphic_ctype', 'configuration_ptr',
638 'created_date', 'programmed_date', 'template', 'device',
637 'created_date', 'programmed_date', 'template', 'device',
639 'experiment')
638 'experiment')
640
639
641 for field in self._meta.fields:
640 for field in self._meta.fields:
642 if field.name in ignored:
641 if field.name in ignored:
643 continue
642 continue
644 data[field.name] = field.value_from_object(self)
643 data[field.name] = field.value_from_object(self)
645
644
646 data['device_type'] = self.device.device_type.name
645 data['device_type'] = self.device.device_type.name
647
646
648 if self.device.device_type.name == 'rc':
647 if self.device.device_type.name == 'rc':
649 data['lines'] = ['{}'.format(line.pk) for line in self.get_lines()]
648 data['lines'] = ['{}'.format(line.pk) for line in self.get_lines()]
650 data['delays'] = self.get_delays()
649 data['delays'] = self.get_delays()
651 data['pulses'] = self.get_pulses()
650 data['pulses'] = self.get_pulses()
652
651
653 elif self.device.device_type.name == 'jars':
652 elif self.device.device_type.name == 'jars':
654 data['decode_type'] = DECODE_TYPE[self.decode_data][1]
653 data['decode_type'] = DECODE_TYPE[self.decode_data][1]
655
654
656 elif self.device.device_type.name == 'dds':
655 elif self.device.device_type.name == 'dds':
657 data['frequencyA_Mhz'] = float(data['frequencyA_Mhz'])
656 data['frequencyA_Mhz'] = float(data['frequencyA_Mhz'])
658 data['frequencyB_Mhz'] = float(data['frequencyB_Mhz'])
657 data['frequencyB_Mhz'] = float(data['frequencyB_Mhz'])
659 data['phaseA'] = dds_data.phase_to_binary(data['phaseA_degrees'])
658 data['phaseA'] = dds_data.phase_to_binary(data['phaseA_degrees'])
660 data['phaseB'] = dds_data.phase_to_binary(data['phaseB_degrees'])
659 data['phaseB'] = dds_data.phase_to_binary(data['phaseB_degrees'])
661
660
662 elif self.device.device_type.name == 'dds_rest':
661 elif self.device.device_type.name == 'dds_rest':
663 data['frequencyA_Mhz'] = float(data['frequencyA_Mhz'])
662 data['frequencyA_Mhz'] = float(data['frequencyA_Mhz'])
664 data['frequencyB_Mhz'] = float(data['frequencyB_Mhz'])
663 data['frequencyB_Mhz'] = float(data['frequencyB_Mhz'])
665 data['phaseA'] = dds_data.phase_to_binary(data['phaseA_degrees'])
664 data['phaseA'] = dds_data.phase_to_binary(data['phaseA_degrees'])
666 data['phaseB'] = dds_data.phase_to_binary(data['phaseB_degrees'])
665 data['phaseB'] = dds_data.phase_to_binary(data['phaseB_degrees'])
667 data['delta_frequency_Mhz'] = float(data['delta_frequency_Mhz'] or 0.00)
666 data['delta_frequency_Mhz'] = float(data['delta_frequency_Mhz'] or 0.00)
668 data['update_clock_Mhz'] = float(data['update_clock_Mhz'] or 0.00)
667 data['update_clock_Mhz'] = float(data['update_clock_Mhz'] or 0.00)
669 data['ramp_rate_clock_Mhz'] = float(data['ramp_rate_clock_Mhz'] or 0.0)
668 data['ramp_rate_clock_Mhz'] = float(data['ramp_rate_clock_Mhz'] or 0.0)
670 return data
669 return data
671
670
672 def clone(self, **kwargs):
671 def clone(self, **kwargs):
673
672
674 self.pk = None
673 self.pk = None
675 self.id = None
674 self.id = None
676 for attr, value in kwargs.items():
675 for attr, value in kwargs.items():
677 setattr(self, attr, value)
676 setattr(self, attr, value)
678
677
679 self.save()
678 self.save()
680
679
681 return self
680 return self
682
681
683 def parms_to_dict(self):
682 def parms_to_dict(self):
684
683
685 params = Params({})
684 params = Params({})
686 params.add(self.jsonify(), 'configurations')
685 params.add(self.jsonify(), 'configurations')
687
686
688 if self.device.device_type.name=='rc':
687 if self.device.device_type.name=='rc':
689 for line in self.get_lines():
688 for line in self.get_lines():
690 params.add(line.jsonify(), 'lines')
689 params.add(line.jsonify(), 'lines')
691
690
692 return params.data
691 return params.data
693
692
694 def parms_to_text(self):
693 def parms_to_text(self):
695
694
696 raise NotImplementedError("This method should be implemented in %s Configuration model" %str(self.device.device_type.name).upper())
695 raise NotImplementedError("This method should be implemented in %s Configuration model" %str(self.device.device_type.name).upper())
697
696
698
697
699 def parms_to_binary(self):
698 def parms_to_binary(self):
700
699
701 raise NotImplementedError("This method should be implemented in %s Configuration model" %str(self.device.device_type.name).upper())
700 raise NotImplementedError("This method should be implemented in %s Configuration model" %str(self.device.device_type.name).upper())
702
701
703
702
704 def dict_to_parms(self, parameters, id=None):
703 def dict_to_parms(self, parameters, id=None):
705
704
706 params = Params(parameters)
705 params = Params(parameters)
707
706
708 if id:
707 if id:
709 data = params.get_conf(id_conf=id)
708 data = params.get_conf(id_conf=id)
710 else:
709 else:
711 data = params.get_conf(dtype=self.device.device_type.name)
710 data = params.get_conf(dtype=self.device.device_type.name)
712
711
713 if data['device_type']=='rc':
712 if data['device_type']=='rc':
714 self.clean_lines()
713 self.clean_lines()
715 lines = data.pop('lines', None)
714 lines = data.pop('lines', None)
716 for line_id in lines:
715 for line_id in lines:
717 pass
716 pass
718
717
719 for key, value in data.items():
718 for key, value in data.items():
720 if key not in ('id', 'device_type'):
719 if key not in ('id', 'device_type'):
721 setattr(self, key, value)
720 setattr(self, key, value)
722
721
723 self.save()
722 self.save()
724
723
725
724
726 def export_to_file(self, format="json"):
725 def export_to_file(self, format="json"):
727
726
728 content_type = ''
727 content_type = ''
729
728
730 if format == 'racp':
729 if format == 'racp':
731 content_type = 'text/plain'
730 content_type = 'text/plain'
732 filename = '%s_%s.%s' %(self.device.device_type.name, self.name, 'racp')
731 filename = '%s_%s.%s' %(self.device.device_type.name, self.name, 'racp')
733 content = self.parms_to_text(file_format = 'racp')
732 content = self.parms_to_text(file_format = 'racp')
734
733
735 if format == 'text':
734 if format == 'text':
736 content_type = 'text/plain'
735 content_type = 'text/plain'
737 filename = '%s_%s.%s' %(self.device.device_type.name, self.name, self.device.device_type.name)
736 filename = '%s_%s.%s' %(self.device.device_type.name, self.name, self.device.device_type.name)
738 content = self.parms_to_text()
737 content = self.parms_to_text()
739
738
740 if format == 'binary':
739 if format == 'binary':
741 content_type = 'application/octet-stream'
740 content_type = 'application/octet-stream'
742 filename = '%s_%s.bin' %(self.device.device_type.name, self.name)
741 filename = '%s_%s.bin' %(self.device.device_type.name, self.name)
743 content = self.parms_to_binary()
742 content = self.parms_to_binary()
744
743
745 if not content_type:
744 if not content_type:
746 content_type = 'application/json'
745 content_type = 'application/json'
747 filename = '%s_%s.json' %(self.device.device_type.name, self.name)
746 filename = '%s_%s.json' %(self.device.device_type.name, self.name)
748 content = json.dumps(self.parms_to_dict(), indent=2)
747 content = json.dumps(self.parms_to_dict(), indent=2)
749
748
750 fields = {'content_type':content_type,
749 fields = {'content_type':content_type,
751 'filename':filename,
750 'filename':filename,
752 'content':content
751 'content':content
753 }
752 }
754
753
755 return fields
754 return fields
756
755
757 def import_from_file(self, fp):
756 def import_from_file(self, fp):
758
757
759 parms = {}
758 parms = {}
760
759
761 path, ext = os.path.splitext(fp.name)
760 path, ext = os.path.splitext(fp.name)
762
761
763 if ext == '.json':
762 if ext == '.json':
764 parms = json.load(fp)
763 parms = json.load(fp)
765
764
766 if ext == '.dds':
765 if ext == '.dds':
767 lines = fp.readlines()
766 lines = fp.readlines()
768 parms = dds_data.text_to_dict(lines)
767 parms = dds_data.text_to_dict(lines)
769
768
770 if ext == '.racp':
769 if ext == '.racp':
771 if self.device.device_type.name == 'jars':
770 if self.device.device_type.name == 'jars':
772 parms = RacpFile(fp).to_dict()
771 parms = RacpFile(fp).to_dict()
773 parms['filter_parms'] = json.loads(self.filter_parms)
772 parms['filter_parms'] = json.loads(self.filter_parms)
774 return parms
773 return parms
775 parms = RCFile(fp).to_dict()
774 parms = RCFile(fp).to_dict()
776
775
777 return parms
776 return parms
778
777
779 def status_device(self):
778 def status_device(self):
780
779
781 self.message = 'Function not implemented'
780 self.message = 'Function not implemented'
782 return False
781 return False
783
782
784
783
785 def stop_device(self):
784 def stop_device(self):
786
785
787 self.message = 'Function not implemented'
786 self.message = 'Function not implemented'
788 print("BUENAS SEΓ‘ALES??? NO LO CREO2",flush=True)
787 print("BUENAS SEΓ‘ALES??? NO LO CREO2",flush=True)
789 return False
788 return False
790
789
791
790
792 def start_device(self):
791 def start_device(self):
793
792
794 self.message = 'Function not implemented'
793 self.message = 'Function not implemented'
795 print("BUENAS SEΓ‘ALES??? NO LO CREO",flush=True)
794 print("BUENAS SEΓ‘ALES??? NO LO CREO",flush=True)
796 return False
795 return False
797
796
798
797
799 def write_device(self, parms):
798 def write_device(self, parms):
800
799
801 self.message = 'Function not implemented'
800 self.message = 'Function not implemented'
802 print("BUENAS SEΓ‘ALES??? NO LO CREO3",flush=True)
801 print("BUENAS SEΓ‘ALES??? NO LO CREO3",flush=True)
803 return False
802 return False
804
803
805 def write_device_mqtt(self, parms):
804 def write_device_mqtt(self, parms):
806
805
807 self.message = 'Function not implemented'
806 self.message = 'Function not implemented'
808 return False
807 return False
809
808
810 def read_device(self):
809 def read_device(self):
811
810
812 self.message = 'Function not implemented'
811 self.message = 'Function not implemented'
813 return False
812 return False
814
813
815
814
816 def get_absolute_url(self):
815 def get_absolute_url(self):
817 return reverse('url_%s_conf' % self.device.device_type.name, args=[str(self.id)])
816 return reverse('url_%s_conf' % self.device.device_type.name, args=[str(self.id)])
818
817
819 def get_absolute_mqtt_url(self):
818 def get_absolute_mqtt_url(self):
819 print("----------------- {} ----------------------".format(self.device.device_type.name),flush=True)
820 if self.device.device_type.name=='abs':
820 if self.device.device_type.name=='abs':
821 return reverse('url_%s_conf_mqtt' % self.device.device_type.name, args=[str(self.id)])
821 return reverse('url_%s_conf_mqtt' % self.device.device_type.name, args=[str(self.id)])
822 else:
822 else:
823 return reverse('url_%s_conf' % self.device.device_type.name, args=[str(self.id)])
823 return reverse('url_%s_conf' % self.device.device_type.name, args=[str(self.id)])
824
824
825 def get_absolute_url_edit(self):
825 def get_absolute_url_edit(self):
826 return reverse('url_edit_%s_conf' % self.device.device_type.name, args=[str(self.id)])
826 return reverse('url_edit_%s_conf' % self.device.device_type.name, args=[str(self.id)])
827
827
828 def get_absolute_url_delete(self):
828 def get_absolute_url_delete(self):
829 return reverse('url_delete_dev_conf', args=[str(self.id)])
829 return reverse('url_delete_dev_conf', args=[str(self.id)])
830
830
831 def get_absolute_url_import(self):
831 def get_absolute_url_import(self):
832 return reverse('url_import_dev_conf', args=[str(self.id)])
832 return reverse('url_import_dev_conf', args=[str(self.id)])
833
833
834 def get_absolute_url_export(self):
834 def get_absolute_url_export(self):
835 return reverse('url_export_dev_conf', args=[str(self.id)])
835 return reverse('url_export_dev_conf', args=[str(self.id)])
836
836
837 def get_absolute_url_write(self):
837 def get_absolute_url_write(self):
838 return reverse('url_write_dev_conf', args=[str(self.id)])
838 return reverse('url_write_dev_conf', args=[str(self.id)])
839
839
840 def get_absolute_url_write_mqtt(self):
840 def get_absolute_url_write_mqtt(self):
841 return reverse('url_write_mqtt_dev_conf', args=[str(self.id)])
841 return reverse('url_write_mqtt_dev_conf', args=[str(self.id)])
842
842
843 def get_absolute_url_read(self):
843 def get_absolute_url_read(self):
844 return reverse('url_read_dev_conf', args=[str(self.id)])
844 return reverse('url_read_dev_conf', args=[str(self.id)])
845
845
846 def get_absolute_url_start(self):
846 def get_absolute_url_start(self):
847 return reverse('url_start_dev_conf', args=[str(self.id)])
847 return reverse('url_start_dev_conf', args=[str(self.id)])
848
848
849 def get_absolute_url_stop(self):
849 def get_absolute_url_stop(self):
850 return reverse('url_stop_dev_conf', args=[str(self.id)])
850 return reverse('url_stop_dev_conf', args=[str(self.id)])
851
851
852 def get_absolute_url_stop_mqtt(self):
852 def get_absolute_url_stop_mqtt(self):
853 return reverse('url_stop_mqtt_dev_conf', args=[str(self.id)])
853 return reverse('url_stop_mqtt_dev_conf', args=[str(self.id)])
854
854
855 def get_absolute_url_status(self):
855 def get_absolute_url_status(self):
856 return reverse('url_status_dev_conf', args=[str(self.id)])
856 return reverse('url_status_dev_conf', args=[str(self.id)])
@@ -1,99 +1,99
1 {% extends "base.html" %}
1 {% extends "base.html" %}
2 {% load django_bootstrap5 %}
2 {% load django_bootstrap5 %}
3 {% load static %}
3 {% load static %}
4 {% load main_tags %}
4 {% load main_tags %}
5
5
6 {% block extra-head %}
6 {% block extra-head %}
7 <link href="{% static 'css/bootstrap-datetimepicker.min.css' %}" media="screen" rel="stylesheet">
7 <link href="{% static 'css/bootstrap-datetimepicker.min.css' %}" media="screen" rel="stylesheet">
8 {% endblock %}
8 {% endblock %}
9 {% block content-title %}{{title}}{% endblock %}
9 {% block content-title %}{{title}}{% endblock %}
10 {% block content-suptitle %}{{suptitle}}{% endblock %}
10 {% block content-suptitle %}{{suptitle}}{% endblock %}
11
11
12 {% block content %}
12 {% block content %}
13
13
14 {% block content-filter %}
14 {% block content-filter %}
15 {% if form %}
15 {% if form %}
16 <form class="form" method="get">
16 <form class="form" method="get">
17 {% bootstrap_form form layout='horizontal' size='md' %}
17 {% bootstrap_form form layout='horizontal' size='md' %}
18 <div class="pull-right">
18 <div class="pull-right">
19 <br>
19 <br>
20 <button type="button" class="btn btn-primary btn-sm" onclick="window.location.replace('?');"><span class="fas fa-sync-alt" aria-hidden="true"></span></button>
20 <button type="button" class="btn btn-primary btn-sm" onclick="window.location.replace('?');"><span class="fas fa-sync-alt" aria-hidden="true"></span></button>
21 <button type="submit" class="btn btn-primary btn-sm"><span class="fas fa-search" aria-hidden="true"></span></button>
21 <button type="submit" class="btn btn-primary btn-sm"><span class="fas fa-search" aria-hidden="true"></span></button>
22 {% if add_url %}
22 {% if add_url %}
23 <a class="btn btn-sm btn-info" href="{{add_url}}"><span class="fas fa-plus" aria-hidden="true"></span></a>
23 <a class="btn btn-sm btn-info" href="{{add_url}}"><span class="fas fa-plus" aria-hidden="true"></span></a>
24 {% endif %}
24 {% endif %}
25 </div>
25 </div>
26 </form>
26 </form>
27 {% endif %}
27 {% endif %}
28 {% endblock %}
28 {% endblock %}
29 <div style="clear: both;"></div>
29 <div style="clear: both;"></div>
30 <br>
30 <br>
31 <table class="table table-hover">
31 <table class="table table-hover">
32 <tr>
32 <tr>
33 <th>#</th>
33 <th>#</th>
34 {% for key in keys %}
34 {% for key in keys %}
35 {% if key == 'location'%}
35 {% if key == 'location'%}
36 <th>System</th>
36 <th>System</th>
37 {% else %}
37 {% else %}
38 <th>{{ key|title }}</th>
38 <th>{{ key|title }}</th>
39 {% endif %}
39 {% endif %}
40 {% endfor%}
40 {% endfor%}
41 </tr>
41 </tr>
42 {% for object in objects %}
42 {% for object in objects %}
43 <tr class="clickable-row" data-href="{{object.get_absolute_mqtt_url}}">
43 <tr class="clickable-row" data-href="{{object.get_absolute_url}}">
44 <td>{{ forloop.counter|add:offset }}</td>
44 <td>{{ forloop.counter|add:offset }}</td>
45 {% for key in keys %}
45 {% for key in keys %}
46 {% if key == 'actions' %}
46 {% if key == 'actions' %}
47 <td>
47 <td>
48 <a class="btn btn-sm btn-danger" href="{{object.get_absolute_url_delete}}"><span class="fas fa-times" aria-hidden="true"></span></a>
48 <a class="btn btn-sm btn-danger" href="{{object.get_absolute_url_delete}}"><span class="fas fa-times" aria-hidden="true"></span></a>
49 <a class="btn btn-sm btn-primary" href="{{object.get_absolute_url_edit}}"><span class="fa fa-pencil" aria-hidden="true"></span></a>
49 <a class="btn btn-sm btn-primary" href="{{object.get_absolute_url_edit}}"><span class="fa fa-pencil" aria-hidden="true"></span></a>
50 </td>
50 </td>
51 {% else %}
51 {% else %}
52 <td>{{ object|attr:key }}</td>
52 <td>{{ object|attr:key }}</td>
53 {% endif %}
53 {% endif %}
54 {% endfor %}
54 {% endfor %}
55 </tr>
55 </tr>
56 {% endfor %}
56 {% endfor %}
57 </table>
57 </table>
58
58
59 <div class="pagination">
59 <div class="pagination">
60 <span class="step-links">
60 <span class="step-links">
61 {% if objects.has_previous %}
61 {% if objects.has_previous %}
62 <a href="?page={{ objects.previous_page_number }}&{{q}}"><span class="fas fa-chevron-left" aria-hidden="true"></span></a>
62 <a href="?page={{ objects.previous_page_number }}&{{q}}"><span class="fas fa-chevron-left" aria-hidden="true"></span></a>
63 {% endif %}
63 {% endif %}
64 <span class="current">
64 <span class="current">
65 Page {{ objects.number }} of {{ objects.paginator.num_pages }}.
65 Page {{ objects.number }} of {{ objects.paginator.num_pages }}.
66 </span>
66 </span>
67 {% if objects.has_next %}
67 {% if objects.has_next %}
68 <a href="?page={{ objects.next_page_number }}&{{q}}"><span class="fas fa-chevron-right" aria-hidden="true"></span></a>
68 <a href="?page={{ objects.next_page_number }}&{{q}}"><span class="fas fa-chevron-right" aria-hidden="true"></span></a>
69 {% endif %}
69 {% endif %}
70 </span>
70 </span>
71 </div>
71 </div>
72
72
73 {% endblock %}
73 {% endblock %}
74
74
75 {% block extra-js%}
75 {% block extra-js%}
76 <script src="{% static 'js/bootstrap-datetimepicker.min.js' %}"></script>
76 <script src="{% static 'js/bootstrap-datetimepicker.min.js' %}"></script>
77 <script type="text/javascript">
77 <script type="text/javascript">
78
78
79 $('.input-group.date').datetimepicker({
79 $('.input-group.date').datetimepicker({
80 format: "YYYY-MM-DD",
80 format: "YYYY-MM-DD",
81 icons: {
81 icons: {
82 time: 'far fa-clock',
82 time: 'far fa-clock',
83 date: 'far fa-calendar-alt',
83 date: 'far fa-calendar-alt',
84 up: 'fas fa-arrow-up',
84 up: 'fas fa-arrow-up',
85 down: 'fas fa-arrow-down',
85 down: 'fas fa-arrow-down',
86 previous: 'fas fa-chevron-left',
86 previous: 'fas fa-chevron-left',
87 next: 'fas fa-chevron-right',
87 next: 'fas fa-chevron-right',
88 today: 'far fa-calendar-check',
88 today: 'far fa-calendar-check',
89 clear: 'far fa-trash-alt',
89 clear: 'far fa-trash-alt',
90 close: 'fas fa-times'
90 close: 'fas fa-times'
91 }
91 }
92 });
92 });
93
93
94 $(".clickable-row").click(function() {
94 $(".clickable-row").click(function() {
95 document.location = $(this).data("href");
95 document.location = $(this).data("href");
96 });
96 });
97
97
98 </script>
98 </script>
99 {% endblock %}
99 {% endblock %}
@@ -1,104 +1,104
1 {% extends "base.html" %}
1 {% extends "base.html" %}
2 {% load django_bootstrap5 %}
2 {% load django_bootstrap5 %}
3 {% load static %}
3 {% load static %}
4 {% load main_tags %}
4 {% load main_tags %}
5 {% block extra-head %}
5 {% block extra-head %}
6 <link href="{% static 'css/bootstrap-datetimepicker.min.css' %}" media="screen" rel="stylesheet">
6 <link href="{% static 'css/bootstrap-datetimepicker.min.css' %}" media="screen" rel="stylesheet">
7 {% endblock %}
7 {% endblock %}
8 {% block content-title %}{{title}}{% endblock %}
8 {% block content-title %}{{title}}{% endblock %}
9 {% block content-suptitle %}{{suptitle}}{% endblock %}
9 {% block content-suptitle %}{{suptitle}}{% endblock %}
10
10
11 {% block content %}
11 {% block content %}
12
12
13 {% block menu-actions %}
13 {% block menu-actions %}
14 <span class=" dropdown pull-right">
14 <span class=" dropdown pull-right">
15 <a href="#" class="dropdown-toggle" data-toggle="dropdown"><span class="fas fa-bars" aria-hidden="true"></span></a>
15 <a href="#" class="dropdown-toggle" data-toggle="dropdown"><span class="fas fa-bars" aria-hidden="true"></span></a>
16 <ul class="dropdown-menu" role="menu">
16 <ul class="dropdown-menu" role="menu">
17 <li><a href="{% url 'url_edit_campaign' campaign.id %}"><span class="fa fa-pencil" aria-hidden="true"></span> Edit</a></li>
17 <li><a href="{% url 'url_edit_campaign' campaign.id %}"><span class="fa fa-pencil" aria-hidden="true"></span> Edit</a></li>
18 <li><a href="{% url 'url_delete_campaign' campaign.id %}"><span class="fa fa-times" aria-hidden="true"></span> Delete</a></li>
18 <li><a href="{% url 'url_delete_campaign' campaign.id %}"><span class="fa fa-times" aria-hidden="true"></span> Delete</a></li>
19 <li><a href="{{ campaign.get_absolute_url_import }}"><span class="fas fa-cloud-download-alt" aria-hidden="true"></span> Import </a></li>
19 <li><a href="{{ campaign.get_absolute_url_import }}"><span class="fas fa-cloud-download-alt" aria-hidden="true"></span> Import </a></li>
20 <li><a href="{{ campaign.get_absolute_url_export }}"><span class="fas fa-cloud-upload-alt" aria-hidden="true"></span> Export </a></li>
20 <li><a href="{{ campaign.get_absolute_url_export }}"><span class="fas fa-cloud-upload-alt" aria-hidden="true"></span> Export </a></li>
21 {% block extra-menu-actions %}
21 {% block extra-menu-actions %}
22 {% endblock %}
22 {% endblock %}
23 <li><a>----------------</a></li>
23 <li><a>----------------</a></li>
24 <!--<li><a href="{{ dev_conf.get_absolute_url_status }}"><span class="glyphicon glyphicon-refresh" aria-hidden="true"></span> Status</a></li>
24 <!--<li><a href="{{ dev_conf.get_absolute_url_status }}"><span class="glyphicon glyphicon-refresh" aria-hidden="true"></span> Status</a></li>
25 {% if not no_play %}
25 {% if not no_play %}
26 <li><a href="{{ dev_conf.get_absolute_url_start}}"><span class="glyphicon glyphicon-play" aria-hidden="true"></span> Start</a></li>
26 <li><a href="{{ dev_conf.get_absolute_url_start}}"><span class="glyphicon glyphicon-play" aria-hidden="true"></span> Start</a></li>
27 <li><a href="{{ dev_conf.get_absolute_url_stop }}"><span class="glyphicon glyphicon-stop" aria-hidden="true"></span> Stop</a></li>
27 <li><a href="{{ dev_conf.get_absolute_url_stop }}"><span class="glyphicon glyphicon-stop" aria-hidden="true"></span> Stop</a></li>
28 {% endif %}
28 {% endif %}
29 <li><a href="{{ dev_conf.get_absolute_url_write }}"><span class="glyphicon glyphicon-download" aria-hidden="true"></span> Write</a></li>
29 <li><a href="{{ dev_conf.get_absolute_url_write }}"><span class="glyphicon glyphicon-download" aria-hidden="true"></span> Write</a></li>
30 <li><a href="{{ dev_conf.get_absolute_url_read }}"><span class="glyphicon glyphicon-upload" aria-hidden="true"></span> Read</a></li>-->
30 <li><a href="{{ dev_conf.get_absolute_url_read }}"><span class="glyphicon glyphicon-upload" aria-hidden="true"></span> Read</a></li>-->
31 </ul>
31 </ul>
32 </span>
32 </span>
33 {% endblock %}
33 {% endblock %}
34
34
35 <table class="table table-bordered">
35 <table class="table table-bordered">
36 {% for key in campaign_keys %}
36 {% for key in campaign_keys %}
37 <tr><th>{{key|title}}</th><td>{{campaign|attr:key}}</td></tr>
37 <tr><th>{{key|title}}</th><td>{{campaign|attr:key}}</td></tr>
38 {% endfor %}
38 {% endfor %}
39 </table>
39 </table>
40
40
41 <!--<button class="btn btn-primary pull-right" style="margin-left: 10px" id="bt_export">Export</button>-->
41 <!--<button class="btn btn-primary pull-right" style="margin-left: 10px" id="bt_export">Export</button>-->
42 <!--<button class="btn btn-primary pull-right" style="margin-left: 10px" id="bt_edit">Edit</button>-->
42 <!--<button class="btn btn-primary pull-right" style="margin-left: 10px" id="bt_edit">Edit</button>-->
43
43
44 <br></br>
44 <br></br>
45 <br></br>
45 <br></br>
46
46
47 <div class="panel-group" id="accordion" role="tablist" aria-multiselectable="true">
47 <div class="panel-group" id="accordion" role="tablist" aria-multiselectable="true">
48
48
49 <div class="panel panel-default">
49 <div class="panel panel-default">
50 <div class="panel-heading" role="tab" id="headingTwo">
50 <div class="panel-heading" role="tab" id="headingTwo">
51 <h4 class="panel-title">
51 <h4 class="panel-title">
52 <a class="collapsed" role="button" data-toggle="collapse" data-parent="#accordion" href="#collapseTwo" aria-expanded="false" aria-controls="collapseTwo">
52 <a class="collapsed" role="button" data-toggle="collapse" data-parent="#accordion" href="#collapseTwo" aria-expanded="false" aria-controls="collapseTwo">
53 Experiment List
53 Experiment List
54 </a>
54 </a>
55 </h4>
55 </h4>
56 </div>
56 </div>
57
57
58 <div id="collapseTwo" class="panel-collapse collapse in" role="tabpanel" aria-labelledby="headingTwo">
58 <div id="collapseTwo" class="panel-collapse collapse in" role="tabpanel" aria-labelledby="headingTwo">
59 <div class="panel-body">
59 <div class="panel-body">
60 <table class="table table-hover">
60 <table class="table table-hover">
61 <tr>
61 <tr>
62 <th>#</th>
62 <th>#</th>
63 {% for header in experiment_keys %}
63 {% for header in experiment_keys %}
64 <th>{{ header|title }}</th>
64 <th>{{ header|title }}</th>
65 {% endfor%}
65 {% endfor%}
66 </tr>
66 </tr>
67 {% for item in experiments %}
67 {% for item in experiments %}
68 <tr class="clickable-row" data-href="{% url 'url_experiment' item.id %}">
68 <tr class="clickable-row" s data-href="{% url 'url_experiment' item.id %}">
69 <td>{{ forloop.counter }}</td>
69 <td>{{ forloop.counter }}</td>
70 {% for key in experiment_keys %}
70 {% for key in experiment_keys %}
71 <td>{{ item|attr:key }}</td>
71 <td>{{ item|attr:key }}</td>
72 {% endfor %}
72 {% endfor %}
73 </tr>
73 </tr>
74 {% endfor %}
74 {% endfor %}
75 </table>
75 </table>
76 </div>
76 </div>
77 </div>
77 </div>
78 </div>
78 </div>
79 </div>
79 </div>
80 <br>
80 <br>
81 <!--<button class="btn btn-primary pull-right" style="margin-left: 10px" id="bt_mix">Mix Experiments</button>-->
81 <!--<button class="btn btn-primary pull-right" style="margin-left: 10px" id="bt_mix">Mix Experiments</button>-->
82 {% endblock %}
82 {% endblock %}
83
83
84 {% block sidebar%}
84 {% block sidebar%}
85 {% include "sidebar_devices.html" %}
85 {% include "sidebar_devices.html" %}
86 {% endblock %}
86 {% endblock %}
87
87
88 {% block extra-js%}
88 {% block extra-js%}
89 <script type="text/javascript">
89 <script type="text/javascript">
90
90
91 $(".clickable-row").click(function() {
91 $(".clickable-row").click(function() {
92 document.location = $(this).data("href");
92 document.location = $(this).data("href");
93 });
93 });
94
94
95 // $("#bt_edit").click(function() {
95 // $("#bt_edit").click(function() {
96 // document.location = "{% url 'url_edit_campaign' campaign.id %}";
96 // document.location = "{% url 'url_edit_campaign' campaign.id %}";
97 // });
97 // });
98
98
99 $("#bt_mix").click(function() {
99 $("#bt_mix").click(function() {
100
100
101 });
101 });
102
102
103 </script>
103 </script>
104 {% endblock %}
104 {% endblock %}
@@ -1,1051 +1,1054
1
1
2
2
3 import ast
3 import ast
4 import json
4 import json
5 import requests
5 import requests
6 import numpy as np
6 import numpy as np
7 from base64 import b64encode
7 from base64 import b64encode
8 from struct import pack
8 from struct import pack
9
9
10 from django.db import models
10 from django.db import models
11 from django.urls import reverse
11 from django.urls import reverse
12 from django.core.validators import MinValueValidator, MaxValueValidator
12 from django.core.validators import MinValueValidator, MaxValueValidator
13
13
14 from apps.main.models import Configuration
14 from apps.main.models import Configuration
15 from apps.main.utils import Params
15 from apps.main.utils import Params
16 from devices.rc import api
16 from devices.rc import api
17 from apps.rc.utils import RCFile
17 from apps.rc.utils import RCFile
18
18
19
19
20 LINE_TYPES = (
20 LINE_TYPES = (
21 ('none', 'Not used'),
21 ('none', 'Not used'),
22 ('tr', 'Transmission/reception selector signal'),
22 ('tr', 'Transmission/reception selector signal'),
23 ('tx', 'A modulating signal (Transmission pulse)'),
23 ('tx', 'A modulating signal (Transmission pulse)'),
24 ('codes', 'BPSK modulating signal'),
24 ('codes', 'BPSK modulating signal'),
25 ('windows', 'Sample window signal'),
25 ('windows', 'Sample window signal'),
26 ('sync', 'Synchronizing signal'),
26 ('sync', 'Synchronizing signal'),
27 ('flip', 'IPP related periodic signal'),
27 ('flip', 'IPP related periodic signal'),
28 ('prog_pulses', 'Programmable pulse'),
28 ('prog_pulses', 'Programmable pulse'),
29 ('mix', 'Mixed line'),
29 ('mix', 'Mixed line'),
30 )
30 )
31
31
32
32
33 SAMPLING_REFS = (
33 SAMPLING_REFS = (
34 ('none', 'No Reference'),
34 ('none', 'No Reference'),
35 ('begin_baud', 'Begin of the first baud'),
35 ('begin_baud', 'Begin of the first baud'),
36 ('first_baud', 'Middle of the first baud'),
36 ('first_baud', 'Middle of the first baud'),
37 ('sub_baud', 'Middle of the sub-baud')
37 ('sub_baud', 'Middle of the sub-baud')
38 )
38 )
39
39
40 DAT_CMDS = {
40 DAT_CMDS = {
41 # Pulse Design commands
41 # Pulse Design commands
42 'DISABLE' : 0, # Disables pulse generation
42 'DISABLE' : 0, # Disables pulse generation
43 'ENABLE' : 24, # Enables pulse generation
43 'ENABLE' : 24, # Enables pulse generation
44 'DELAY_START' : 40, # Write delay status to memory
44 'DELAY_START' : 40, # Write delay status to memory
45 'FLIP_START' : 48, # Write flip status to memory
45 'FLIP_START' : 48, # Write flip status to memory
46 'SAMPLING_PERIOD' : 64, # Establish Sampling Period
46 'SAMPLING_PERIOD' : 64, # Establish Sampling Period
47 'TX_ONE' : 72, # Output '0' in line TX
47 'TX_ONE' : 72, # Output '0' in line TX
48 'TX_ZERO' : 88, # Output '0' in line TX
48 'TX_ZERO' : 88, # Output '0' in line TX
49 'SW_ONE' : 104, # Output '0' in line SW
49 'SW_ONE' : 104, # Output '0' in line SW
50 'SW_ZERO' : 112, # Output '1' in line SW
50 'SW_ZERO' : 112, # Output '1' in line SW
51 'RESTART': 120, # Restarts CR8 Firmware
51 'RESTART': 120, # Restarts CR8 Firmware
52 'CONTINUE' : 253, # Function Unknown
52 'CONTINUE' : 253, # Function Unknown
53 # Commands available to new controllers
53 # Commands available to new controllers
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.
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 'CLOCK_DIVISOR_INIT' : 12, # Specifies Clock Divisor. Legacy command, ignored in the actual .dat conversion
55 'CLOCK_DIVISOR_INIT' : 12, # Specifies Clock Divisor. Legacy command, ignored in the actual .dat conversion
56 'CLOCK_DIVISOR_LAST' : 22, # Specifies Clock Divisor (default 60 if not included) syntax: 255,22 254,N-1.
56 'CLOCK_DIVISOR_LAST' : 22, # Specifies Clock Divisor (default 60 if not included) syntax: 255,22 254,N-1.
57 'CLOCK_DIVIDER' : 8,
57 'CLOCK_DIVIDER' : 8,
58 }
58 }
59
59
60 MAX_BITS = 8
60 MAX_BITS = 8
61
61
62 # Rotate left: 0b1001 --> 0b0011
62 # Rotate left: 0b1001 --> 0b0011
63 rol = lambda val, r_bits: \
63 rol = lambda val, r_bits: \
64 (val << r_bits%MAX_BITS) & (2**MAX_BITS-1) | \
64 (val << r_bits%MAX_BITS) & (2**MAX_BITS-1) | \
65 ((val & (2**MAX_BITS-1)) >> (MAX_BITS-(r_bits%MAX_BITS)))
65 ((val & (2**MAX_BITS-1)) >> (MAX_BITS-(r_bits%MAX_BITS)))
66
66
67 # Rotate right: 0b1001 --> 0b1100
67 # Rotate right: 0b1001 --> 0b1100
68 ror = lambda val, r_bits: \
68 ror = lambda val, r_bits: \
69 ((val & (2**MAX_BITS-1)) >> r_bits%MAX_BITS) | \
69 ((val & (2**MAX_BITS-1)) >> r_bits%MAX_BITS) | \
70 (val << (MAX_BITS-(r_bits%MAX_BITS)) & (2**MAX_BITS-1))
70 (val << (MAX_BITS-(r_bits%MAX_BITS)) & (2**MAX_BITS-1))
71
71
72
72
73 class RCConfiguration(Configuration):
73 class RCConfiguration(Configuration):
74
74
75 ipp = models.FloatField(verbose_name='IPP [Km]', validators=[MinValueValidator(1)], default=300)
75 ipp = models.FloatField(verbose_name='IPP [Km]', validators=[MinValueValidator(1)], default=300)
76 ntx = models.PositiveIntegerField(verbose_name='Number of TX', validators=[MinValueValidator(1)], default=1)
76 ntx = models.PositiveIntegerField(verbose_name='Number of TX', validators=[MinValueValidator(1)], default=1)
77 clock_in = models.FloatField(verbose_name='Clock in [MHz]', validators=[MinValueValidator(1), MaxValueValidator(80)], default=1)
77 clock_in = models.FloatField(verbose_name='Clock in [MHz]', validators=[MinValueValidator(1), MaxValueValidator(80)], default=1)
78 clock_divider = models.PositiveIntegerField(verbose_name='Clock divider', validators=[MinValueValidator(1), MaxValueValidator(256)], default=1)
78 clock_divider = models.PositiveIntegerField(verbose_name='Clock divider', validators=[MinValueValidator(1), MaxValueValidator(256)], default=1)
79 clock = models.FloatField(verbose_name='Clock Master [MHz]', blank=True, default=1)
79 clock = models.FloatField(verbose_name='Clock Master [MHz]', blank=True, default=1)
80 time_before = models.PositiveIntegerField(verbose_name='Time before [&mu;S]', default=12)
80 time_before = models.PositiveIntegerField(verbose_name='Time before [&mu;S]', default=12)
81 time_after = models.PositiveIntegerField(verbose_name='Time after [&mu;S]', default=1)
81 time_after = models.PositiveIntegerField(verbose_name='Time after [&mu;S]', default=1)
82 sync = models.PositiveIntegerField(verbose_name='Synchro delay', default=0)
82 sync = models.PositiveIntegerField(verbose_name='Synchro delay', default=0)
83 sampling_reference = models.CharField(verbose_name='Sampling Reference', choices=SAMPLING_REFS, default='none', max_length=40)
83 sampling_reference = models.CharField(verbose_name='Sampling Reference', choices=SAMPLING_REFS, default='none', max_length=40)
84 control_tx = models.BooleanField(verbose_name='Control Switch TX', default=False)
84 control_tx = models.BooleanField(verbose_name='Control Switch TX', default=False)
85 control_sw = models.BooleanField(verbose_name='Control Switch SW', default=False)
85 control_sw = models.BooleanField(verbose_name='Control Switch SW', default=False)
86 total_units = models.PositiveIntegerField(default=0)
86 total_units = models.PositiveIntegerField(default=0)
87 mix = models.BooleanField(default=False)
87 mix = models.BooleanField(default=False)
88
88
89 class Meta:
89 class Meta:
90 db_table = 'rc_configurations'
90 db_table = 'rc_configurations'
91
91
92 def get_absolute_url_plot(self):
92 def get_absolute_url_plot(self):
93 return reverse('url_plot_rc_pulses', args=[str(self.id)])
93 return reverse('url_plot_rc_pulses', args=[str(self.id)])
94
94
95 @property
95 @property
96 def ipp_unit(self):
96 def ipp_unit(self):
97
97
98 return '{} ({})'.format(self.ipp, int(self.ipp*self.km2unit))
98 return '{} ({})'.format(self.ipp, int(self.ipp*self.km2unit))
99
99
100 @property
100 @property
101 def us2unit(self):
101 def us2unit(self):
102
102
103 return self.clock_in/self.clock_divider
103 return self.clock_in/self.clock_divider
104
104
105 @property
105 @property
106 def km2unit(self):
106 def km2unit(self):
107
107
108 return 20./3*(self.clock_in/self.clock_divider)
108 return 20./3*(self.clock_in/self.clock_divider)
109
109
110 def clone(self, **kwargs):
110 def clone(self, **kwargs):
111
111
112 lines = self.get_lines()
112 lines = self.get_lines()
113 self.pk = None
113 self.pk = None
114 self.id = None
114 self.id = None
115 for attr, value in kwargs.items():
115 for attr, value in kwargs.items():
116 setattr(self, attr, value)
116 setattr(self, attr, value)
117 self.save()
117 self.save()
118
118
119 for line in lines:
119 for line in lines:
120 line.clone(rc_configuration=self)
120 line.clone(rc_configuration=self)
121
121
122 new_lines = self.get_lines()
122 new_lines = self.get_lines()
123 for line in new_lines:
123 for line in new_lines:
124 line_params = json.loads(line.params)
124 line_params = json.loads(line.params)
125 if 'TX_ref' in line_params and (line_params['TX_ref'] != '0'):
125 if 'TX_ref' in line_params and (line_params['TX_ref'] != '0'):
126 ref_line = RCLine.objects.get(pk=line_params['TX_ref'])
126 ref_line = RCLine.objects.get(pk=line_params['TX_ref'])
127 line_params['TX_ref'] = ['{}'.format(l.pk) for l in new_lines if l.get_name()==ref_line.get_name()][0]
127 line_params['TX_ref'] = ['{}'.format(l.pk) for l in new_lines if l.get_name()==ref_line.get_name()][0]
128 line.params = json.dumps(line_params)
128 line.params = json.dumps(line_params)
129 line.save()
129 line.save()
130
130
131 return self
131 return self
132
132
133 def get_lines(self, **kwargs):
133 def get_lines(self, **kwargs):
134 '''
134 '''
135 Retrieve configuration lines
135 Retrieve configuration lines
136 '''
136 '''
137
137
138 return RCLine.objects.filter(rc_configuration=self.pk, **kwargs)
138 return RCLine.objects.filter(rc_configuration=self.pk, **kwargs)
139
139
140
140
141 def clean_lines(self):
141 def clean_lines(self):
142 '''
142 '''
143 '''
143 '''
144
144
145 empty_line = RCLineType.objects.get(name='none')
145 empty_line = RCLineType.objects.get(name='none')
146
146
147 for line in self.get_lines():
147 for line in self.get_lines():
148 line.line_type = empty_line
148 line.line_type = empty_line
149 line.params = '{}'
149 line.params = '{}'
150 line.save()
150 line.save()
151
151
152 def dict_to_parms(self, params, id=None):
152 def dict_to_parms(self, params, id=None):
153 '''
153 '''
154 '''
154 '''
155
155
156 if id:
156 if id:
157 data = Params(params).get_conf(id_conf=id)
157 data = Params(params).get_conf(id_conf=id)
158 else:
158 else:
159 data = Params(params).get_conf(dtype='rc')
159 data = Params(params).get_conf(dtype='rc')
160
160
161 #print(data)
161 #print(data)
162 # self.name = data['name']
162 # self.name = data['name']
163 self.ipp = data['ipp']
163 self.ipp = data['ipp']
164 self.ntx = data['ntx']
164 self.ntx = data['ntx']
165 self.clock_in = data['clock_in']
165 self.clock_in = data['clock_in']
166 self.clock_divider = data['clock_divider']
166 self.clock_divider = data['clock_divider']
167 self.clock = data['clock']
167 self.clock = data['clock']
168 self.time_before = data['time_before']
168 self.time_before = data['time_before']
169 self.time_after = data['time_after']
169 self.time_after = data['time_after']
170 self.sync = data['sync']
170 self.sync = data['sync']
171 self.sampling_reference = data['sampling_reference']
171 self.sampling_reference = data['sampling_reference']
172 self.total_units = self.ipp*self.ntx*self.km2unit
172 self.total_units = self.ipp*self.ntx*self.km2unit
173 self.save()
173 self.save()
174 self.clean_lines()
174 self.clean_lines()
175
175
176 #print(params)
176 #print(params)
177
177
178 positions = {'tx':0, 'tr':0}
178 positions = {'tx':0, 'tr':0}
179 for i, id in enumerate(data['lines']):
179 for i, id in enumerate(data['lines']):
180 line_data = params['lines']['byId'][id]
180 line_data = params['lines']['byId'][id]
181 line_type = RCLineType.objects.get(name=line_data['line_type'])
181 line_type = RCLineType.objects.get(name=line_data['line_type'])
182 if line_type.name == 'codes':
182 if line_type.name == 'codes':
183 code = RCLineCode.objects.get(name=line_data['params']['code'])
183 code = RCLineCode.objects.get(name=line_data['params']['code'])
184 line_data['params']['code'] = code.pk
184 line_data['params']['code'] = code.pk
185 if line_type.name == 'tx':
185 if line_type.name == 'tx':
186 position = positions['tx']
186 position = positions['tx']
187 positions['tx'] += 1
187 positions['tx'] += 1
188 elif line_type.name == 'tr':
188 elif line_type.name == 'tr':
189 position = positions['tr']
189 position = positions['tr']
190 positions['tr'] += 1
190 positions['tr'] += 1
191 else:
191 else:
192 position = 0
192 position = 0
193 line, dum = RCLine.objects.update_or_create(
193 line, dum = RCLine.objects.update_or_create(
194 rc_configuration=self,
194 rc_configuration=self,
195 channel=i,
195 channel=i,
196 position=position,
196 position=position,
197 defaults={
197 defaults={
198 'line_type': line_type,
198 'line_type': line_type,
199 'params': json.dumps(line_data['params'])
199 'params': json.dumps(line_data['params'])
200 }
200 }
201 )
201 )
202 # print(line,flush=True)
202 # print(line,flush=True)
203
203
204 for i, line in enumerate(self.get_lines()):
204 for i, line in enumerate(self.get_lines()):
205 line_params = json.loads(line.params)
205 line_params = json.loads(line.params)
206 print("accedimos a dict_to5",flush=True)
206 print("accedimos a dict_to5",flush=True)
207 if 'TX_ref' in line_params:
207 if 'TX_ref' in line_params:
208 if line_params['TX_ref'] in (0, '0'):
208 if line_params['TX_ref'] in (0, '0'):
209 line_params['TX_ref'] = '0'
209 line_params['TX_ref'] = '0'
210 else:
210 else:
211 ref_id = '{}'.format(line_params['TX_ref'])
211 ref_id = '{}'.format(line_params['TX_ref'])
212 ref_line = params['lines']['byId'][ref_id]
212 ref_line = params['lines']['byId'][ref_id]
213 line_params['TX_ref'] = RCLine.objects.get(
213 line_params['TX_ref'] = RCLine.objects.get(
214 rc_configuration=self,
214 rc_configuration=self,
215 params=json.dumps(ref_line['params'])
215 params=json.dumps(ref_line['params'])
216 ).pk
216 ).pk
217 line.params = json.dumps(line_params)
217 line.params = json.dumps(line_params)
218 print(line.params)
218 print(line.params)
219 line.save()
219 line.save()
220 print("Fin de dict to param")
220 print("Fin de dict to param")
221
221
222 def get_delays(self):
222 def get_delays(self):
223
223
224 pulses = [line.pulses_as_points() for line in self.get_lines()]
224 pulses = [line.pulses_as_points() for line in self.get_lines()]
225 points = [tup for tups in pulses for tup in tups]
225 points = [tup for tups in pulses for tup in tups]
226 points = set([x for tup in points for x in tup])
226 points = set([x for tup in points for x in tup])
227 points = list(points)
227 points = list(points)
228 points.sort()
228 points.sort()
229
229
230 if points[0]!=0:
230 if points[0]!=0:
231 points.insert(0, 0)
231 points.insert(0, 0)
232
232
233 return [points[i+1]-points[i] for i in range(len(points)-1)]
233 return [points[i+1]-points[i] for i in range(len(points)-1)]
234
234
235
235
236 def get_pulses(self, binary=True):
236 def get_pulses(self, binary=True):
237
237
238 pulses = [line.pulses_as_points() for line in self.get_lines()]
238 pulses = [line.pulses_as_points() for line in self.get_lines()]
239 tuples = [tup for tups in pulses for tup in tups]
239 tuples = [tup for tups in pulses for tup in tups]
240 points = set([x for tup in tuples for x in tup])
240 points = set([x for tup in tuples for x in tup])
241 points = list(points)
241 points = list(points)
242 points.sort()
242 points.sort()
243 states = []
243 states = []
244 last = [0 for x in pulses]
244 last = [0 for x in pulses]
245
245
246 for x in points:
246 for x in points:
247 dum = []
247 dum = []
248 for i, tups in enumerate(pulses):
248 for i, tups in enumerate(pulses):
249 ups = [tup[0] for tup in tups if tup!=(0,0)]
249 ups = [tup[0] for tup in tups if tup!=(0,0)]
250 dws = [tup[1] for tup in tups if tup!=(0,0)]
250 dws = [tup[1] for tup in tups if tup!=(0,0)]
251 if x in ups:
251 if x in ups:
252 dum.append(1)
252 dum.append(1)
253 elif x in dws:
253 elif x in dws:
254 dum.append(0)
254 dum.append(0)
255 else:
255 else:
256 dum.append(last[i])
256 dum.append(last[i])
257 states.append(dum)
257 states.append(dum)
258 last = dum
258 last = dum
259
259
260 if binary:
260 if binary:
261 ret = []
261 ret = []
262 for flips in states:
262 for flips in states:
263 flips.reverse()
263 flips.reverse()
264 ret.append(int(''.join([str(x) for x in flips]), 2))
264 ret.append(int(''.join([str(x) for x in flips]), 2))
265 states = ret
265 states = ret
266
266
267 return states[:-1]
267 return states[:-1]
268
268
269 def add_cmd(self, cmd):
269 def add_cmd(self, cmd):
270
270
271 if cmd in DAT_CMDS:
271 if cmd in DAT_CMDS:
272 return (255, DAT_CMDS[cmd])
272 return (255, DAT_CMDS[cmd])
273
273
274 def add_data(self, value):
274 def add_data(self, value):
275
275
276 return (254, value-1)
276 return (254, value-1)
277
277
278 def parms_to_binary(self, dat=True):
278 def parms_to_binary(self, dat=True):
279 '''
279 '''
280 Create "dat" stream to be send to CR
280 Create "dat" stream to be send to CR
281 '''
281 '''
282
282
283 data = bytearray()
283 data = bytearray()
284 # create header
284 # create header
285 data.extend(self.add_cmd('DISABLE'))
285 data.extend(self.add_cmd('DISABLE'))
286 data.extend(self.add_cmd('CONTINUE'))
286 data.extend(self.add_cmd('CONTINUE'))
287 data.extend(self.add_cmd('RESTART'))
287 data.extend(self.add_cmd('RESTART'))
288
288
289 if self.control_sw:
289 if self.control_sw:
290 data.extend(self.add_cmd('SW_ONE'))
290 data.extend(self.add_cmd('SW_ONE'))
291 else:
291 else:
292 data.extend(self.add_cmd('SW_ZERO'))
292 data.extend(self.add_cmd('SW_ZERO'))
293
293
294 if self.control_tx:
294 if self.control_tx:
295 data.extend(self.add_cmd('TX_ONE'))
295 data.extend(self.add_cmd('TX_ONE'))
296 else:
296 else:
297 data.extend(self.add_cmd('TX_ZERO'))
297 data.extend(self.add_cmd('TX_ZERO'))
298
298
299 # write divider
299 # write divider
300 data.extend(self.add_cmd('CLOCK_DIVIDER'))
300 data.extend(self.add_cmd('CLOCK_DIVIDER'))
301 data.extend(self.add_data(self.clock_divider))
301 data.extend(self.add_data(self.clock_divider))
302
302
303 # write delays
303 # write delays
304 data.extend(self.add_cmd('DELAY_START'))
304 data.extend(self.add_cmd('DELAY_START'))
305 # first delay is always zero
305 # first delay is always zero
306 data.extend(self.add_data(1))
306 data.extend(self.add_data(1))
307
307
308 delays = self.get_delays()
308 delays = self.get_delays()
309
309
310 for delay in delays:
310 for delay in delays:
311 while delay>252:
311 while delay>252:
312 data.extend(self.add_data(253))
312 data.extend(self.add_data(253))
313 delay -= 253
313 delay -= 253
314 data.extend(self.add_data(int(delay)))
314 data.extend(self.add_data(int(delay)))
315
315
316 # write flips
316 # write flips
317 data.extend(self.add_cmd('FLIP_START'))
317 data.extend(self.add_cmd('FLIP_START'))
318
318
319 states = self.get_pulses(binary=True)
319 states = self.get_pulses(binary=True)
320
320
321
321
322 last = 0
322 last = 0
323 for flip, delay in zip(states, delays):
323 for flip, delay in zip(states, delays):
324 data.extend(self.add_data((flip^last)+1))
324 data.extend(self.add_data((flip^last)+1))
325 last = flip
325 last = flip
326 while delay>252:
326 while delay>252:
327 data.extend(self.add_data(1))
327 data.extend(self.add_data(1))
328 delay -= 253
328 delay -= 253
329
329
330 # write sampling period
330 # write sampling period
331 data.extend(self.add_cmd('SAMPLING_PERIOD'))
331 data.extend(self.add_cmd('SAMPLING_PERIOD'))
332 wins = self.get_lines(line_type__name='windows')
332 wins = self.get_lines(line_type__name='windows')
333 if wins:
333 if wins:
334 win_params = json.loads(wins[0].params)['params']
334 win_params = json.loads(wins[0].params)['params']
335 if win_params:
335 if win_params:
336 dh = int(win_params[0]['resolution']*self.km2unit)
336 dh = int(win_params[0]['resolution']*self.km2unit)
337 else:
337 else:
338 dh = 1
338 dh = 1
339 else:
339 else:
340 dh = 1
340 dh = 1
341 data.extend(self.add_data(dh))
341 data.extend(self.add_data(dh))
342
342
343 # write enable
343 # write enable
344 data.extend(self.add_cmd('ENABLE'))
344 data.extend(self.add_cmd('ENABLE'))
345
345
346 if not dat:
346 if not dat:
347 return data
347 return data
348
348
349 return '\n'.join(['{}'.format(x) for x in data])
349 return '\n'.join(['{}'.format(x) for x in data])
350
350
351 def update_pulses(self):
351 def update_pulses(self):
352 contador = 0
352 contador = 0
353 for line in self.get_lines():
353 for line in self.get_lines():
354 contador=contador+1
354 contador=contador+1
355 print(contador)
355 print(contador)
356 line.update_pulses()
356 line.update_pulses()
357
357
358 def plot_pulses2(self, km=False):
358 def plot_pulses2(self, km=False):
359
359
360 import matplotlib
360 import matplotlib
361 matplotlib.use('Agg')
361 matplotlib.use('Agg')
362 import matplotlib.pyplot as plt
362 import matplotlib.pyplot as plt
363 from bokeh.resources import CDN
363 from bokeh.resources import CDN
364 from bokeh.embed import components
364 from bokeh.embed import components
365 from bokeh.mpl import to_bokeh
365 from bokeh.mpl import to_bokeh
366 from bokeh.models.tools import WheelZoomTool, ResetTool, PanTool, HoverTool, SaveTool
366 from bokeh.models.tools import WheelZoomTool, ResetTool, PanTool, HoverTool, SaveTool
367
367
368 lines = self.get_lines()
368 lines = self.get_lines()
369
369
370 N = len(lines)
370 N = len(lines)
371 npoints = self.total_units/self.km2unit if km else self.total_units
371 npoints = self.total_units/self.km2unit if km else self.total_units
372 fig = plt.figure(figsize=(12, 2+N*0.5))
372 fig = plt.figure(figsize=(12, 2+N*0.5))
373 ax = fig.add_subplot(111)
373 ax = fig.add_subplot(111)
374 labels = ['IPP']
374 labels = ['IPP']
375
375
376 for i, line in enumerate(lines):
376 for i, line in enumerate(lines):
377 labels.append(line.get_name(channel=True))
377 labels.append(line.get_name(channel=True))
378 l = ax.plot((0, npoints),(N-i-1, N-i-1))
378 l = ax.plot((0, npoints),(N-i-1, N-i-1))
379 points = [(tup[0], tup[1]-tup[0]) for tup in line.pulses_as_points(km=km) if tup!=(0,0)]
379 points = [(tup[0], tup[1]-tup[0]) for tup in line.pulses_as_points(km=km) if tup!=(0,0)]
380 ax.broken_barh(points, (N-i-1, 0.5),
380 ax.broken_barh(points, (N-i-1, 0.5),
381 edgecolor=l[0].get_color(), facecolor='none')
381 edgecolor=l[0].get_color(), facecolor='none')
382
382
383 n = 0
383 n = 0
384 f = ((self.ntx+50)/100)*5 if ((self.ntx+50)/100)*10>0 else 2
384 f = ((self.ntx+50)/100)*5 if ((self.ntx+50)/100)*10>0 else 2
385 for x in np.arange(0, npoints, self.ipp if km else self.ipp*self.km2unit):
385 for x in np.arange(0, npoints, self.ipp if km else self.ipp*self.km2unit):
386 if n%f==0:
386 if n%f==0:
387 ax.text(x, N, '%s' % n, size=10)
387 ax.text(x, N, '%s' % n, size=10)
388 n += 1
388 n += 1
389
389
390 labels.reverse()
390 labels.reverse()
391 ax.set_yticks(range(len(labels)))
391 ax.set_yticks(range(len(labels)))
392 ax.set_yticklabels(labels)
392 ax.set_yticklabels(labels)
393 ax.set_xlabel = 'Units'
393 ax.set_xlabel = 'Units'
394 plot = to_bokeh(fig, use_pandas=False)
394 plot = to_bokeh(fig, use_pandas=False)
395 plot.tools = [PanTool(dimensions="width"), WheelZoomTool(dimensions="width"), ResetTool(), SaveTool()]
395 plot.tools = [PanTool(dimensions="width"), WheelZoomTool(dimensions="width"), ResetTool(), SaveTool()]
396 plot.toolbar_location="above"
396 plot.toolbar_location="above"
397
397
398 return components(plot, CDN)
398 return components(plot, CDN)
399
399
400 def plot_pulses(self, km=False):
400 def plot_pulses(self, km=False):
401
401
402 from bokeh.plotting import figure
402 from bokeh.plotting import figure
403 from bokeh.resources import CDN
403 from bokeh.resources import CDN
404 from bokeh.embed import components
404 from bokeh.embed import components
405 from bokeh.models import FixedTicker, PrintfTickFormatter
405 from bokeh.models import FixedTicker, PrintfTickFormatter
406 from bokeh.models.tools import WheelZoomTool, ResetTool, PanTool, HoverTool, SaveTool
406 from bokeh.models.tools import WheelZoomTool, ResetTool, PanTool, HoverTool, SaveTool
407 from bokeh.models.sources import ColumnDataSource
407 from bokeh.models.sources import ColumnDataSource
408
408
409 lines = self.get_lines().reverse()
409 lines = self.get_lines().reverse()
410
410
411 N = len(lines)
411 N = len(lines)
412 npoints = self.total_units/self.km2unit if km else self.total_units
412 npoints = self.total_units/self.km2unit if km else self.total_units
413 ipp = self.ipp if km else self.ipp*self.km2unit
413 ipp = self.ipp if km else self.ipp*self.km2unit
414
414
415 hover = HoverTool(tooltips=[("Line", "@name"),
415 hover = HoverTool(tooltips=[("Line", "@name"),
416 ("IPP", "@ipp"),
416 ("IPP", "@ipp"),
417 ("X", "@left")])
417 ("X", "@left")])
418
418
419 tools = [PanTool(dimensions="width"),
419 tools = [PanTool(dimensions="width"),
420 WheelZoomTool(dimensions="width"),
420 WheelZoomTool(dimensions="width"),
421 hover, SaveTool()]
421 hover, SaveTool()]
422
422
423 plot = figure(width=1000,
423 plot = figure(width=1000,
424 height=40+N*50,
424 height=40+N*50,
425 y_range = (0, N),
425 y_range = (0, N),
426 tools=tools,
426 tools=tools,
427 toolbar_location='above',
427 toolbar_location='above',
428 toolbar_sticky=False,)
428 toolbar_sticky=False,)
429
429
430 plot.xaxis.axis_label = 'Km' if km else 'Units'
430 plot.xaxis.axis_label = 'Km' if km else 'Units'
431 plot.xaxis[0].formatter = PrintfTickFormatter(format='%d')
431 plot.xaxis[0].formatter = PrintfTickFormatter(format='%d')
432 plot.yaxis.axis_label = 'Pulses'
432 plot.yaxis.axis_label = 'Pulses'
433 plot.yaxis[0].ticker=FixedTicker(ticks=list(range(N)))
433 plot.yaxis[0].ticker=FixedTicker(ticks=list(range(N)))
434 plot.yaxis[0].formatter = PrintfTickFormatter(format='Line %d')
434 plot.yaxis[0].formatter = PrintfTickFormatter(format='Line %d')
435
435
436 for i, line in enumerate(lines):
436 for i, line in enumerate(lines):
437
437
438 points = [tup for tup in line.pulses_as_points(km=km) if tup!=(0,0)]
438 points = [tup for tup in line.pulses_as_points(km=km) if tup!=(0,0)]
439
439
440 source = ColumnDataSource(data = dict(
440 source = ColumnDataSource(data = dict(
441 bottom = [i for tup in points],
441 bottom = [i for tup in points],
442 top = [i+0.5 for tup in points],
442 top = [i+0.5 for tup in points],
443 left = [tup[0] for tup in points],
443 left = [tup[0] for tup in points],
444 right = [tup[1] for tup in points],
444 right = [tup[1] for tup in points],
445 ipp = [int(tup[0]/ipp) for tup in points],
445 ipp = [int(tup[0]/ipp) for tup in points],
446 name = [line.get_name() for tup in points]
446 name = [line.get_name() for tup in points]
447 ))
447 ))
448
448
449 plot.quad(
449 plot.quad(
450 bottom = 'bottom',
450 bottom = 'bottom',
451 top = 'top',
451 top = 'top',
452 left = 'left',
452 left = 'left',
453 right = 'right',
453 right = 'right',
454 source = source,
454 source = source,
455 fill_alpha = 0,
455 fill_alpha = 0,
456 #line_color = 'blue',
456 #line_color = 'blue',
457 )
457 )
458
458
459 plot.line([0, npoints], [i, i])#, color='blue')
459 plot.line([0, npoints], [i, i])#, color='blue')
460
460
461 return components(plot, CDN)
461 return components(plot, CDN)
462
462
463 def request(self, cmd, method='get', **kwargs):
463 def request(self, cmd, method='get', **kwargs):
464
464
465 req = getattr(requests, method)(self.device.url(cmd), **kwargs)
465 req = getattr(requests, method)(self.device.url(cmd), **kwargs)
466 payload = req.json()
466 payload = req.json()
467
467
468 return payload
468 return payload
469
469
470 def status_device(self):
470 def status_device(self):
471
471
472 try:
472 try:
473 self.device.status = 0
473 self.device.status = 0
474 payload = self.request('status')
474 payload = self.request('status')
475 if payload['status']=='enable':
475 if payload['status']=='enable':
476 self.device.status = 3
476 self.device.status = 3
477 elif payload['status']=='disable':
477 elif payload['status']=='disable':
478 self.device.status = 2
478 self.device.status = 2
479 else:
479 else:
480 self.device.status = 1
480 self.device.status = 1
481 self.device.save()
481 self.device.save()
482 self.message = 'RC status: {}'.format(payload['status'])
482 self.message = 'RC status: {}'.format(payload['status'])
483 return False
483 return False
484 except Exception as e:
484 except Exception as e:
485 if 'No route to host' not in str(e):
485 if 'No route to host' not in str(e):
486 self.device.status = 4
486 self.device.status = 4
487 self.device.save()
487 self.device.save()
488 self.message = 'RC status: {}'.format(str(e))
488 self.message = 'RC status: {}'.format(str(e))
489 return False
489 return False
490
490
491 self.device.save()
491 self.device.save()
492 return True
492 return True
493
493
494 def reset_device(self):
494 def reset_device(self):
495
495
496 try:
496 try:
497 payload = self.request('reset', 'post')
497 payload = self.request('reset', 'post')
498 if payload['reset']=='ok':
498 if payload['reset']=='ok':
499 self.message = 'RC restarted OK'
499 self.message = 'RC restarted OK'
500 self.device.status = 2
500 self.device.status = 2
501 self.device.save()
501 self.device.save()
502 else:
502 else:
503 self.message = 'RC restart fail'
503 self.message = 'RC restart fail'
504 self.device.status = 4
504 self.device.status = 4
505 self.device.save()
505 self.device.save()
506 except Exception as e:
506 except Exception as e:
507 self.message = 'RC reset: {}'.format(str(e))
507 self.message = 'RC reset: {}'.format(str(e))
508 return False
508 return False
509
509
510 return True
510 return True
511
511
512 def stop_device(self):
512 def stop_device(self):
513
513 # Se crea el modo ocupado para una vez inicia el STOP
514 self.device.status = 5
515 self.device.save()
516 # Por si se demora deteniendo, que su estado sea busy
514 try:
517 try:
515 payload = self.request('stop', 'post')
518 payload = self.request('stop', 'post')
516 self.message = 'RC stop: {}'.format(payload['stop'])
519 self.message = 'RC stop: {}'.format(payload['stop'])
517 if payload['stop']=='ok':
520 if payload['stop']=='ok':
518 self.device.status = 2
521 self.device.status = 2
519 self.device.save()
522 self.device.save()
520 else:
523 else:
521 self.device.status = 4
524 self.device.status = 4
522 self.device.save()
525 self.device.save()
523 return False
526 return False
524 except Exception as e:
527 except Exception as e:
525 if 'No route to host' not in str(e):
528 if 'No route to host' not in str(e):
526 self.device.status = 4
529 self.device.status = 4
527 else:
530 else:
528 self.device.status = 0
531 self.device.status = 0
529 self.message = 'RC stop: {}'.format(str(e))
532 self.message = 'RC stop: {}'.format(str(e))
530 self.device.save()
533 self.device.save()
531 return False
534 return False
532
535
533 return True
536 return True
534
537
535 def start_device(self):
538 def start_device(self):
536
539
537 try:
540 try:
538 payload = self.request('start', 'post')
541 payload = self.request('start', 'post')
539 self.message = 'RC start: {}'.format(payload['start'])
542 self.message = 'RC start: {}'.format(payload['start'])
540 if payload['start']=='ok':
543 if payload['start']=='ok':
541 self.device.status = 3
544 self.device.status = 3
542 self.device.save()
545 self.device.save()
543 else:
546 else:
544 return False
547 return False
545 except Exception as e:
548 except Exception as e:
546 if 'No route to host' not in str(e):
549 if 'No route to host' not in str(e):
547 self.device.status = 4
550 self.device.status = 4
548 else:
551 else:
549 self.device.status = 0
552 self.device.status = 0
550 self.message = 'RC start: {}'.format(str(e))
553 self.message = 'RC start: {}'.format(str(e))
551 self.device.save()
554 self.device.save()
552 return False
555 return False
553
556
554 return True
557 return True
555
558
556 def write_device(self, raw=False):
559 def write_device(self, raw=False):
557 print("write device",flush=True)
560 print("write device",flush=True)
558
561
559 if not raw:
562 if not raw:
560 clock = RCClock.objects.get(rc_configuration=self)
563 clock = RCClock.objects.get(rc_configuration=self)
561 if clock.mode:
564 if clock.mode:
562 data = {'default': clock.frequency}
565 data = {'default': clock.frequency}
563 else:
566 else:
564 data = {'manual': [clock.multiplier, clock.divisor, clock.reference]}
567 data = {'manual': [clock.multiplier, clock.divisor, clock.reference]}
565 payload = self.request('setfreq', 'post', data=json.dumps(data))
568 payload = self.request('setfreq', 'post', data=json.dumps(data))
566 # print(payload)
569 # print(payload)
567 if payload['command'] != 'ok':
570 if payload['command'] != 'ok':
568 self.message = 'RC write: {}'.format(payload['command'])
571 self.message = 'RC write: {}'.format(payload['command'])
569 # print('RC write: {}'.format(payload['command']))
572 # print('RC write: {}'.format(payload['command']))
570 else:
573 else:
571 self.message = payload['programming']
574 self.message = payload['programming']
572 if payload['programming'] == 'fail':
575 if payload['programming'] == 'fail':
573 self.message = 'RC write: error programming CGS chip'
576 self.message = 'RC write: error programming CGS chip'
574
577
575 values = []
578 values = []
576 for pulse, delay in zip(self.get_pulses(), self.get_delays()):
579 for pulse, delay in zip(self.get_pulses(), self.get_delays()):
577 while delay > 65536:
580 while delay > 65536:
578 values.append((pulse, 65535))
581 values.append((pulse, 65535))
579 delay -= 65536
582 delay -= 65536
580 values.append((pulse, delay-1))
583 values.append((pulse, delay-1))
581 data = bytearray()
584 data = bytearray()
582 #reset
585 #reset
583 data.extend((128, 0))
586 data.extend((128, 0))
584 #disable
587 #disable
585 data.extend((129, 0))
588 data.extend((129, 0))
586 #SW switch
589 #SW switch
587 if self.control_sw:
590 if self.control_sw:
588 data.extend((130, 2))
591 data.extend((130, 2))
589 else:
592 else:
590 data.extend((130, 0))
593 data.extend((130, 0))
591 #divider
594 #divider
592 data.extend((131, self.clock_divider-1))
595 data.extend((131, self.clock_divider-1))
593 #enable writing
596 #enable writing
594 data.extend((139, 62))
597 data.extend((139, 62))
595
598
596 last = 0
599 last = 0
597 for tup in values:
600 for tup in values:
598 vals = pack('<HH', last^tup[0], tup[1])
601 vals = pack('<HH', last^tup[0], tup[1])
599 last = tup[0]
602 last = tup[0]
600 data.extend((133, vals[1], 132, vals[0], 133, vals[3], 132, vals[2]))
603 data.extend((133, vals[1], 132, vals[0], 133, vals[3], 132, vals[2]))
601
604
602 #enable
605 #enable
603 data.extend((129, 1))
606 data.extend((129, 1))
604
607
605 if raw:
608 if raw:
606 return b64encode(data)
609 return b64encode(data)
607
610
608 #try:
611 #try:
609 payload = self.request('stop', 'post')
612 payload = self.request('stop', 'post')
610 payload = self.request('reset', 'post')
613 payload = self.request('reset', 'post')
611 #payload = self.request('divider', 'post', data={'divider': self.clock_divider-1})
614 #payload = self.request('divider', 'post', data={'divider': self.clock_divider-1})
612 #payload = self.request('write', 'post', data=b64encode(bytearray((139, 62))), timeout=20)
615 #payload = self.request('write', 'post', data=b64encode(bytearray((139, 62))), timeout=20)
613 n = len(data)
616 n = len(data)
614 x = 0
617 x = 0
615 #while x < n:
618 #while x < n:
616 payload = self.request('write', 'post', data=b64encode(data))
619 payload = self.request('write', 'post', data=b64encode(data))
617 # x += 1024
620 # x += 1024
618
621
619 if payload['write']=='ok':
622 if payload['write']=='ok':
620 self.device.status = 3
623 self.device.status = 3
621 self.device.save()
624 self.device.save()
622 self.message = 'RC configured and started'
625 self.message = 'RC configured and started'
623 # print('RC configured and started')
626 # print('RC configured and started')
624 else:
627 else:
625 self.device.status = 1
628 self.device.status = 1
626 self.device.save()
629 self.device.save()
627 self.message = 'RC write: {}'.format(payload['write'])
630 self.message = 'RC write: {}'.format(payload['write'])
628 # print('RC write: {}'.format(payload['write']))
631 # print('RC write: {}'.format(payload['write']))
629 return False
632 return False
630
633
631 #payload = self.request('start', 'post')
634 #payload = self.request('start', 'post')
632
635
633 #except Exception as e:
636 #except Exception as e:
634 # if 'No route to host' not in str(e):
637 # if 'No route to host' not in str(e):
635 # self.device.status = 4
638 # self.device.status = 4
636 # else:
639 # else:
637 # self.device.status = 0
640 # self.device.status = 0
638 # self.message = 'RC write: {}'.format(str(e))
641 # self.message = 'RC write: {}'.format(str(e))
639 # self.device.save()
642 # self.device.save()
640 # return False
643 # return False
641
644
642 return True
645 return True
643
646
644
647
645 def get_absolute_url_import(self):
648 def get_absolute_url_import(self):
646 return reverse('url_import_rc_conf', args=[str(self.id)])
649 return reverse('url_import_rc_conf', args=[str(self.id)])
647
650
648
651
649 class RCLineCode(models.Model):
652 class RCLineCode(models.Model):
650
653
651 name = models.CharField(max_length=40)
654 name = models.CharField(max_length=40)
652 bits_per_code = models.PositiveIntegerField(default=0)
655 bits_per_code = models.PositiveIntegerField(default=0)
653 number_of_codes = models.PositiveIntegerField(default=0)
656 number_of_codes = models.PositiveIntegerField(default=0)
654 codes = models.TextField(blank=True, null=True)
657 codes = models.TextField(blank=True, null=True)
655
658
656 class Meta:
659 class Meta:
657 db_table = 'rc_line_codes'
660 db_table = 'rc_line_codes'
658 ordering = ('name',)
661 ordering = ('name',)
659
662
660 def __str__(self):
663 def __str__(self):
661 return u'%s' % self.name
664 return u'%s' % self.name
662
665
663
666
664 class RCLineType(models.Model):
667 class RCLineType(models.Model):
665
668
666 name = models.CharField(choices=LINE_TYPES, max_length=40)
669 name = models.CharField(choices=LINE_TYPES, max_length=40)
667 description = models.TextField(blank=True, null=True)
670 description = models.TextField(blank=True, null=True)
668 params = models.TextField(default='[]')
671 params = models.TextField(default='[]')
669
672
670 class Meta:
673 class Meta:
671 db_table = 'rc_line_types'
674 db_table = 'rc_line_types'
672
675
673 def __str__(self):
676 def __str__(self):
674 return u'%s - %s' % (self.name.upper(), self.get_name_display())
677 return u'%s - %s' % (self.name.upper(), self.get_name_display())
675
678
676
679
677 class RCLine(models.Model):
680 class RCLine(models.Model):
678
681
679 rc_configuration = models.ForeignKey('RCConfiguration', on_delete=models.CASCADE)
682 rc_configuration = models.ForeignKey('RCConfiguration', on_delete=models.CASCADE)
680 line_type = models.ForeignKey('RCLineType',on_delete=models.CASCADE)
683 line_type = models.ForeignKey('RCLineType',on_delete=models.CASCADE)
681 channel = models.PositiveIntegerField(default=0)
684 channel = models.PositiveIntegerField(default=0)
682 position = models.PositiveIntegerField(default=0)
685 position = models.PositiveIntegerField(default=0)
683 params = models.TextField(default='{}')
686 params = models.TextField(default='{}')
684 pulses = models.TextField(default='')
687 pulses = models.TextField(default='')
685
688
686 class Meta:
689 class Meta:
687 db_table = 'rc_lines'
690 db_table = 'rc_lines'
688 ordering = ['channel']
691 ordering = ['channel']
689
692
690 def __str__(self):
693 def __str__(self):
691 # print("AAAA: ",self.rc_configuration,flush=True)
694 # print("AAAA: ",self.rc_configuration,flush=True)
692 # ret = u'{}|{} - {}'.format(self.pk, self.get_name(),self.rc_configuration.name)
695 # ret = u'{}|{} - {}'.format(self.pk, self.get_name(),self.rc_configuration.name)
693 # return ret
696 # return ret
694 if self.rc_configuration:
697 if self.rc_configuration:
695 return u'{}|{} - {}'.format(self.pk, self.get_name(), self.rc_configuration.name)
698 return u'{}|{} - {}'.format(self.pk, self.get_name(), self.rc_configuration.name)
696
699
697 def jsonify(self):
700 def jsonify(self):
698
701
699 data = {}
702 data = {}
700 data['params'] = json.loads(self.params)
703 data['params'] = json.loads(self.params)
701 data['id'] = '{}'.format(self.pk)
704 data['id'] = '{}'.format(self.pk)
702 data['line_type'] = self.line_type.name
705 data['line_type'] = self.line_type.name
703 data['name'] = self.get_name()
706 data['name'] = self.get_name()
704 if data['line_type']=='codes':
707 if data['line_type']=='codes':
705 data['params']['code'] = RCLineCode.objects.get(pk=data['params']['code']).name
708 data['params']['code'] = RCLineCode.objects.get(pk=data['params']['code']).name
706
709
707 return data
710 return data
708
711
709
712
710 def clone(self, **kwargs):
713 def clone(self, **kwargs):
711
714
712 self.pk = None
715 self.pk = None
713 self.id = None
716 self.id = None
714
717
715 for attr, value in kwargs.items():
718 for attr, value in kwargs.items():
716 setattr(self, attr, value)
719 setattr(self, attr, value)
717
720
718 self.save()
721 self.save()
719
722
720 return self
723 return self
721
724
722 def get_name(self, channel=False):
725 def get_name(self, channel=False):
723
726
724 chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
727 chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
725 s = ''
728 s = ''
726
729
727 if self.line_type.name in ('tx',):
730 if self.line_type.name in ('tx',):
728 s = chars[self.position]
731 s = chars[self.position]
729 elif self.line_type.name in ('codes', 'windows', 'tr'):
732 elif self.line_type.name in ('codes', 'windows', 'tr'):
730 if 'TX_ref' in json.loads(self.params):
733 if 'TX_ref' in json.loads(self.params):
731 pk = json.loads(self.params)['TX_ref']
734 pk = json.loads(self.params)['TX_ref']
732 if pk in (0, '0'):
735 if pk in (0, '0'):
733 s = ','.join(chars[l.position] for l in self.rc_configuration.get_lines(line_type__name='tx'))
736 s = ','.join(chars[l.position] for l in self.rc_configuration.get_lines(line_type__name='tx'))
734 else:
737 else:
735 ref = RCLine.objects.get(pk=pk)
738 ref = RCLine.objects.get(pk=pk)
736 s = chars[ref.position]
739 s = chars[ref.position]
737 s = '({})'.format(s)
740 s = '({})'.format(s)
738
741
739 s = '{}{}'.format(self.line_type.name.upper(), s)
742 s = '{}{}'.format(self.line_type.name.upper(), s)
740
743
741 if channel:
744 if channel:
742 return '{} {}'.format(s, self.channel)
745 return '{} {}'.format(s, self.channel)
743 else:
746 else:
744 return s
747 return s
745
748
746 def get_lines(self, **kwargs):
749 def get_lines(self, **kwargs):
747
750
748 return RCLine.objects.filter(rc_configuration=self.rc_configuration, **kwargs)
751 return RCLine.objects.filter(rc_configuration=self.rc_configuration, **kwargs)
749
752
750 def pulses_as_array(self):
753 def pulses_as_array(self):
751
754
752 y = np.zeros(self.rc_configuration.total_units)
755 y = np.zeros(self.rc_configuration.total_units)
753
756
754 for tup in ast.literal_eval(self.pulses):
757 for tup in ast.literal_eval(self.pulses):
755 y[tup[0]:tup[1]] = 1
758 y[tup[0]:tup[1]] = 1
756
759
757 return y.astype(np.int8)
760 return y.astype(np.int8)
758
761
759 def pulses_as_points(self, km=False):
762 def pulses_as_points(self, km=False):
760
763
761 if km:
764 if km:
762 unit2km = 1/self.rc_configuration.km2unit
765 unit2km = 1/self.rc_configuration.km2unit
763 return [(tup[0]*unit2km, tup[1]*unit2km) for tup in ast.literal_eval(self.pulses)]
766 return [(tup[0]*unit2km, tup[1]*unit2km) for tup in ast.literal_eval(self.pulses)]
764 else:
767 else:
765 return ast.literal_eval(self.pulses)
768 return ast.literal_eval(self.pulses)
766
769
767 def get_win_ref(self, params, tx_id, km2unit):
770 def get_win_ref(self, params, tx_id, km2unit):
768
771
769 ref = self.rc_configuration.sampling_reference
772 ref = self.rc_configuration.sampling_reference
770 codes = [line for line in self.get_lines(line_type__name='codes') if int(json.loads(line.params)['TX_ref'])==int(tx_id)]
773 codes = [line for line in self.get_lines(line_type__name='codes') if int(json.loads(line.params)['TX_ref'])==int(tx_id)]
771
774
772 if codes:
775 if codes:
773 tx_width = float(json.loads(RCLine.objects.get(pk=tx_id).params)['pulse_width'])*km2unit/len(json.loads(codes[0].params)['codes'][0])
776 tx_width = float(json.loads(RCLine.objects.get(pk=tx_id).params)['pulse_width'])*km2unit/len(json.loads(codes[0].params)['codes'][0])
774 else:
777 else:
775 tx_width = float(json.loads(RCLine.objects.get(pk=tx_id).params)['pulse_width'])*km2unit
778 tx_width = float(json.loads(RCLine.objects.get(pk=tx_id).params)['pulse_width'])*km2unit
776
779
777 if ref=='first_baud':
780 if ref=='first_baud':
778 return int(1 + round((tx_width + 1)/2 + params['first_height']*km2unit - params['resolution']*km2unit))
781 return int(1 + round((tx_width + 1)/2 + params['first_height']*km2unit - params['resolution']*km2unit))
779 elif ref=='sub_baud':
782 elif ref=='sub_baud':
780 return np.ceil(1 + params['first_height']*km2unit - params['resolution']*km2unit/2)
783 return np.ceil(1 + params['first_height']*km2unit - params['resolution']*km2unit/2)
781 else:
784 else:
782 return 0
785 return 0
783
786
784 def update_pulses(self):
787 def update_pulses(self):
785 '''
788 '''
786 Update pulses field
789 Update pulses field
787 '''
790 '''
788
791
789 km2unit = self.rc_configuration.km2unit
792 km2unit = self.rc_configuration.km2unit
790 us2unit = self.rc_configuration.us2unit
793 us2unit = self.rc_configuration.us2unit
791 ipp = self.rc_configuration.ipp
794 ipp = self.rc_configuration.ipp
792 ntx = int(self.rc_configuration.ntx)
795 ntx = int(self.rc_configuration.ntx)
793 ipp_u = int(ipp*km2unit)
796 ipp_u = int(ipp*km2unit)
794 total = ipp_u*ntx if self.rc_configuration.total_units==0 else self.rc_configuration.total_units
797 total = ipp_u*ntx if self.rc_configuration.total_units==0 else self.rc_configuration.total_units
795 y = []
798 y = []
796
799
797 if self.line_type.name=='tr':
800 if self.line_type.name=='tr':
798 tr_params = json.loads(self.params)
801 tr_params = json.loads(self.params)
799 #print(tr_params)
802 #print(tr_params)
800 #print(tr_params['TX_ref'])
803 #print(tr_params['TX_ref'])
801 if tr_params['TX_ref'] in ('0', 0):
804 if tr_params['TX_ref'] in ('0', 0):
802 txs = self.get_lines(line_type__name='tx')
805 txs = self.get_lines(line_type__name='tx')
803 else:
806 else:
804 txs = RCLine.objects.filter(pk=tr_params['TX_ref'])
807 txs = RCLine.objects.filter(pk=tr_params['TX_ref'])
805
808
806 for tx in txs:
809 for tx in txs:
807 params = json.loads(tx.params)
810 params = json.loads(tx.params)
808
811
809 if float(params['pulse_width'])==0:
812 if float(params['pulse_width'])==0:
810 continue
813 continue
811 delays = [float(d)*km2unit for d in params['delays'].split(',') if d]
814 delays = [float(d)*km2unit for d in params['delays'].split(',') if d]
812 width = float(params['pulse_width'])*km2unit+int(self.rc_configuration.time_before*us2unit)
815 width = float(params['pulse_width'])*km2unit+int(self.rc_configuration.time_before*us2unit)
813 before = 0
816 before = 0
814 after = int(self.rc_configuration.time_after*us2unit)
817 after = int(self.rc_configuration.time_after*us2unit)
815
818
816 y_tx = self.points(ntx, ipp_u, width,
819 y_tx = self.points(ntx, ipp_u, width,
817 delay=delays,
820 delay=delays,
818 before=before,
821 before=before,
819 after=after,
822 after=after,
820 sync=self.rc_configuration.sync)
823 sync=self.rc_configuration.sync)
821
824
822 ranges = params['range'].split(',')
825 ranges = params['range'].split(',')
823
826
824 if len(ranges)>0 and ranges[0]!='0':
827 if len(ranges)>0 and ranges[0]!='0':
825 y_tx = self.mask_ranges(y_tx, ranges)
828 y_tx = self.mask_ranges(y_tx, ranges)
826
829
827 tr_ranges = tr_params['range'].split(',')
830 tr_ranges = tr_params['range'].split(',')
828
831
829 if len(tr_ranges)>0 and tr_ranges[0]!='0':
832 if len(tr_ranges)>0 and tr_ranges[0]!='0':
830 y_tx = self.mask_ranges(y_tx, tr_ranges)
833 y_tx = self.mask_ranges(y_tx, tr_ranges)
831
834
832 y.extend(y_tx)
835 y.extend(y_tx)
833
836
834 self.pulses = str(y)
837 self.pulses = str(y)
835 y = self.array_to_points(self.pulses_as_array())
838 y = self.array_to_points(self.pulses_as_array())
836
839
837 elif self.line_type.name=='tx':
840 elif self.line_type.name=='tx':
838 params = json.loads(self.params)
841 params = json.loads(self.params)
839 delays = [float(d)*km2unit for d in params['delays'].split(',') if d]
842 delays = [float(d)*km2unit for d in params['delays'].split(',') if d]
840 width = float(params['pulse_width'])*km2unit
843 width = float(params['pulse_width'])*km2unit
841
844
842 if width>0:
845 if width>0:
843 before = int(self.rc_configuration.time_before*us2unit)
846 before = int(self.rc_configuration.time_before*us2unit)
844 after = 0
847 after = 0
845
848
846 y = self.points(ntx, ipp_u, width,
849 y = self.points(ntx, ipp_u, width,
847 delay=delays,
850 delay=delays,
848 before=before,
851 before=before,
849 after=after,
852 after=after,
850 sync=self.rc_configuration.sync)
853 sync=self.rc_configuration.sync)
851
854
852 ranges = params['range'].split(',')
855 ranges = params['range'].split(',')
853
856
854 if len(ranges)>0 and ranges[0]!='0':
857 if len(ranges)>0 and ranges[0]!='0':
855 y = self.mask_ranges(y, ranges)
858 y = self.mask_ranges(y, ranges)
856
859
857 elif self.line_type.name=='flip':
860 elif self.line_type.name=='flip':
858 n = float(json.loads(self.params)['number_of_flips'])
861 n = float(json.loads(self.params)['number_of_flips'])
859 width = n*ipp*km2unit
862 width = n*ipp*km2unit
860 y = self.points(int((ntx+1)/(2*n)), ipp_u*n*2, width)
863 y = self.points(int((ntx+1)/(2*n)), ipp_u*n*2, width)
861
864
862 elif self.line_type.name=='codes':
865 elif self.line_type.name=='codes':
863 params = json.loads(self.params)
866 params = json.loads(self.params)
864 tx = RCLine.objects.get(pk=params['TX_ref'])
867 tx = RCLine.objects.get(pk=params['TX_ref'])
865 tx_params = json.loads(tx.params)
868 tx_params = json.loads(tx.params)
866 delays = [float(d)*km2unit for d in tx_params['delays'].split(',') if d]
869 delays = [float(d)*km2unit for d in tx_params['delays'].split(',') if d]
867 f = int(float(tx_params['pulse_width'])*km2unit/len(params['codes'][0]))
870 f = int(float(tx_params['pulse_width'])*km2unit/len(params['codes'][0]))
868 codes = [(np.fromstring(''.join([s*f for s in code]), dtype=np.uint8)-48).astype(np.int8) for code in params['codes']]
871 codes = [(np.fromstring(''.join([s*f for s in code]), dtype=np.uint8)-48).astype(np.int8) for code in params['codes']]
869 codes = [self.array_to_points(code) for code in codes]
872 codes = [self.array_to_points(code) for code in codes]
870 n = len(codes)
873 n = len(codes)
871
874
872 ranges = tx_params['range'].split(',')
875 ranges = tx_params['range'].split(',')
873 if len(ranges)>0 and ranges[0]!='0':
876 if len(ranges)>0 and ranges[0]!='0':
874 dum = self.mask_ranges(tx.pulses_as_points(), ranges)
877 dum = self.mask_ranges(tx.pulses_as_points(), ranges)
875 else:
878 else:
876 dum = tx.pulses_as_points()
879 dum = tx.pulses_as_points()
877
880
878 for i, tup in enumerate(dum):
881 for i, tup in enumerate(dum):
879 if tup==(0,0): continue
882 if tup==(0,0): continue
880 code = codes[i%n]
883 code = codes[i%n]
881 y.extend([(c[0]+tup[0], c[1]+tup[0]) for c in code])
884 y.extend([(c[0]+tup[0], c[1]+tup[0]) for c in code])
882
885
883 elif self.line_type.name=='sync':
886 elif self.line_type.name=='sync':
884 params = json.loads(self.params)
887 params = json.loads(self.params)
885 n = ipp_u*ntx
888 n = ipp_u*ntx
886 if params['invert'] in ('1', 1):
889 if params['invert'] in ('1', 1):
887 y = [(n-1, n)]
890 y = [(n-1, n)]
888 else:
891 else:
889 y = [(0, 1)]
892 y = [(0, 1)]
890
893
891 elif self.line_type.name=='prog_pulses':
894 elif self.line_type.name=='prog_pulses':
892 params = json.loads(self.params)
895 params = json.loads(self.params)
893 if int(params['periodic'])==0:
896 if int(params['periodic'])==0:
894 nntx = 1
897 nntx = 1
895 nipp = ipp_u*ntx
898 nipp = ipp_u*ntx
896 else:
899 else:
897 nntx = ntx
900 nntx = ntx
898 nipp = ipp_u
901 nipp = ipp_u
899
902
900 if 'params' in params and len(params['params'])>0:
903 if 'params' in params and len(params['params'])>0:
901 for p in params['params']:
904 for p in params['params']:
902 y_pp = self.points(nntx, nipp,
905 y_pp = self.points(nntx, nipp,
903 p['end']-p['begin'],
906 p['end']-p['begin'],
904 before=p['begin'])
907 before=p['begin'])
905
908
906 y.extend(y_pp)
909 y.extend(y_pp)
907
910
908 elif self.line_type.name=='windows':
911 elif self.line_type.name=='windows':
909 params = json.loads(self.params)
912 params = json.loads(self.params)
910 if 'params' in params and len(params['params'])>0:
913 if 'params' in params and len(params['params'])>0:
911 tx = RCLine.objects.get(pk=params['TX_ref'])
914 tx = RCLine.objects.get(pk=params['TX_ref'])
912 tx_params = json.loads(tx.params)
915 tx_params = json.loads(tx.params)
913 ranges = tx_params['range'].split(',')
916 ranges = tx_params['range'].split(',')
914 for p in params['params']:
917 for p in params['params']:
915 y_win = self.points(ntx, ipp_u,
918 y_win = self.points(ntx, ipp_u,
916 p['resolution']*p['number_of_samples']*km2unit,
919 p['resolution']*p['number_of_samples']*km2unit,
917 before=int(self.rc_configuration.time_before*us2unit)+p['first_height']*km2unit,
920 before=int(self.rc_configuration.time_before*us2unit)+p['first_height']*km2unit,
918 sync=self.rc_configuration.sync+self.get_win_ref(p, params['TX_ref'], km2unit))
921 sync=self.rc_configuration.sync+self.get_win_ref(p, params['TX_ref'], km2unit))
919
922
920
923
921 if len(ranges)>0 and ranges[0]!='0':
924 if len(ranges)>0 and ranges[0]!='0':
922 y_win = self.mask_ranges(y_win, ranges)
925 y_win = self.mask_ranges(y_win, ranges)
923
926
924 y.extend(y_win)
927 y.extend(y_win)
925
928
926 elif self.line_type.name=='mix':
929 elif self.line_type.name=='mix':
927 values = self.rc_configuration.parameters.split('-')
930 values = self.rc_configuration.parameters.split('-')
928 confs = [RCConfiguration.objects.get(pk=value.split('|')[0]) for value in values]
931 confs = [RCConfiguration.objects.get(pk=value.split('|')[0]) for value in values]
929 modes = [value.split('|')[1] for value in values]
932 modes = [value.split('|')[1] for value in values]
930 ops = [value.split('|')[2] for value in values]
933 ops = [value.split('|')[2] for value in values]
931 delays = [value.split('|')[3] for value in values]
934 delays = [value.split('|')[3] for value in values]
932 masks = [value.split('|')[4] for value in values]
935 masks = [value.split('|')[4] for value in values]
933 print("masks")
936 print("masks")
934 print(masks)
937 print(masks)
935 print('{:8b}'.format(int(masks[0])))
938 print('{:8b}'.format(int(masks[0])))
936 mask = list('{:8b}'.format(int(masks[0])))
939 mask = list('{:8b}'.format(int(masks[0])))
937 print("mask")
940 print("mask")
938 print(mask)
941 print(mask)
939 mask.reverse()
942 mask.reverse()
940 print("mask reverse")
943 print("mask reverse")
941 print(mask)
944 print(mask)
942 if mask[self.channel] in ('0', '', ' '):
945 if mask[self.channel] in ('0', '', ' '):
943 y = np.zeros(confs[0].total_units, dtype=np.int8)
946 y = np.zeros(confs[0].total_units, dtype=np.int8)
944 else:
947 else:
945 y = confs[0].get_lines(channel=self.channel)[0].pulses_as_array()
948 y = confs[0].get_lines(channel=self.channel)[0].pulses_as_array()
946
949
947 for i in range(1, len(values)):
950 for i in range(1, len(values)):
948 mask = list('{:8b}'.format(int(masks[i])))
951 mask = list('{:8b}'.format(int(masks[i])))
949 mask.reverse()
952 mask.reverse()
950
953
951 if mask[self.channel] in ('0', '', ' '):
954 if mask[self.channel] in ('0', '', ' '):
952 continue
955 continue
953 Y = confs[i].get_lines(channel=self.channel)[0].pulses_as_array()
956 Y = confs[i].get_lines(channel=self.channel)[0].pulses_as_array()
954 delay = float(delays[i])*km2unit
957 delay = float(delays[i])*km2unit
955
958
956 if modes[i]=='P':
959 if modes[i]=='P':
957 if delay>0:
960 if delay>0:
958 if delay<self.rc_configuration.ipp*km2unit and len(Y)==len(y):
961 if delay<self.rc_configuration.ipp*km2unit and len(Y)==len(y):
959 y_temp = np.empty_like(Y)
962 y_temp = np.empty_like(Y)
960 y_temp[:delay] = 0
963 y_temp[:delay] = 0
961 y_temp[delay:] = Y[:-delay]
964 y_temp[delay:] = Y[:-delay]
962 elif delay+len(Y)>len(y):
965 elif delay+len(Y)>len(y):
963 y_new = np.zeros(delay+len(Y), dtype=np.int8)
966 y_new = np.zeros(delay+len(Y), dtype=np.int8)
964 y_new[:len(y)] = y
967 y_new[:len(y)] = y
965 y = y_new
968 y = y_new
966 y_temp = np.zeros(delay+len(Y), dtype=np.int8)
969 y_temp = np.zeros(delay+len(Y), dtype=np.int8)
967 y_temp[-len(Y):] = Y
970 y_temp[-len(Y):] = Y
968 elif delay+len(Y)==len(y):
971 elif delay+len(Y)==len(y):
969 y_temp = np.zeros(delay+len(Y))
972 y_temp = np.zeros(delay+len(Y))
970 y_temp[-len(Y):] = Y
973 y_temp[-len(Y):] = Y
971 elif delay+len(Y)<len(y):
974 elif delay+len(Y)<len(y):
972 y_temp = np.zeros(len(y), dtype=np.int8)
975 y_temp = np.zeros(len(y), dtype=np.int8)
973 y_temp[delay:delay+len(Y)] = Y
976 y_temp[delay:delay+len(Y)] = Y
974 else:
977 else:
975 y_temp = Y.copy()
978 y_temp = Y.copy()
976
979
977 if ops[i]=='OR':
980 if ops[i]=='OR':
978 y = y | y_temp
981 y = y | y_temp
979 elif ops[i]=='XOR':
982 elif ops[i]=='XOR':
980 y = y ^ y_temp
983 y = y ^ y_temp
981 elif ops[i]=='AND':
984 elif ops[i]=='AND':
982 y = y & y_temp
985 y = y & y_temp
983 elif ops[i]=='NAND':
986 elif ops[i]=='NAND':
984 y = y & ~y_temp
987 y = y & ~y_temp
985 else:
988 else:
986 y = np.concatenate([y, Y])
989 y = np.concatenate([y, Y])
987
990
988 total = len(y)
991 total = len(y)
989 y = self.array_to_points(y)
992 y = self.array_to_points(y)
990
993
991 else:
994 else:
992 y = []
995 y = []
993
996
994 if self.rc_configuration.total_units != total:
997 if self.rc_configuration.total_units != total:
995 self.rc_configuration.total_units = total
998 self.rc_configuration.total_units = total
996 self.rc_configuration.save()
999 self.rc_configuration.save()
997
1000
998 self.pulses = str(y)
1001 self.pulses = str(y)
999 self.save()
1002 self.save()
1000
1003
1001 @staticmethod
1004 @staticmethod
1002 def array_to_points(X):
1005 def array_to_points(X):
1003
1006
1004 if X.size==0:
1007 if X.size==0:
1005 return []
1008 return []
1006
1009
1007 d = X[1:]-X[:-1]
1010 d = X[1:]-X[:-1]
1008
1011
1009 up = np.where(d==1)[0]
1012 up = np.where(d==1)[0]
1010 if X[0]==1:
1013 if X[0]==1:
1011 up = np.concatenate((np.array([-1]), up))
1014 up = np.concatenate((np.array([-1]), up))
1012 up += 1
1015 up += 1
1013
1016
1014 dw = np.where(d==-1)[0]
1017 dw = np.where(d==-1)[0]
1015 if X[-1]==1:
1018 if X[-1]==1:
1016 dw = np.concatenate((dw, np.array([len(X)-1])))
1019 dw = np.concatenate((dw, np.array([len(X)-1])))
1017 dw += 1
1020 dw += 1
1018
1021
1019 return [(tup[0], tup[1]) for tup in zip(up, dw)]
1022 return [(tup[0], tup[1]) for tup in zip(up, dw)]
1020
1023
1021 @staticmethod
1024 @staticmethod
1022 def mask_ranges(Y, ranges):
1025 def mask_ranges(Y, ranges):
1023
1026
1024 y = [(0, 0) for __ in Y]
1027 y = [(0, 0) for __ in Y]
1025
1028
1026 for index in ranges:
1029 for index in ranges:
1027 if '-' in index:
1030 if '-' in index:
1028 args = [int(a) for a in index.split('-')]
1031 args = [int(a) for a in index.split('-')]
1029 y[args[0]-1:args[1]] = Y[args[0]-1:args[1]]
1032 y[args[0]-1:args[1]] = Y[args[0]-1:args[1]]
1030 else:
1033 else:
1031 y[int(index)-1] = Y[int(index)-1]
1034 y[int(index)-1] = Y[int(index)-1]
1032
1035
1033 return y
1036 return y
1034
1037
1035 @staticmethod
1038 @staticmethod
1036 def points(ntx, ipp, width, delay=[0], before=0, after=0, sync=0):
1039 def points(ntx, ipp, width, delay=[0], before=0, after=0, sync=0):
1037
1040
1038 delays = len(delay)
1041 delays = len(delay)
1039
1042
1040 Y = [(int(ipp*x+before+delay[x%delays]+sync), int(ipp*x+width+before+delay[x%delays]+after+sync)) for x in range(ntx)]
1043 Y = [(int(ipp*x+before+delay[x%delays]+sync), int(ipp*x+width+before+delay[x%delays]+after+sync)) for x in range(ntx)]
1041
1044
1042 return Y
1045 return Y
1043
1046
1044 class RCClock(models.Model):
1047 class RCClock(models.Model):
1045
1048
1046 rc_configuration = models.ForeignKey('RCConfiguration', on_delete=models.CASCADE)
1049 rc_configuration = models.ForeignKey('RCConfiguration', on_delete=models.CASCADE)
1047 mode = models.BooleanField(default=True, choices=((True, 'Auto'), (False, 'Manual')))
1050 mode = models.BooleanField(default=True, choices=((True, 'Auto'), (False, 'Manual')))
1048 multiplier = models.PositiveIntegerField(default=60)
1051 multiplier = models.PositiveIntegerField(default=60)
1049 divisor = models.PositiveIntegerField(default=10)
1052 divisor = models.PositiveIntegerField(default=10)
1050 reference = models.PositiveSmallIntegerField(default=1, choices=((0, 'Internal (25MHz)'), (1, 'External (10MHz)')))
1053 reference = models.PositiveSmallIntegerField(default=1, choices=((0, 'Internal (25MHz)'), (1, 'External (10MHz)')))
1051 frequency = models.FloatField(default=60.0) No newline at end of file
1054 frequency = models.FloatField(default=60.0)
General Comments 0
You need to be logged in to leave comments. Login now