##// END OF EJS Templates
Task #714: Modulo Web ABS...
Fiorella Quino -
r181:ea9394e8ace0
parent child
Show More
@@ -1,940 +1,1077
1 1 from django.db import models
2 2 from apps.main.models import Configuration
3 3 from django.core.urlresolvers import reverse
4 4 # Create your models here.
5 5
6 6 import ast
7 7 import socket
8 8 import json
9 9 import requests
10 10 import struct
11 11 import sys, time
12 12
13 13 import multiprocessing
14 14
15 15
16 16 antenna_default = json.dumps({
17 17 "antenna_up": [[0.0,0.0,0.0,0.0,0.5,0.5,0.5,0.5],
18 18 [0.0,0.0,0.0,0.0,0.5,0.5,0.5,0.5],
19 19 [0.0,0.0,0.0,0.0,0.5,0.5,0.5,0.5],
20 20 [0.0,0.0,0.0,0.0,0.5,0.5,0.5,0.5],
21 21 [0.5,0.5,0.5,0.5,1.0,1.0,1.0,1.0],
22 22 [0.5,0.5,0.5,0.5,1.0,1.0,1.0,1.0],
23 23 [0.5,0.5,0.5,0.5,1.0,1.0,1.0,1.0],
24 24 [0.5,0.5,0.5,0.5,1.0,1.0,1.0,1.0]
25 25 ]
26 26 ,
27 27 "antenna_down": [[0.0,0.0,0.0,0.0,0.5,0.5,0.5,0.5],
28 28 [0.0,0.0,0.0,0.0,0.5,0.5,0.5,0.5],
29 29 [0.0,0.0,0.0,0.0,0.5,0.5,0.5,0.5],
30 30 [0.0,0.0,0.0,0.0,0.5,0.5,0.5,0.5],
31 31 [0.5,0.5,0.5,0.5,3.0,3.0,3.0,3.0],
32 32 [0.5,0.5,0.5,0.5,3.0,3.0,3.0,3.0],
33 33 [0.5,0.5,0.5,0.5,3.0,3.0,3.0,3.0],
34 34 [0.5,0.5,0.5,0.5,3.0,3.0,3.0,3.0]],
35 35 })
36 36
37 37
38 38 tx_default = json.dumps({
39 39 "up": [[1,1,1,1,0,0,0,0],
40 40 [1,1,1,1,0,0,0,0],
41 41 [1,1,1,1,0,0,0,0],
42 42 [1,1,1,1,0,0,0,0],
43 43 [0,0,0,0,1,1,1,1],
44 44 [0,0,0,0,1,1,1,1],
45 45 [0,0,0,0,1,1,1,1],
46 46 [0,0,0,0,1,1,1,1]],
47 47
48 48 "down": [[1,1,1,1,0,0,0,0],
49 49 [1,1,1,1,0,0,0,0],
50 50 [1,1,1,1,0,0,0,0],
51 51 [1,1,1,1,0,0,0,0],
52 52 [0,0,0,0,1,1,1,1],
53 53 [0,0,0,0,1,1,1,1],
54 54 [0,0,0,0,1,1,1,1],
55 55 [0,0,0,0,1,1,1,1]],
56 56 })
57 57
58 58 rx_default = json.dumps({
59 59 "up": [[1,1,1,1,0,0,0,0],
60 60 [1,1,1,1,0,0,0,0],
61 61 [1,1,1,1,0,0,0,0],
62 62 [1,1,1,1,0,0,0,0],
63 63 [0,0,0,0,1,1,1,1],
64 64 [0,0,0,0,1,1,1,1],
65 65 [0,0,0,0,1,1,1,1],
66 66 [0,0,0,0,1,1,1,1]],
67 67
68 68 "down": [[1,1,1,1,0,0,0,0],
69 69 [1,1,1,1,0,0,0,0],
70 70 [1,1,1,1,0,0,0,0],
71 71 [1,1,1,1,0,0,0,0],
72 72 [0,0,0,0,1,1,1,1],
73 73 [0,0,0,0,1,1,1,1],
74 74 [0,0,0,0,1,1,1,1],
75 75 [0,0,0,0,1,1,1,1]],
76 76 })
77 77
78 78 conf_default = {}
79 79 status_default = {}
80 80 for i in range(1,65):
81 81 conf_default[str(i)] = ""
82 82 status_default[str(i)] = 0
83 83
84 84 ues_default = json.dumps({
85 85 "up": [0.533333,0.00000,1.06667,0.00000],
86 86 "down": [0.533333,0.00000,1.06667,0.00000]
87 87 })
88 88
89 89 onlyrx_default = json.dumps({
90 90 "up": False,
91 91 "down": False
92 92 })
93 93
94 94 def up_convertion(cadena):
95 95 valores = []
96 96 for c in cadena:
97 97 if c == 1.0: valores=valores+['000']
98 98 if c == 2.0: valores=valores+['001']
99 99 if c == 3.0: valores=valores+['010']
100 100 if c == 0.0: valores=valores+['011']
101 101 if c == 0.5: valores=valores+['100']
102 102 if c == 1.5: valores=valores+['101']
103 103 if c == 2.5: valores=valores+['110']
104 104 if c == 3.5: valores=valores+['111']
105 105
106 106 return valores
107 107
108 108 def up_conv_bits(value):
109 109
110 110 if value == 1.0: bits="000"
111 111 if value == 2.0: bits="001"
112 112 if value == 3.0: bits="010"
113 113 if value == 0.0: bits="011"
114 114 if value == 0.5: bits="100"
115 115 if value == 1.5: bits="101"
116 116 if value == 2.5: bits="110"
117 117 if value == 3.5: bits="111"
118 118
119 119 return bits
120 120
121 121 def down_convertion(cadena):
122 122 valores = []
123 123 for c in cadena:
124 124 if c == 1.0: valores=valores+['000']
125 125 if c == 2.0: valores=valores+['001']
126 126 if c == 3.0: valores=valores+['010']
127 127 if c == 0.0: valores=valores+['011']
128 128 if c == 0.5: valores=valores+['100']
129 129 if c == 1.5: valores=valores+['101']
130 130 if c == 2.5: valores=valores+['110']
131 131 if c == 3.5: valores=valores+['111']
132 132
133 133 return valores
134 134
135 135 def down_conv_bits(value):
136 136
137 137 if value == 1.0: bits="000"
138 138 if value == 2.0: bits="001"
139 139 if value == 3.0: bits="010"
140 140 if value == 0.0: bits="011"
141 141 if value == 0.5: bits="100"
142 142 if value == 1.5: bits="101"
143 143 if value == 2.5: bits="110"
144 144 if value == 3.5: bits="111"
145 145
146 146 return bits
147 147
148 148 def ip2position(module_number):
149 149 j=0
150 150 i=0
151 151 for x in range(0,module_number-1):
152 152 j=j+1
153 153 if j==8:
154 154 i=i+1
155 155 j=0
156 156
157 157 pos = [i,j]
158 158 return pos
159 159
160 160
161 def fromBinary2Char(binary_string):
162 number = int(binary_string, 2)
163 #Plus 33 to avoid more than 1 characters values such as: '\x01'-'\x1f'
164 number = number + 33
165 char = chr(number)
166 return char
167
168 def fromChar2Binary(char):
169 number = ord(char) - 33
170 #Minus 33 to get the real value
171 bits = bin(number)[2:]
172 #To ensure we have a string with 6bits
173 if len(bits) < 6:
174 bits = bits.zfill(6)
175 return bits
176
177
161 178 def change_beam_for_multiprocessing(module):
162 179
163 180 for i in range (1,50):
164 181 beam_pos = 0
165 182 module_address = ('192.168.1.'+str(module), 5500)
166 183 header = 'JROABSCeCnModCnMod0100000'
167 184 numbers = len(str(beam_pos))
168 185 function = 'CHGB'
169 186
170 187 message_tx = header+str(numbers)+function+str(beam_pos)+'0'
171 188
172 189 # Create the datagram socket
173 190 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
174 191 sock.connect(module_address)
175 192
176 193 sock.send(message_tx)
177 194 #t = sock.recv(1024)
178 195 sock.close()
179 196 sock = None
180 197
181 198
182 199 time.sleep(0.2)
183 200
184 201
185 202 beam_pos = 1
186 203 numbers = len(str(beam_pos))
187 204
188 205 message_tx = header+str(numbers)+function+str(beam_pos)+'0'
189 206
190 207 # Create the datagram socket
191 208 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
192 209 sock.connect(module_address)
193 210 sock.send(message_tx)
194 211 sock.close()
195 212 sock = None
196 213
197 214 time.sleep(0.2)
198 215
199 216
200 217
201 218 class ABSConfiguration(Configuration):
202 219 beams = models.CharField(verbose_name='Beams', max_length=20000, default="{}")
203 220 module_status = models.CharField(verbose_name='Module Status', max_length=10000, default=json.dumps(status_default))
204 221
205 222 class Meta:
206 223 db_table = 'abs_configurations'
207 224
208 225 def get_absolute_url_plot(self):
209 226 return reverse('url_plot_abs_patterns', args=[str(self.id)])
210 227
211 228
212 229 def parms_to_dict(self):
213 230
214 231 parameters = {}
215 232
216 233 parameters['device_id'] = self.device.id
217 234 parameters['name'] = self.name
218 235 parameters['beams'] = {}
219 236
220 237 beams = ast.literal_eval(self.beams)
221 238 b=1
222 239 for beam in beams:
223 240 absbeam = ABSBeam.objects.get(pk=beams[beam])
224 241 parameters['beams']['beam'+str(b)] = absbeam.parms_to_dict()
225 242 b+=1
226 243
227 244 return parameters
228 245
246 def get_beams(self, **kwargs):
247 '''
248 This function returns ABS Configuration beams
249 '''
250 return ABSBeam.objects.filter(abs_conf=self.pk, **kwargs)
251
252 def clone(self, **kwargs):
253
254 beams = self.get_beams()
255 self.pk = None
256 self.id = None
257 for attr, value in kwargs.items():
258 setattr(self, attr, value)
259 self.save()
260
261 for beam in beams:
262 beam.clone(abs_conf=self)
263
264 return self
265
229 266
230 267 def module_conf(self, module_num, beams):
231 268 """
232 269 This function creates beam configurations for one abs module.
233 270 """
234 271 ip_address = self.device.ip_address
235 272 ip_address = ip_address.split('.')
236 273 module_seq = (ip_address[0],ip_address[1],ip_address[2])
237 274 dot = '.'
238 275 module_ip = dot.join(module_seq)+'.'+str(module_num)
239 276 module_port = self.device.port_address
240 277 write_route = 'http://'+module_ip+':'+str(module_port)+'/configure'
241 278
242 279 header = 'JROABSCeCnModCnMod01000108SNDFexperimento1.ab1'
243 280 module = 'ABS_'+str(module_num)
244 bs = {}
281 bs = '' #{}
245 282 i=1
246 283 #beams = {1: '001000', 2: '010001', 3: '010010', 4: '000011', 5: '101100', 6: '101101',
247 284 # 7: '110110', 8: '111111', 9: '000000', 10: '001001', 11: '010010', 12: '011011'}
248 285 for beam in beams:
249 bs[i] = beam.module_6bits(module_num)
286 #bs[i] = fromBinary2Char(beam.module_6bits(module_num))
287 bs = bs + fromBinary2Char(beam.module_6bits(module_num))
250 288 i=i+1
251 289
252 290 beams = bs
253 291
254 292 parameters = {}
255 293 parameters['header'] = header
256 294 parameters['module'] = module
257 parameters['beams'] = json.dumps(beams)
258
295 parameters['beams'] = beams #json.dumps(beams)
296 print parameters['beams']
259 297 answer = ''
260 298
261 299 try:
262 300 r_write = requests.post(write_route, parameters, timeout=0.5)
263 301 answer = r_write.json()
264 302 self.message = answer['message']
265 303 except:
266 304 self.message = "Could not write ABS parameters"
267 305 return 0
268 306 return 1
269 307
270
271 308 def read_module(self, module):
272 309
273 310 """
274 311 Read out-bits (up-down) of 1 abs module NOT for Configuration
275 312 """
276 313
277 314 parameters = {}
278 315 ip_address = self.device.ip_address
279 316 ip_address = ip_address.split('.')
280 317 module_seq = (ip_address[0],ip_address[1],ip_address[2])
281 318 dot = '.'
282 319 module_ip = dot.join(module_seq)+'.'+str(module)
283 320 module_port = self.device.port_address
284 321 read_route = 'http://'+module_ip+':'+str(module_port)+'/read'
285 322
286 323 print(read_route)
287 324
288 325 answer = ''
289 326 module_bits = ''
290 327
291 328 try:
292 329 r_write = requests.get(read_route, timeout=0.7)
293 330 answer = r_write.json()
294 message = answer['message']
331 self.message = answer['message']
295 332 module_bits = answer['allbits']
296 333 except:
297 message = "Could not read ABS parameters"
334 #message = "Could not read ABS parameters"
298 335 return 0
299 336
300 337 return module_bits
301 338
302 339
303 340 def write_device(self):
304 341 """
305 342 This function sends the beams list to every abs module.
343 It needs 'module_conf' function
306 344 """
307 345
308 beams_list = ast.literal_eval(self.beams)
309 beams = []
310
311 for bl in range(1,len(beams_list)+1):
312 b = ABSBeam.objects.get(pk=beams_list['beam'+str(bl)])
313 beams.append(b)
346 ###beams_list = ast.literal_eval(self.beams)
347 ###beams = []
348 beams = ABSBeam.objects.filter(abs_conf=self)
349 ###for bl in range(1,len(beams_list)+1):
350 ### b = ABSBeam.objects.get(pk=beams_list['beam'+str(bl)])
351 ### beams.append(b)
314 352
315 353 #---Write each abs module---
316 beams_status = ast.literal_eval(self.module_status)
317 for i in range(62,65):
318 try:
319 self.module_conf(i, beams)
320 beams_status[str(i)] = 1
321 self.module_status = json.dumps(beams_status)
322 self.save()
323 #self.module_conf(63,beams)
324 #beams_status[str(63)] = 1
325 #self.module_status = json.dumps(beams_status)
326 except:
327 beams_status[str(i)] = 0
328 self.module_status = json.dumps(beams_status)
329 self.save()
330 #return 0
354 if beams:
355 beams_status = ast.literal_eval(self.module_status)
356 for i in range(62,65): #(62,65)
357 try:
358 answer = self.module_conf(i, beams)
359 beams_status[str(i)] = 1
360 self.module_status = json.dumps(beams_status)
361 self.save()
362 #self.module_conf(63,beams)
363 #beams_status[str(63)] = 1
364 #self.module_status = json.dumps(beams_status)
365 except:
366 beams_status[str(i)] = 0
367 self.module_status = json.dumps(beams_status)
368 self.save()
369 answer = 0
370 return 0
371 else:
372 self.message = "ABS Configuration does not have beams"
373 return 0
331 374
332 375 #self.device.status = 1
376 ##
377 if answer==1:
378 self.message = "ABS Beams List have been sent to ABS Modules"
379 else:
380 self.message = "Could not read ABS parameters"
381
382 ##
333 383 self.save()
334 384 return 1
335 385
336 386
337 387 def write_module(self, module):
338 388
339 389 """
340 390 Send configuration to one abs module
341 391 """
342 392
343 393 parameters = {}
344 394 ip_address = self.abs_conf.device.ip_address
345 395 ip_address = ip_address.split('.')
346 396 module_seq = (ip_address[0],ip_address[1],ip_address[2])
347 397 dot = '.'
348 398 module_ip = dot.join(module_seq)+'.'+str(module)
349 399 module_port = self.abs_conf.device.port_address
350 400 write_route = 'http://'+module_ip+':'+str(module_port)+'/configure'
351 401
352 402 #print write_route
353 403
354 404 header = 'JROABSCeCnModCnMod01000108SNDFexperimento1.ab1'
355 405 module = 'ABS_'+str(module)
356 406 beams = {1: '001000', 2: '010001', 3: '010010', 4: '000011', 5: '101100', 6: '101101',
357 407 7: '110110', 8: '111111', 9: '000000', 10: '001001', 11: '010010', 12: '011011'}
358 408
359 409 parameters['header'] = header
360 410 parameters['module'] = module
361 411 parameters['beams'] = json.dumps(beams)
362 412
363 413 answer = ''
364 414
365 415 try:
366 416 r_write = requests.post(write_route, parameters, timeout=0.5)
367 417 answer = r_write.json()
368 418 self.message = answer['message']
369 419 except:
370 420 self.message = "Could not write ABS parameters"
371 421 return 0
372 422
373 423
374 424 #self.device.status = int(answer['status'])
375 425
376 426 return 1
377 427
378 428
379 429 def beam_selector(self, module, beam_pos):
380 430 """
381 431 This function selects the beam number for one absmodule.
382 432 """
383 433
384 434 if beam_pos > 0:
385 435 beam_pos = beam_pos - 1
386 436 else:
387 437 beam_pos = 0
388 438
389 439 #El indice del apunte debe ser menor que el numero total de apuntes
390 440 #El servidor tcp en el embebido comienza a contar desde 0
391 441 beams_list = ast.literal_eval(self.beams)
392 442 if len(beams_list) < beam_pos:
393 443 return 0
394 444
395 445 flag = 1
396 446 if beam_pos>9:
397 447 flag = 2
398 448
399 449 module_address = ('192.168.1.'+str(module), 5500)
400 450 header = 'JROABSCeCnModCnMod0100000'
401 451 numbers = len(str(beam_pos))
402 452 function = 'CHGB'
403 453
404 454 message_tx = header+str(numbers)+function+str(beam_pos)+'0'
405 455
406 456 # Create the datagram socket
407 457 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
408 458 #sock.connect(module_address)
409 459 try:
410 460 sock.connect(module_address)
411 461 sock.send(message_tx)
412 462 sock.close()
413 463 print("Writing abs module:"+module_address[0]+"...")
414 464 except:
415 465 sock = None
416 466 print("Problem writing abs module:"+module_address[0])
417 467 return 0
418 468
419 469 return 1
420 470
421 471
422 472 def change_beam(self, beam_pos):
423 473 """
424 474 This function selects the beam number for all absmodules.
425 475 """
426 476 for i in range(1,65):
427 477 try:
428 478 self.beam_selector(i,beam_pos)
429 479 except:
430 480 print("Problem with module: 192.168.1."+str(i))
431 481 self.message = "Problem with module: 192.168.1."+str(i)
432 482 #return 0
433 483 return 1
434 484
435 485
436 486 def send_beam_num(self, beam_pos):
437 487 """
438 488 This function connects to a multicast group and sends the beam number
439 489 to all abs modules.
440 490 """
441 491
442 492 if beam_pos > 0:
443 493 beam_pos = beam_pos - 1
444 494 else:
445 495 beam_pos = 0
446 496
447 497 #El indice del apunte debe ser menor que el numero total de apuntes
448 498 #El servidor tcp en el embebido comienza a contar desde 0
449 499 beams_list = ast.literal_eval(self.beams)
450 500 if len(beams_list) < beam_pos:
451 501 return 0
452 502
453 503 flag = 1
454 504 if beam_pos>9:
455 505 flag = 2
456 506
457 507 header = 'JROABSCeCnModCnMod0100000'
458 508 flag = str(flag)
459 509 function = 'CHGB'
460 510 message_tx = header+flag+function+str(beam_pos)+'0'
461 511
462 512 multicast_group = '224.3.29.71'
463 513 server_address = ('',10000)
464 514
465 515 # Create the socket
466 516 sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
467 517 # Bind to the server address
468 518 sock.bind(server_address)
469 519 # Telling the OS add the socket to the multicast on all interfaces
470 520 group = socket.inet_aton(multicast_group)
471 521 mreq = struct.pack('4sL', group, socket.INADDR_ANY)
472 522 sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)
473 523
474 524 #print 'sending acknowledgement to all: \n' + message_tx
475 525 sock.sendto(message_tx, (multicast_group, 10000))
476 526 sock.close()
477 527 sock = None
478 528
479 529 return 1
480 530
481 531 def test1(self):
482 532 t1 = time.time()
483 533 t2 = 0
484 while (t2-t1)<300:
534 while (t2-t1)<100:#300
485 535 t2 = time.time()
486 self.send_beam_num(1)
487 time.sleep(0.04)
488 536 self.send_beam_num(2)
489 537 time.sleep(0.04)
538 self.send_beam_num(1)
539 time.sleep(0.04)
490 540 return
491 541
492 542 def change_procs_test1(self, module):
493 543
494 for i in range (1,300):
495 beam_pos = 0
544 for i in range (1,300):#300
545 beam_pos = 1
496 546 module_address = ('192.168.1.'+str(module), 5500)
497 547 header = 'JROABSCeCnModCnMod0100000'
498 548 numbers = len(str(beam_pos))
499 549 function = 'CHGB'
500 550
501 551 message_tx = header+str(numbers)+function+str(beam_pos)+'0'
502 552
503 553 # Create the datagram socket
504 554 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
505 555 sock.connect(module_address)
506 556
507 557 sock.send(message_tx)
508 558 #t = sock.recv(1024)
509 559 sock.close()
510 560 sock = None
511 561
512 562
513 time.sleep(0.2)
563 time.sleep(0.04)
514 564
515 565
516 beam_pos = 1
566 beam_pos = 0
517 567 numbers = len(str(beam_pos))
518 568
519 569 message_tx = header+str(numbers)+function+str(beam_pos)+'0'
520 570
521 571 # Create the datagram socket
522 572 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
523 573 sock.connect(module_address)
524 574 sock.send(message_tx)
525 575 sock.close()
526 576 sock = None
527 577
528 time.sleep(0.2)
578 time.sleep(0.04)
529 579
530 580
531 581 def multi_procs_test1(self):
532 582
583 """
584 This function sends the beam number to all abs modules using multiprocessing.
585 """
586
533 587 #if __name__ == "__main__":
534 588 size = 10000000 # Number of random numbers to add
535 procs = 65 # (Number-1) of processes to create
589 procs = 65 # (Number-1) of processes to create (absmodule)
536 590
537 591 # Create a list of jobs and then iterate through
538 592 # the number of processes appending each process to
539 593 # the job list
540 594 jobs = []
541 for i in range(62, procs):
595 for i in range(1, procs):
542 596
543 597 process = multiprocessing.Process(target=self.change_procs_test1,args=(i,))
544 598 jobs.append(process)
545 599 #print jobs
546 600
547 601 # Start the processes (i.e. calculate the random number lists)
548 602 for j in jobs:
549 603 #time.sleep(0.4)
550 604 #print j
551 605 j.start()
552 606
553 607 # Ensure all of the processes have finished
554 608 for j in jobs:
555 609 j.join()
556 610
557 611 print("List processing complete.")
558 612 return 1
559 613
560 614
615
616 def multi_procs_test2(self):
617 """
618 This function use multiprocessing python library. Importing Pool we can select
619 the number of cores we want to use
620 After 'nproc' linux command, we know how many cores computer has.
621 NOT WORKING
622 """
623 import multiprocessing
624 pool = multiprocessing.Pool(3) # cores
625
626 tasks = []
627 procs = 65
628 for i in range(62, procs):
629 tasks.append( (i,))
630 #print tasks
631 #pool.apply_async(self.change_procs_test1, 62)
632 results = [pool.apply( self.change_procs_test1, t ) for t in tasks]
633 #for result in results:
634 #result.get()
635 #(plotNum, plotFilename) = result.get()
636 #print("Result: plot %d written to %s" % (plotNum, plotFilename) )
637
638 return 1
639
640
641 def multi_procs_test3(self):
642 """
643 This function use multiprocessing python library. Importing Pool we can select
644 the number of cores we want to use
645 After 'nproc' linux command, we know how many cores computer has.
646 """
647 from multiprocessing import Pool
648 import time
649
650 def f(x):
651 return x*x
652
653 tasks = []
654 procs = 65
655 pool = Pool(processes=4)
656
657 #for i in range(62, procs):
658 #result = pool.map(f, range(62,65))
659 it = pool.imap(self.change_procs_test1, range(62,65))
660 #result.get(timeout=5)
661
662 return 1
663
664
665 def f(x):
666 print x
667 return
668
669 def multi_procs_test4(self):
670 import multiprocessing as mp
671
672
673 num_workers = mp.cpu_count()
674
675 pool = mp.Pool(num_workers)
676 procs = 65
677 for i in range(62, procs):
678 #for task in tasks:
679 pool.apply_async(self.f, args = (i,))
680
681 pool.close()
682 pool.join()
683
684 return 1
685
686
561 687 def status_device(self):
562 688
563 689 return 1
564 690
565 691
566 692
567 693 class ABSBeam(models.Model):
568 694
569 695 name = models.CharField(max_length=60, default='Beam')
570 696 antenna = models.CharField(verbose_name='Antenna', max_length=1000, default=antenna_default)
571 697 abs_conf = models.ForeignKey(ABSConfiguration, null=True, verbose_name='ABS Configuration')
572 698 tx = models.CharField(verbose_name='Tx', max_length=1000, default=tx_default)
573 699 rx = models.CharField(verbose_name='Rx', max_length=1000, default=rx_default)
574 700 s_time = models.TimeField(verbose_name='Star Time', default='00:00:00')
575 701 e_time = models.TimeField(verbose_name='End Time', default='23:59:59')
576 702 modules_conf = models.CharField(verbose_name='Modules', max_length=2000, default=json.dumps(conf_default))
577 703 ues = models.CharField(verbose_name='Ues', max_length=100, default=ues_default)
578 704 only_rx = models.CharField(verbose_name='Only RX', max_length=40, default=onlyrx_default)
579 705
580 706 class Meta:
581 707 db_table = 'abs_beams'
582 708
583 709 def __unicode__(self):
584 710 return u'%s' % (self.name)
585 711
586 712 def parms_to_dict(self):
587 713
588 714 #Update data
589 715 self.modules_6bits()
590 716
591 717 parameters = {}
592 718
593 719 parameters['name'] = self.name
594 720 parameters['antenna'] = ast.literal_eval(self.antenna)
595 721 parameters['abs_conf'] = self.abs_conf.name
596 722 parameters['tx'] = ast.literal_eval(self.tx)
597 723 parameters['rx'] = ast.literal_eval(self.rx)
598 724 parameters['s_time'] = self.s_time.strftime("%H:%M:%S")
599 725 parameters['e_time'] = self.e_time.strftime("%H:%M:%S")
600 726 parameters['configuration'] = ast.literal_eval(self.modules_conf)
601 727 parameters['ues'] = ast.literal_eval(self.ues)
602 728 parameters['only_rx'] = json.loads(self.only_rx)
603 729
604 730 return parameters
605 731
606 732 def dict_to_parms(self, parameters):
607 733
608 734 self.name = parameters['name']
609 735 self.antenna = json.dumps(parameters['antenna'])
610 736 #self.abs_conf = parameters['abs_conf']
611 737 self.tx = json.dumps(parameters['tx'])
612 738 self.rx = json.dumps(parameters['rx'])
613 739 #parameters['s_time']
614 740 #parameters['e_time']
615 741 self.ues = json.dumps(parameters['ues'])
616 742 self.only_rx = json.dumps(parameters['only_rx'])
617 743
618 744 self.modules_6bits()
619 745 self.save()
620 746
621 747 return parameters
622 748
749 def clone(self, **kwargs):
750
751 self.pk = None
752 self.id = None
753 for attr, value in kwargs.items():
754 setattr(self, attr, value)
755
756 self.save()
757
758 return self
759
623 760
624 761 def change_beam(self, beam_pos=0):
625 762
626 763 module_63 = ('192.168.1.63', 5500)
627 764 header = 'JROABSCeCnModCnMod0100000'
628 765 numbers = len(str(beam_pos))
629 766 function = 'CHGB'
630 767
631 768 message_tx = header+str(numbers)+function+str(beam_pos)+'0'
632 769
633 770 # Create the datagram socket
634 771 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
635 772 sock.connect(module_63)
636 773 sock.send(message_tx)
637 774 sock.close()
638 775 return message_tx
639 776
640 777 def change_module_beam(self, module=61,beam_pos=0):
641 778
642 779 module_address = ('192.168.1.'+str(module), 5500)
643 780 header = 'JROABSCeCnModCnMod0100000'
644 781 numbers = len(str(beam_pos))
645 782 function = 'CHGB'
646 783
647 784 message_tx = header+str(numbers)+function+str(beam_pos)+'0'
648 785
649 786 # Create the datagram socket
650 787 try:
651 788 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
652 789 sock.connect(module_address)
653 790 sock.send(message_tx)
654 791 sock.close()
655 792 except:
656 793 return 0
657 794 return message_tx
658 795
659 796 def write_device(self):
660 797
661 798 parameters = {}
662 799
663 800 module_ip = '192.168.1.63'
664 801 write_route = 'http://192.168.1.63:8080/configure'
665 802
666 803 header = 'JROABSCeCnModCnMod01000108SNDFexperimento1.ab1'
667 804 module = 'ABS_63'
668 805 beams = {1: '001000', 2: '010001', 3: '010010', 4: '000011', 5: '101100', 6: '101101',
669 806 7: '110110', 8: '111111', 9: '000000', 10: '001001', 11: '010010', 12: '011011'}
670 807
671 808 parameters['header'] = header
672 809 parameters['module'] = module
673 810 parameters['beams'] = json.dumps(beams)
674 811
675 812 answer = ''
676 813
677 814 try:
678 815 r_write = requests.post(write_route, parameters, timeout=0.5)
679 816 answer = r_write.json()
680 817 self.message = answer['message']
681 818 except:
682 819 self.message = "Could not write ABS parameters"
683 820 return 0
684 821
685 822
686 823 #self.device.status = int(answer['status'])
687 824
688 825 return 1
689 826
690 827
691 828
692 829 def module_6bits(self, module):
693 830 """
694 831 This function reads antenna pattern and choose 6bits (upbits-downbits) for one abs module
695 832 """
696 833 if module > 64:
697 834 beam_bits = ""
698 835 return beam_bits
699 836
700 837 data = ast.literal_eval(self.antenna)
701 838 up_data = data['antenna_up']
702 839 down_data = data['antenna_down']
703 840
704 841 pos = ip2position(module)
705 842 up_value = up_data[pos[0]][pos[1]]
706 843 down_value = down_data[pos[0]][pos[1]]
707 844
708 845 up_bits = up_conv_bits(up_value)
709 846 down_bits = down_conv_bits(down_value)
710 847 beam_bits = up_bits+down_bits
711 848
712 849 return beam_bits
713 850
714 851 def modules_6bits(self):
715 852 """
716 853 This function returns 6bits from every abs module (1-64) in a dict
717 854 """
718 855 modules_configuration = ast.literal_eval(self.modules_conf)
719 856
720 857 for i in range(1,65):
721 858 modules_configuration[str(i)] = self.module_6bits(i)
722 859
723 860 self.modules_conf = json.dumps(modules_configuration)
724 861 self.save()
725 862
726 863 return self.modules_conf
727 864
728 865 def add_beam2list(self):
729 866 """
730 867 This function adds a beam to the beams list of ABS Configuration.
731 868 """
732 869 beams = ast.literal_eval(self.abs_conf.beams)
733 870 if any(beams):
734 871 for beam in beams:
735 872 if beams[beam] == self.id:
736 873 return
737 874 i = len(beams)+1
738 875 beams['beam'+str(i)] = self.id
739 876 else:
740 877 beams['beam1'] = self.id
741 878
742 879 self.abs_conf.beams = json.dumps(beams)
743 880 self.abs_conf.save()
744 881
745 882 return
746 883
747 884 def remove_beamfromlist(self):
748 885 """
749 886 This function removes current beam from the beams list of ABS Configuration.
750 887 """
751 888 beams = ast.literal_eval(self.abs_conf.beams)
752 889 dict_position = ''
753 890
754 891 if any(beams):
755 892 for beam in beams:
756 893 if beams[beam] == self.id:
757 894 dict_position = beam
758 895 if dict_position != '':
759 896 beams.pop(str(dict_position),None)
760 897 else:
761 898 return
762 899
763 900 self.abs_conf.beams = json.dumps(beams)
764 901 self.abs_conf.save()
765 902
766 903 return
767 904
768 905 @property
769 906 def get_upvalues(self):
770 907 """
771 908 This function reads antenna pattern and show the up-value of one abs module
772 909 """
773 910
774 911 data = ast.literal_eval(self.antenna)
775 912 up_data = data['antenna_up']
776 913
777 914 up_values = []
778 915 for data in up_data:
779 916 for i in range(0,8):
780 917 up_values.append(data[i])
781 918
782 919 return up_values
783 920
784 921 @property
785 922 def antenna_upvalues(self):
786 923 """
787 924 This function reads antenna pattern and show the up - values of one abs beam
788 925 in a particular order
789 926 """
790 927 data = ast.literal_eval(self.antenna)
791 928 up_data = data['antenna_up']
792 929
793 930 return up_data
794 931
795 932 @property
796 933 def antenna_downvalues(self):
797 934 """
798 935 This function reads antenna pattern and show the down - values of one abs beam
799 936 in a particular order
800 937 """
801 938 data = ast.literal_eval(self.antenna)
802 939 down_data = data['antenna_down']
803 940
804 941 return down_data
805 942
806 943 @property
807 944 def get_downvalues(self):
808 945 """
809 946 This function reads antenna pattern and show the down-value of one abs module
810 947 """
811 948
812 949 data = ast.literal_eval(self.antenna)
813 950 down_data = data['antenna_down']
814 951
815 952 down_values = []
816 953 for data in down_data:
817 954 for i in range(0,8):
818 955 down_values.append(data[i])
819 956
820 957 return down_values
821 958
822 959 @property
823 960 def get_up_ues(self):
824 961 """
825 962 This function shows the up-ues-value of one beam
826 963 """
827 964 data = ast.literal_eval(self.ues)
828 965 up_ues = data['up']
829 966
830 967 return up_ues
831 968
832 969 @property
833 970 def get_down_ues(self):
834 971 """
835 972 This function shows the down-ues-value of one beam
836 973 """
837 974 data = ast.literal_eval(self.ues)
838 975 down_ues = data['down']
839 976
840 977 return down_ues
841 978
842 979 @property
843 980 def get_up_onlyrx(self):
844 981 """
845 982 This function shows the up-onlyrx-value of one beam
846 983 """
847 984 data = json.loads(self.only_rx)
848 985 up_onlyrx = data['up']
849 986
850 987 return up_onlyrx
851 988
852 989 @property
853 990 def get_down_onlyrx(self):
854 991 """
855 992 This function shows the down-onlyrx-value of one beam
856 993 """
857 994 data = json.loads(self.only_rx)
858 995 down_onlyrx = data['down']
859 996
860 997 return down_onlyrx
861 998
862 999 @property
863 1000 def get_tx(self):
864 1001 """
865 1002 This function shows the tx-values of one beam
866 1003 """
867 1004 data = json.loads(self.tx)
868 1005
869 1006 return data
870 1007
871 1008 @property
872 1009 def get_uptx(self):
873 1010 """
874 1011 This function shows the up-tx-values of one beam
875 1012 """
876 1013 data = json.loads(self.tx)
877 1014 up_data = data['up']
878 1015
879 1016 up_values = []
880 1017 for data in up_data:
881 1018 for i in range(0,8):
882 1019 up_values.append(data[i])
883 1020
884 1021 return up_values
885 1022
886 1023 @property
887 1024 def get_downtx(self):
888 1025 """
889 1026 This function shows the down-tx-values of one beam
890 1027 """
891 1028 data = json.loads(self.tx)
892 1029 down_data = data['down']
893 1030
894 1031 down_values = []
895 1032 for data in down_data:
896 1033 for i in range(0,8):
897 1034 down_values.append(data[i])
898 1035
899 1036 return down_values
900 1037
901 1038
902 1039
903 1040 @property
904 1041 def get_rx(self):
905 1042 """
906 1043 This function shows the rx-values of one beam
907 1044 """
908 1045 data = json.loads(self.rx)
909 1046
910 1047 return data
911 1048
912 1049 @property
913 1050 def get_uprx(self):
914 1051 """
915 1052 This function shows the up-rx-values of one beam
916 1053 """
917 1054 data = json.loads(self.rx)
918 1055 up_data = data['up']
919 1056
920 1057 up_values = []
921 1058 for data in up_data:
922 1059 for i in range(0,8):
923 1060 up_values.append(data[i])
924 1061
925 1062 return up_values
926 1063
927 1064 @property
928 1065 def get_downrx(self):
929 1066 """
930 1067 This function shows the down-rx-values of one beam
931 1068 """
932 1069 data = json.loads(self.rx)
933 1070 down_data = data['down']
934 1071
935 1072 down_values = []
936 1073 for data in down_data:
937 1074 for i in range(0,8):
938 1075 down_values.append(data[i])
939 1076
940 1077 return down_values
@@ -1,462 +1,462
1 1 {% extends "dev_conf.html" %}
2 2
3 3 {% block extra-menu-actions %}
4 4 <li><a href="{{ dev_conf.get_absolute_url_plot }}" target="_blank"><span class="glyphicon glyphicon-picture" aria-hidden="true"></span> View Patterns </a></li>
5 <li><a href="{{ dev_conf.get_absolute_url_write }}"><span class="glyphicon glyphicon-download" aria-hidden="true"></span> Write</a></li>
5 <!--<li><a href="{{ dev_conf.get_absolute_url_write }}"><span class="glyphicon glyphicon-download" aria-hidden="true"></span> Write</a></li>-->
6 6 {% endblock %}
7 7
8 8 {% block extra-content %}
9 9 <style>
10 10
11 11 .abs {
12 12 border: 2px solid #00334d;
13 13 vertical-align: center;
14 14 display: inline-block;
15 15 }
16 16 .abs tr:nth-child(1){
17 17 border-bottom: 1px dashed #00334d;
18 18 }
19 19 .abs tr{
20 20 border-bottom: 0px solid #00334d;
21 21 }
22 22 .abs td {
23 23 border-right: 1px dashed #00334d;
24 24 text-align: center;
25 25 padding: 5px;
26 26 }
27 27
28 28
29 29 .legend {
30 30 margin-left: 15px;
31 31 display: inline-block;
32 32 border: 2px solid #00334d;
33 33 vertical-align: top;
34 34 }
35 35 .legend th{
36 36 border-bottom: 1px dashed #00334d;
37 37 font-weight: bold;
38 38 vertical-align: center;
39 39 text-align: center;
40 40 }
41 41 .legend td {
42 42 padding: 2px;
43 43 text-align: center;
44 44 }
45 45
46 46
47 47 .north {
48 48 border: 2px solid #00334d;
49 49 vertical-align: center;
50 50 font-weight: bold;
51 51 }
52 52 .north tr{
53 53 border: 1px solid #ffffff;
54 54 background-color: #FF0000;
55 55 }
56 56 .north td{
57 57 border: 2px solid #e2e2e7;
58 58 text-align: center;
59 59 padding: 1px 15px 1px 15px;
60 60 }
61 61 .north tr:nth-child(even) td:nth-child(n){
62 62 border-bottom: 12px solid #e2e2e7;
63 63 }
64 64 .north td:nth-child(n) {
65 65 border-right: 12px solid #e2e2e7;
66 66 }
67 67 .north td:nth-last-child(4n+1) {
68 68 border-right: 2px solid #e2e2e7;
69 69 }
70 70 .north tr:nth-last-child(1) td:nth-child(n){
71 71 border-bottom: 3px solid #e2e2e7;
72 72 }
73 73
74 74 .north tr:nth-child(2) td:nth-child(2){
75 75 background-color: #00cc00;
76 76 }
77 77
78 78 .north tr:nth-child(2) td:nth-child(4){
79 79 background-color: #ee902c;
80 80 }
81 81
82 82
83 83
84 84 .east {
85 85 border: 2px solid #00334d;
86 86 vertical-align: center;
87 87 font-weight: bold;
88 88 }
89 89 .east tr{
90 90 border: 1px solid #ffffff;
91 91 background-color: #FF0000;
92 92 }
93 93 .east td{
94 94 border: 2px solid #e2e2e7;
95 95 text-align: center;
96 96 padding: 1px 15px 1px 15px;
97 97 }
98 98 .east tr:nth-child(even) td:nth-child(n){
99 99 border-bottom: 12px solid #e2e2e7;
100 100 }
101 101 .east td:nth-child(n) {
102 102 border-right: 12px solid #e2e2e7;
103 103 }
104 104 .east td:nth-last-child(4n+1) {
105 105 border-right: 2px solid #e2e2e7;
106 106 }
107 107 .east tr:nth-last-child(1) td:nth-child(n){
108 108 border-bottom: 3px solid #e2e2e7;
109 109 }
110 110
111 111 .east tr:nth-child(2) td:nth-child(2){
112 112 background-color: #00cc00;
113 113 }
114 114
115 115 .east tr:nth-child(2) td:nth-child(4){
116 116 background-color: #ee902c;
117 117 }
118 118
119 119
120 120 .west {
121 121 border: 2px solid #00334d;
122 122 vertical-align: center;
123 123 font-weight: bold;
124 124 }
125 125 .west tr{
126 126 border: 1px solid #ffffff;
127 127 background-color: #FF0000;
128 128 }
129 129 .west td{
130 130 border: 2px solid #e2e2e7;
131 131 text-align: center;
132 132 padding: 1px 15px 1px 15px;
133 133 }
134 134 .west tr:nth-child(even) td:nth-child(n){
135 135 border-bottom: 12px solid #e2e2e7;
136 136 }
137 137 .west td:nth-child(n) {
138 138 border-right: 12px solid #e2e2e7;
139 139 }
140 140 .west td:nth-last-child(4n+1) {
141 141 border-right: 2px solid #e2e2e7;
142 142 }
143 143 .west tr:nth-last-child(1) td:nth-child(n){
144 144 border-bottom: 3px solid #e2e2e7;
145 145 }
146 146
147 147 .west tr:nth-child(2) td:nth-child(2){
148 148 background-color: #00cc00;
149 149 }
150 150
151 151 .west tr:nth-child(2) td:nth-child(4){
152 152 background-color: #ee902c;
153 153 }
154 154
155 155
156 156 .south {
157 157 border: 2px solid #00334d;
158 158 vertical-align: center;
159 159 font-weight: bold;
160 160 }
161 161 .south tr{
162 162 border: 1px solid #ffffff;
163 163 background-color: #FF0000;
164 164 }
165 165 .south td{
166 166 border: 2px solid #e2e2e7;
167 167 text-align: center;
168 168 padding: 1px 15px 1px 15px;
169 169 }
170 170 .south tr:nth-child(even) td:nth-child(n){
171 171 border-bottom: 12px solid #e2e2e7;
172 172 }
173 173 .south td:nth-child(n) {
174 174 border-right: 12px solid #e2e2e7;
175 175 }
176 176 .south td:nth-last-child(4n+1) {
177 177 border-right: 2px solid #e2e2e7;
178 178 }
179 179 .south tr:nth-last-child(1) td:nth-child(n){
180 180 border-bottom: 3px solid #e2e2e7;
181 181 }
182 182
183 183 .south tr:nth-child(2) td:nth-child(2){
184 184 background-color: #00cc00;
185 185 }
186 186
187 187 .south tr:nth-child(2) td:nth-child(4){
188 188 background-color: #ee902c;
189 189 }
190 190
191 191
192 192
193 193 </style>
194 194
195 195 <h4>Beams:</h4>
196 {% if beams_id %}
196 {% if beams %}
197 197
198 198 <div class="container">
199 199 <ul class="nav nav-pills">
200 200
201 201 {% for beam in beams %}
202 202 <li {% if forloop.counter == 1 %} class="active" {% endif %}>
203 203 <a data-toggle="pill" id="button-{{ forloop.counter }}" href="#">{{ forloop.counter }}</a>
204 204 </li>
205 205 {% endfor %}
206 206
207 207 </ul>
208 208 </div>
209 209
210 210
211 211 <script>
212 212 $(document).ready(function() {
213 213
214 214 {% for beam in beams %}
215 215 $( "#button-{{ forloop.counter }}" ).click(function() {
216 216 //$(this).addClass('active');
217 217
218 218 var beam_upvalues = {{beam.get_upvalues}};
219 219 var beam_downvalues = {{beam.get_downvalues}};
220 220 //alert(beam_upvalues)
221 221 var table = document.getElementById('abs_pattern');
222 222 var cells = table.getElementsByTagName('td');
223 223 //alert(cells[99].textContent);
224 224
225 225 for (var i = 1, len = 30; i < len; i++) {
226 226 if ((i > 24) && (i<29)){
227 227 cells[i].innerHTML = beam_upvalues[i-1].toFixed(1);
228 228 cells[i+4].innerHTML = beam_downvalues[i-1].toFixed(1);
229 229 }
230 230 else if ((i > 16) && (i<21)){
231 231 cells[i].innerHTML = beam_upvalues[i-1].toFixed(1);
232 232 cells[i+4].innerHTML = beam_downvalues[i-1].toFixed(1);
233 233 }
234 234 else if ((i > 8) && (i<13)){
235 235 cells[i].innerHTML = beam_upvalues[i-1].toFixed(1);
236 236 cells[i+4].innerHTML = beam_downvalues[i-1].toFixed(1);
237 237 }
238 238 else if (i < 5) {
239 239 cells[i].innerHTML = beam_upvalues[i-1].toFixed(1);
240 240 cells[i+4].innerHTML = beam_downvalues[i-1].toFixed(1);
241 241 }
242 242 }
243 243
244 244 for (var i = 34, len = 63; i < len; i++) {
245 245 if ((i > 57) && (i<62)) {
246 246 cells[i].innerHTML = beam_upvalues[i-30].toFixed(1);
247 247 cells[i+4].innerHTML = beam_downvalues[i-30].toFixed(1);
248 248 }
249 249 if ((i > 49) && (i<54)) {
250 250 cells[i].innerHTML = beam_upvalues[i-30].toFixed(1);
251 251 cells[i+4].innerHTML = beam_downvalues[i-30].toFixed(1);
252 252 }
253 253 else if ((i > 41) && (i<46)) {
254 254 cells[i].innerHTML = beam_upvalues[i-30].toFixed(1);
255 255 cells[i+4].innerHTML = beam_downvalues[i-30].toFixed(1);
256 256 }
257 257 else if (i < 38) {
258 258 cells[i].innerHTML = beam_upvalues[i-30].toFixed(1);
259 259 cells[i+4].innerHTML = beam_downvalues[i-30].toFixed(1);
260 260 }
261 261 }
262 262
263 263 for (var i = 67, len = 96; i < len; i++) {
264 264 if ((i > 90) && (i<95)) {
265 265 cells[i].innerHTML = beam_upvalues[i-35].toFixed(1);
266 266 cells[i+4].innerHTML = beam_downvalues[i-35].toFixed(1);
267 267 }
268 268 else if ((i > 82) && (i<87)) {
269 269 cells[i].innerHTML = beam_upvalues[i-35].toFixed(1);
270 270 cells[i+4].innerHTML = beam_downvalues[i-35].toFixed(1);
271 271 }
272 272 else if ((i > 74) && (i<79)) {
273 273 cells[i].innerHTML = beam_upvalues[i-35].toFixed(1);
274 274 cells[i+4].innerHTML = beam_downvalues[i-35].toFixed(1);
275 275 }
276 276 else if (i < 71) {
277 277 cells[i].innerHTML = beam_upvalues[i-35].toFixed(1);
278 278 cells[i+4].innerHTML = beam_downvalues[i-35].toFixed(1);
279 279 }
280 280 }
281 281
282 282 for (var i = 100, len = 129; i < len; i++) {
283 283 if ((i > 123) && (i<128)) {
284 284 cells[i].innerHTML = beam_upvalues[i-64].toFixed(1);
285 285 cells[i+4].innerHTML = beam_downvalues[i-64].toFixed(1);
286 286 }
287 287 else if ((i > 115) && (i<120)) {
288 288 cells[i].innerHTML = beam_upvalues[i-64].toFixed(1);
289 289 cells[i+4].innerHTML = beam_downvalues[i-64].toFixed(1);
290 290 }
291 291 else if ((i > 107) && (i<112)) {
292 292 cells[i].innerHTML = beam_upvalues[i-64].toFixed(1);
293 293 cells[i+4].innerHTML = beam_downvalues[i-64].toFixed(1);
294 294 }
295 295 else if (i < 104) {
296 296 cells[i].innerHTML = beam_upvalues[i-64].toFixed(1);
297 297 cells[i+4].innerHTML = beam_downvalues[i-64].toFixed(1);
298 298 }
299 299 }
300 300
301 301 //$('#button-1').addClass("active");
302 302
303 303 });
304 304
305 305 {% endfor %}
306 306
307 307
308 308
309 309
310 310 //})
311 311
312 312 //function ChangeColor() {
313 313 // document.getElementById("button_1").style.backgroundColor = "#2c3e50";
314 314 // document.getElementById("button_1").style.color = "#ecf0f1";
315 315 //}
316 316 });
317 317 </script>
318 318
319 319
320 320
321 321 <br>
322 322
323 323 <table id="abs_pattern" class="abs">
324 324 <tr>
325 325 <td> <b>North Quarter</b>
326 326 <table class="north ">
327 327 <tr>
328 328 <td>{{beams.0.get_upvalues.0}}</td> <td>{{beams.0.get_upvalues.1}}</td> <td>{{beams.0.get_upvalues.2}}</td> <td>{{beams.0.get_upvalues.3}}</td>
329 329 </tr>
330 330 <tr>
331 331 <td>{{beams.0.get_downvalues.0}}</td> <td>{{beams.0.get_downvalues.1}}</td> <td>{{beams.0.get_downvalues.2}}</td> <td>{{beams.0.get_downvalues.3}}</td>
332 332 </tr>
333 333 <tr>
334 334 <td>{{beams.0.get_upvalues.8}}</td> <td>{{beams.0.get_upvalues.9}}</td> <td>{{beams.0.get_upvalues.10}}</td> <td>{{beams.0.get_upvalues.11}}</td>
335 335 </tr>
336 336 <tr>
337 337 <td>{{beams.0.get_downvalues.8}}</td> <td>{{beams.0.get_downvalues.9}}</td> <td>{{beams.0.get_downvalues.10}}</td> <td>{{beams.0.get_downvalues.11}}</td>
338 338 </tr>
339 339 <tr>
340 340 <td>{{beams.0.get_upvalues.16}}</td> <td>{{beams.0.get_upvalues.17}}</td> <td>{{beams.0.get_upvalues.18}}</td> <td>{{beams.0.get_upvalues.19}}</td>
341 341 </tr>
342 342 <tr>
343 343 <td>{{beams.0.get_downvalues.16}}</td> <td>{{beams.0.get_downvalues.17}}</td> <td>{{beams.0.get_downvalues.18}}</td> <td>{{beams.0.get_downvalues.19}}</td>
344 344 </tr>
345 345 <tr>
346 346 <td>{{beams.0.get_upvalues.24}}</td> <td>{{beams.0.get_upvalues.25}}</td> <td>{{beams.0.get_upvalues.26}}</td> <td>{{beams.0.get_upvalues.27}}</td>
347 347 </tr>
348 348 <tr>
349 349 <td>{{beams.0.get_downvalues.24}}</td> <td>{{beams.0.get_downvalues.25}}</td> <td>{{beams.0.get_downvalues.26}}</td> <td>{{beams.0.get_downvalues.27}}</td>
350 350 </tr>
351 351 </table>
352 352 </td>
353 353 <td> <b>East Quarter</b>
354 354 <table class="east ">
355 355 <tr>
356 356 <td>{{beams.0.get_upvalues.4}}</td> <td>{{beams.0.get_upvalues.5}}</td> <td>{{beams.0.get_upvalues.6}}</td> <td>{{beams.0.get_upvalues.7}}</td>
357 357 </tr>
358 358 <tr>
359 359 <td>{{beams.0.get_downvalues.4}}</td> <td>{{beams.0.get_downvalues.5}}</td> <td>{{beams.0.get_downvalues.6}}</td> <td>{{beams.0.get_downvalues.7}}</td>
360 360 </tr>
361 361 <tr>
362 362 <td>{{beams.0.get_upvalues.12}}</td> <td>{{beams.0.get_upvalues.13}}</td> <td>{{beams.0.get_upvalues.14}}</td> <td>{{beams.0.get_upvalues.15}}</td>
363 363 </tr>
364 364 <tr>
365 365 <td>{{beams.0.get_downvalues.12}}</td> <td>{{beams.0.get_downvalues.13}}</td> <td>{{beams.0.get_downvalues.14}}</td> <td>{{beams.0.get_downvalues.15}}</td>
366 366 </tr>
367 367 <tr>
368 368 <td>{{beams.0.get_upvalues.20}}</td> <td>{{beams.0.get_upvalues.21}}</td> <td>{{beams.0.get_upvalues.22}}</td> <td>{{beams.0.get_upvalues.23}}</td>
369 369 </tr>
370 370 <tr>
371 371 <td>{{beams.0.get_downvalues.20}}</td> <td>{{beams.0.get_downvalues.21}}</td> <td>{{beams.0.get_downvalues.22}}</td> <td>{{beams.0.get_downvalues.23}}</td>
372 372 </tr>
373 373 <tr>
374 374 <td>{{beams.0.get_upvalues.28}}</td> <td>{{beams.0.get_upvalues.29}}</td> <td>{{beams.0.get_upvalues.30}}</td> <td>{{beams.0.get_upvalues.31}}</td>
375 375 </tr>
376 376 <tr>
377 377 <td>{{beams.0.get_downvalues.28}}</td> <td>{{beams.0.get_downvalues.29}}</td> <td>{{beams.0.get_downvalues.30}}</td> <td>{{beams.0.get_downvalues.31}}</td>
378 378 </tr>
379 379 </table>
380 380 </td>
381 381 </tr>
382 382 <tr>
383 383 <td> <b>West Quarter</b>
384 384 <table class="west ">
385 385 <tr>
386 386 <td>{{beams.0.get_upvalues.32}}</td> <td>{{beams.0.get_upvalues.33}}</td> <td>{{beams.0.get_upvalues.34}}</td> <td>{{beams.0.get_upvalues.35}}</td>
387 387 </tr>
388 388 <tr>
389 389 <td>{{beams.0.get_downvalues.32}}</td> <td>{{beams.0.get_downvalues.33}}</td> <td>{{beams.0.get_downvalues.34}}</td> <td>{{beams.0.get_downvalues.35}}</td>
390 390 </tr>
391 391 <tr>
392 392 <td>{{beams.0.get_upvalues.40}}</td> <td>{{beams.0.get_upvalues.41}}</td> <td>{{beams.0.get_upvalues.42}}</td> <td>{{beams.0.get_upvalues.43}}</td>
393 393 </tr>
394 394 <tr>
395 395 <td>{{beams.0.get_downvalues.40}}</td> <td>{{beams.0.get_downvalues.41}}</td> <td>{{beams.0.get_downvalues.42}}</td> <td>{{beams.0.get_downvalues.43}}</td>
396 396 </tr>
397 397 <tr>
398 398 <td>{{beams.0.get_upvalues.48}}</td> <td>{{beams.0.get_upvalues.49}}</td> <td>{{beams.0.get_upvalues.50}}</td> <td>{{beams.0.get_upvalues.51}}</td>
399 399 </tr>
400 400 <tr>
401 401 <td>{{beams.0.get_downvalues.48}}</td> <td>{{beams.0.get_downvalues.49}}</td> <td>{{beams.0.get_downvalues.50}}</td> <td>{{beams.0.get_downvalues.51}}</td>
402 402 </tr>
403 403 <tr>
404 404 <td>{{beams.0.get_upvalues.56}}</td> <td>{{beams.0.get_upvalues.57}}</td> <td>{{beams.0.get_upvalues.58}}</td> <td>{{beams.0.get_upvalues.59}}</td>
405 405 </tr>
406 406 <tr>
407 407 <td>{{beams.0.get_downvalues.56}}</td> <td>{{beams.0.get_downvalues.57}}</td> <td>{{beams.0.get_downvalues.58}}</td> <td>{{beams.0.get_downvalues.59}}</td>
408 408 </tr>
409 409 </table>
410 410 </td>
411 411 <td> <b>South Quarter</b>
412 412 <table class="south ">
413 413 <tr>
414 414 <td>{{beams.0.get_upvalues.36}}</td> <td>{{beams.0.get_upvalues.37}}</td> <td>{{beams.0.get_upvalues.38}}</td> <td>{{beams.0.get_upvalues.39}}</td>
415 415 </tr>
416 416 <tr>
417 417 <td>{{beams.0.get_downvalues.36}}</td> <td>{{beams.0.get_downvalues.37}}</td> <td>{{beams.0.get_downvalues.38}}</td> <td>{{beams.0.get_downvalues.39}}</td>
418 418 </tr>
419 419 <tr>
420 420 <td>{{beams.0.get_upvalues.44}}</td> <td>{{beams.0.get_upvalues.45}}</td> <td>{{beams.0.get_upvalues.46}}</td> <td>{{beams.0.get_upvalues.47}}</td>
421 421 </tr>
422 422 <tr>
423 423 <td>{{beams.0.get_downvalues.44}}</td> <td>{{beams.0.get_downvalues.45}}</td> <td>{{beams.0.get_downvalues.46}}</td> <td>{{beams.0.get_downvalues.47}}</td>
424 424 </tr>
425 425 <tr>
426 426 <td>{{beams.0.get_upvalues.52}}</td> <td>{{beams.0.get_upvalues.53}}</td> <td>{{beams.0.get_upvalues.54}}</td> <td>{{beams.0.get_upvalues.55}}</td>
427 427 </tr>
428 428 <tr>
429 429 <td>{{beams.0.get_downvalues.52}}</td> <td>{{beams.0.get_downvalues.53}}</td> <td>{{beams.0.get_downvalues.54}}</td> <td>{{beams.0.get_downvalues.55}}</td>
430 430 </tr>
431 431 <tr>
432 432 <td>{{beams.0.get_upvalues.60}}</td> <td>{{beams.0.get_upvalues.61}}</td> <td>{{beams.0.get_upvalues.62}}</td> <td>{{beams.0.get_upvalues.63}}</td>
433 433 </tr>
434 434 <tr>
435 435 <td>{{beams.0.get_downvalues.60}}</td> <td>{{beams.0.get_downvalues.61}}</td> <td>{{beams.0.get_downvalues.62}}</td> <td>{{beams.0.get_downvalues.63}}</td>
436 436 </tr>
437 437 </table>
438 438 </td>
439 439 </tr>
440 440 </table>
441 441
442 442 <table class="legend">
443 443 <tr>
444 444 <th colspan="2">Legend</th>
445 445 </tr>
446 446 <tr>
447 447 <td style="color:#ff0000;"><i>RED</i></td><td>Disconnected</td>
448 448 </tr>
449 449 <tr>
450 450 <td style="color:#ee902c;"><i>ORANGE</i></td><td>Connected</td>
451 451 </tr>
452 452 <tr>
453 453 <td style="color:#00cc00;"><i>GREEN</i></td><td>Running</td>
454 454 </tr>
455 455 </table>
456 456
457 457 {% else %}
458 458 <p style="color:#b4bcc2; margin-left: 5%;"><i>No Beams...</i></p>
459 459 {% endif %}
460 460
461 461
462 462 {% endblock %}
@@ -1,365 +1,368
1 1 from django.shortcuts import render_to_response
2 2 from django.template import RequestContext
3 3 from django.shortcuts import redirect, render, get_object_or_404
4 4 from django.contrib import messages
5 5 from django.conf import settings
6 6 from django.http import HttpResponse
7 7
8 8 from datetime import datetime
9 9 from time import sleep
10 10 import os
11 11
12 12 from apps.main.models import Device, Configuration
13 13 from apps.main.views import sidebar
14 14
15 15 from .models import ABSConfiguration, ABSBeam
16 16 from .forms import ABSConfigurationForm, ABSBeamEditForm, ABSBeamAddForm
17 17
18 18 from .utils.overJroShow import overJroShow
19 19 from .utils.OverJRO import OverJRO
20 20 # Create your views here.
21 21 import json, ast
22 22
23 23
24 24 def get_values_from_form(form_data):
25 25
26 26 sublistup = []
27 27 sublistdown = []
28 28 subtxlistup = []
29 29 subtxlistdown = []
30 30 subrxlistup = []
31 31 subrxlistdown = []
32 32
33 33 up_values_list = []
34 34 down_values_list = []
35 35 up_txvalues_list = []
36 36 down_txvalues_list = []
37 37 up_rxvalues_list = []
38 38 down_rxvalues_list = []
39 39
40 40 values_list = {}
41 41 cont = 1
42 42
43 43 for i in range(1,65):
44 44 x = float(form_data['abs_up'+str(i)])
45 45 y = float(form_data['abs_down'+str(i)])
46 46 sublistup.append(x)
47 47 sublistdown.append(y)
48 48
49 49 if str(i) in form_data.getlist('uptx_checks'):
50 50 subtxlistup.append(1)
51 51 else:
52 52 subtxlistup.append(0)
53 53 if str(i) in form_data.getlist('downtx_checks'):
54 54 subtxlistdown.append(1)
55 55 else:
56 56 subtxlistdown.append(0)
57 57
58 58 if str(i) in form_data.getlist('uprx_checks'):
59 59 subrxlistup.append(1)
60 60 else:
61 61 subrxlistup.append(0)
62 62 if str(i) in form_data.getlist('downrx_checks'):
63 63 subrxlistdown.append(1)
64 64 else:
65 65 subrxlistdown.append(0)
66 66
67 67 cont = cont+1
68 68
69 69 if cont == 9:
70 70 up_values_list.append(sublistup)
71 71 down_values_list.append(sublistdown)
72 72 sublistup = []
73 73 sublistdown = []
74 74
75 75 up_txvalues_list.append(subtxlistup)
76 76 down_txvalues_list.append(subtxlistdown)
77 77 subtxlistup = []
78 78 subtxlistdown = []
79 79 up_rxvalues_list.append(subrxlistup)
80 80 down_rxvalues_list.append(subrxlistdown)
81 81 subrxlistup = []
82 82 subrxlistdown = []
83 83 cont = 1
84 84
85 85
86 86 list_uesup = []
87 87 list_uesdown = []
88 88 for i in range(1,5):
89 89 if form_data['ues_up'+str(i)] == '':
90 90 list_uesup.append(0.0)
91 91 else:
92 92 list_uesup.append(float(form_data['ues_up'+str(i)]))
93 93
94 94 if form_data['ues_down'+str(i)] == '':
95 95 list_uesdown.append(0.0)
96 96 else:
97 97 list_uesdown.append(float(form_data['ues_down'+str(i)]))
98 98
99 99 onlyrx_list = form_data.getlist('onlyrx')
100 100 only_rx = {}
101 101 if '1' in onlyrx_list:
102 102 only_rx['up'] = True
103 103 else:
104 104 only_rx['up'] = False
105 105 if '2' in onlyrx_list:
106 106 only_rx['down'] = True
107 107 else:
108 108 only_rx['down'] = False
109 109
110 110 antenna = {'antenna_up': up_values_list, 'antenna_down': down_values_list}
111 111 tx = {'up': up_txvalues_list, 'down': down_txvalues_list}
112 112 rx = {'up': up_rxvalues_list, 'down': down_rxvalues_list}
113 113 ues = {'up': list_uesup, 'down': list_uesdown}
114 114 name = str(form_data['beam_name'])
115 115
116 116 beam_data = {'name': name, 'antenna': antenna, 'tx': tx, 'rx': rx, 'ues': ues, 'only_rx': only_rx}
117 117
118 118 return beam_data
119 119
120 120
121 121
122 122 def abs_conf(request, id_conf):
123 123
124 124 conf = get_object_or_404(ABSConfiguration, pk=id_conf)
125 beams = ABSBeam.objects.filter(abs_conf=conf)
126 #beams_dict = ast.literal_eval(conf.beams)
127 #beams = []
128 #for beam_id in range(1,len(beams_dict)+1):
129 # beam = ABSBeam.objects.get(pk=beams_dict['beam'+str(beam_id)])
130 # beams.append(beam)
125 131
126 beams_dict = ast.literal_eval(conf.beams)
127 beams = []
128 for beam_id in range(1,len(beams_dict)+1):
129 beam = ABSBeam.objects.get(pk=beams_dict['beam'+str(beam_id)])
130 beams.append(beam)
131
132 beams_id = ast.literal_eval(conf.beams)
132 #beams_id = ast.literal_eval(conf.beams)
133 133
134 134 ip=conf.device.ip_address
135 135 port=conf.device.port_address
136 136
137 137 kwargs = {}
138 138 kwargs['status'] = conf.device.get_status_display()
139 139
140 140
141 141 kwargs['dev_conf'] = conf
142 142 kwargs['dev_conf_keys'] = ['name',]
143 143
144 144 kwargs['title'] = 'ABS Configuration'
145 145 kwargs['suptitle'] = 'Details'
146 146 kwargs['no_play'] = True
147 147
148 148 kwargs['button'] = 'Edit Configuration'
149 149
150 150 #kwargs['no_play'] = True
151 kwargs['beams_id'] = beams_id
151 #kwargs['beams_id'] = beams_id
152 152 kwargs['beams'] = beams
153 153 kwargs['beam_selector'] = 0
154 154 #kwargs['my_data'] = simplejson.dumps(beams)
155 155
156 156 kwargs['only_stop'] = True
157 157
158 158 ###### SIDEBAR ######
159 159 kwargs.update(sidebar(conf=conf))
160 160
161 161 return render(request, 'abs_conf.html', kwargs)
162 162
163 163 def abs_conf_edit(request, id_conf):
164 164
165 165 conf = get_object_or_404(ABSConfiguration, pk=id_conf)
166 beams_list = ast.literal_eval(conf.beams)
167 i = 1
168 beams = []
169 for b in beams_list:
170 beam = ABSBeam.objects.get(pk=beams_list['beam'+str(i)])
171 beams.append(beam)
172 i=i+1
166 #beams_list = ast.literal_eval(conf.beams)
167 #i = 1
168 #beams = []
169 #for b in beams_list:
170 # beam = ABSBeam.objects.get(pk=beams_list['beam'+str(i)])
171 # beams.append(beam)
172 # i=i+1
173
174 beams = ABSBeam.objects.filter(abs_conf=conf)
175 print beams
173 176
174 177 if request.method=='GET':
175 178 form = ABSConfigurationForm(instance=conf)
176 179
177 180 if request.method=='POST':
178 181 form = ABSConfigurationForm(request.POST, instance=conf)
179 182
180 183 if form.is_valid():
181 184 conf = form.save(commit=False)
182 185 conf.save()
183 186 return redirect('url_abs_conf', id_conf=conf.id)
184 187
185 188 ###### SIDEBAR ######
186 189 kwargs = {}
187 190
188 191 kwargs['dev_conf'] = conf
189 192 #kwargs['id_dev'] = conf.id
190 193 kwargs['id_conf'] = conf.id
191 194 kwargs['form'] = form
192 195 kwargs['abs_beams'] = beams
193 196 kwargs['title'] = 'Device Configuration'
194 197 kwargs['suptitle'] = 'Edit'
195 198 kwargs['button'] = 'Save'
196 199
197 200 kwargs['edit'] = True
198 201
199 202 return render(request, 'abs_conf_edit.html', kwargs)
200 203
201 204
202 205
203 206
204 207 def add_beam(request, id_conf):
205 208
206 209 conf = get_object_or_404(ABSConfiguration, pk=id_conf)
207 210 confs = Configuration.objects.all()
208 211
209 212 if request.method=='GET':
210 213 #form = ABSBeamEditForm()
211 214 form = ABSBeamAddForm()
212 215
213 216 if request.method=='POST':
214 217 form = ABSBeamAddForm(request.POST)
215 218
216 219 beam_data = get_values_from_form(request.POST)
217 220
218 221 new_beam = ABSBeam(
219 222 name =beam_data['name'],
220 223 antenna =json.dumps(beam_data['antenna']),
221 224 abs_conf=conf,
222 225 tx =json.dumps(beam_data['tx']),
223 226 rx =json.dumps(beam_data['rx']),
224 227 ues =json.dumps(beam_data['ues']),
225 228 only_rx =json.dumps(beam_data['only_rx'])
226 229 )
227 230 new_beam.save()
228 231 #---Update 6bits configuration and add beam to abs configuration beams list.
229 232 new_beam.modules_6bits()
230 233 new_beam.add_beam2list()
231 234 messages.success(request, 'Beam: "%s" has been added.' % new_beam.name)
232 235
233 236 return redirect('url_edit_abs_conf', conf.id)
234 237
235 238 ###### SIDEBAR ######
236 239 kwargs = {}
237 240
238 241 #kwargs['dev_conf'] = conf.device
239 242 #kwargs['id_dev'] = conf.device
240 243 kwargs['id_conf'] = conf.id
241 244 kwargs['form'] = form
242 245 kwargs['title'] = 'ABS Beams'
243 246 kwargs['suptitle'] = 'Add Beam'
244 247 kwargs['button'] = 'Add'
245 248 kwargs['no_sidebar'] = True
246 249
247 250 #kwargs['previous'] = conf.get_absolute_url_edit()
248 251 kwargs['edit'] = True
249 252
250 253 return render(request, 'abs_add_beam.html', kwargs)
251 254
252 255
253 256 def edit_beam(request, id_conf, id_beam):
254 257
255 258 conf = get_object_or_404(ABSConfiguration, pk=id_conf)
256 259 beam = get_object_or_404(ABSBeam, pk=id_beam)
257 260
258 261 if request.method=='GET':
259 262 form = ABSBeamEditForm(initial={'beam': beam})
260 263
261 264 if request.method=='POST':
262 265 form = ABSBeamEditForm(request.POST)
263 266
264 267 beam_data = get_values_from_form(request.POST)
265 268
266 269 beam.dict_to_parms(beam_data)
267 270 beam.save()
268 271
269 272 messages.success(request, 'Beam: "%s" has been updated.' % beam.name)
270 273
271 274 return redirect('url_edit_abs_conf', conf.id)
272 275
273 276 ###### SIDEBAR ######
274 277 kwargs = {}
275 278
276 279 kwargs['id_conf'] = conf.id
277 280 kwargs['form'] = form
278 281 kwargs['title'] = 'ABS Beams'
279 282 kwargs['suptitle'] = 'Edit Beam'
280 283 kwargs['button'] = 'Save'
281 284 kwargs['no_sidebar'] = True
282 285
283 286 #kwargs['previous'] = conf.get_absolute_url_edit()
284 287 kwargs['edit'] = True
285 288
286 289 return render(request, 'abs_edit_beam.html', kwargs)
287 290
288 291
289 292
290 293 def remove_beam(request, id_conf, id_beam):
291 294
292 295 conf = get_object_or_404(ABSConfiguration, pk=id_conf)
293 296 beam = get_object_or_404(ABSBeam, pk=id_beam)
294 297
295 298 if request.method=='POST':
296 299 if beam:
297 300 try:
298 301 beam.remove_beamfromlist()
299 302 beam.delete()
300 303 messages.success(request, 'Beam: "%s" has been deleted.' % beam)
301 304 except:
302 305 messages.error(request, 'Unable to delete beam: "%s".' % beam)
303 306
304 307 return redirect('url_edit_abs_conf', conf.id)
305 308
306 309 ###### SIDEBAR ######
307 310 kwargs = {}
308 311
309 312 kwargs['object'] = beam
310 313 kwargs['delete'] = True
311 314 kwargs['title'] = 'Delete'
312 315 kwargs['suptitle'] = 'Beam'
313 316 kwargs['previous'] = conf.get_absolute_url_edit()
314 317 return render(request, 'confirm.html', kwargs)
315 318
316 319
317 320
318 321 def plot_patterns(request, id_conf, id_beam=None):
319 322
320 323 kwargs = {}
321 324 conf = get_object_or_404(ABSConfiguration, pk=id_conf)
322 325 beams = ABSBeam.objects.filter(abs_conf=conf)
323 326
324 327 if id_beam:
325 328 beam = get_object_or_404(ABSBeam, pk=id_beam)
326 329 kwargs['beam'] = beam
327 330
328 331
329 332 ###### SIDEBAR ######
330 333
331 334 kwargs['dev_conf'] = conf.device
332 335 kwargs['id_dev'] = conf.device
333 336 kwargs['id_conf'] = conf.id
334 337 kwargs['abs_beams'] = beams
335 338 kwargs['title'] = 'ABS Patterns'
336 339 kwargs['suptitle'] = conf.name
337 340 kwargs['no_sidebar'] = True
338 341
339 342 return render(request, 'abs_patterns.html', kwargs)
340 343
341 344
342 345 def plot_pattern(request, id_conf, id_beam, antenna):
343 346
344 347 if antenna=='down':
345 348 sleep(3)
346 349
347 350 conf = get_object_or_404(ABSConfiguration, pk=id_conf)
348 351 beam = get_object_or_404(ABSBeam, pk=id_beam)
349 352
350 353 name = conf.experiment.name
351 354
352 355 just_rx = 1 if json.loads(beam.only_rx)[antenna] else 0
353 356 phases = json.loads(beam.antenna)['antenna_{}'.format(antenna)]
354 357 gain_tx = json.loads(beam.tx)[antenna]
355 358 gain_rx = json.loads(beam.rx)[antenna]
356 359 ues = json.loads(beam.ues)[antenna]
357 360
358 361 newOverJro = overJroShow(name)
359 362 fig = newOverJro.plotPattern2(datetime.today(), phases, gain_tx, gain_rx, ues, just_rx)
360 363
361 364 response=HttpResponse(content_type='image/png')
362 365
363 366 fig.canvas.print_png(response)
364 367
365 368 return response
General Comments 0
You need to be logged in to leave comments. Login now