##// END OF EJS Templates
ver_3Julio :: Fix IP bug in ABS
jespinoza -
r407:c93b3c968e19
parent child
Show More
@@ -1,461 +1,462
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 from django.urls import reverse
8 8 from django.views.decorators.csrf import csrf_exempt
9 9 from django.utils.safestring import mark_safe
10 10
11 11 from datetime import datetime
12 12 from time import sleep
13 13 import os
14 14 import io
15 15
16 16 from apps.main.models import Device, Configuration, Experiment
17 17 from apps.main.views import sidebar
18 18
19 19 from .models import ABSConfiguration, ABSBeam
20 20 from .forms import ABSConfigurationForm, ABSBeamEditForm, ABSBeamAddForm, ABSImportForm
21 21
22 22 from .utils.overJroShow import overJroShow
23 23 #from .utils.OverJRO import OverJRO
24 24 #Create your views here.
25 25 import json, ast
26 26
27 27
28 28 def get_values_from_form(form_data):
29 29
30 30 sublistup = []
31 31 sublistdown = []
32 32 subtxlistup = []
33 33 subtxlistdown = []
34 34 subrxlistup = []
35 35 subrxlistdown = []
36 36
37 37 up_values_list = []
38 38 down_values_list = []
39 39 up_txvalues_list = []
40 40 down_txvalues_list = []
41 41 up_rxvalues_list = []
42 42 down_rxvalues_list = []
43 43
44 44 values_list = {}
45 45 cont = 1
46 46
47 47 for i in range(1,65):
48 48 x = float(form_data['abs_up'+str(i)])
49 49 y = float(form_data['abs_down'+str(i)])
50 50 sublistup.append(x)
51 51 sublistdown.append(y)
52 52
53 53 if str(i) in form_data.getlist('uptx_checks'):
54 54 subtxlistup.append(1)
55 55 else:
56 56 subtxlistup.append(0)
57 57 if str(i) in form_data.getlist('downtx_checks'):
58 58 subtxlistdown.append(1)
59 59 else:
60 60 subtxlistdown.append(0)
61 61
62 62 if str(i) in form_data.getlist('uprx_checks'):
63 63 subrxlistup.append(1)
64 64 else:
65 65 subrxlistup.append(0)
66 66 if str(i) in form_data.getlist('downrx_checks'):
67 67 subrxlistdown.append(1)
68 68 else:
69 69 subrxlistdown.append(0)
70 70
71 71 cont = cont+1
72 72
73 73 if cont == 9:
74 74 up_values_list.append(sublistup)
75 75 down_values_list.append(sublistdown)
76 76 sublistup = []
77 77 sublistdown = []
78 78
79 79 up_txvalues_list.append(subtxlistup)
80 80 down_txvalues_list.append(subtxlistdown)
81 81 subtxlistup = []
82 82 subtxlistdown = []
83 83 up_rxvalues_list.append(subrxlistup)
84 84 down_rxvalues_list.append(subrxlistdown)
85 85 subrxlistup = []
86 86 subrxlistdown = []
87 87 cont = 1
88 88
89 89
90 90 list_uesup = []
91 91 list_uesdown = []
92 92 for i in range(1,5):
93 93 if form_data['ues_up'+str(i)] == '':
94 94 list_uesup.append(0.0)
95 95 else:
96 96 list_uesup.append(float(form_data['ues_up'+str(i)]))
97 97
98 98 if form_data['ues_down'+str(i)] == '':
99 99 list_uesdown.append(0.0)
100 100 else:
101 101 list_uesdown.append(float(form_data['ues_down'+str(i)]))
102 102
103 103 onlyrx_list = form_data.getlist('onlyrx')
104 104 only_rx = {}
105 105 if '1' in onlyrx_list:
106 106 only_rx['up'] = True
107 107 else:
108 108 only_rx['up'] = False
109 109 if '2' in onlyrx_list:
110 110 only_rx['down'] = True
111 111 else:
112 112 only_rx['down'] = False
113 113
114 114 antenna = {'antenna_up': up_values_list, 'antenna_down': down_values_list}
115 115 tx = {'up': up_txvalues_list, 'down': down_txvalues_list}
116 116 rx = {'up': up_rxvalues_list, 'down': down_rxvalues_list}
117 117 ues = {'up': list_uesup, 'down': list_uesdown}
118 118 name = str(form_data['beam_name'])
119 119
120 120 beam_data = {'name': name, 'antenna': antenna, 'tx': tx, 'rx': rx, 'ues': ues, 'only_rx': only_rx}
121 121
122 122 return beam_data
123 123
124 124
125 125 def abs_conf(request, id_conf):
126 126
127 127 conf = get_object_or_404(ABSConfiguration, pk=id_conf)
128 128 beams = ABSBeam.objects.filter(abs_conf=conf)
129 129 #------------Colors for Active Beam:-------------
130 130 all_status = {}
131 131 module_messages = json.loads(conf.module_messages)
132 132
133 133 color_status = {}
134 134 for i, status in enumerate(conf.module_status):
135 135 if status == '3': #Running background-color: #00cc00;
136 136 all_status['{}'.format(i+1)] = 2
137 137 color_status['{}'.format(i+1)] = 'class=text-success'#'bgcolor=#00cc00'
138 138 elif status == '2':
139 139 all_status['{}'.format(i+1)] = 1
140 140 color_status['{}'.format(i+1)] = 'class=text-info'
141 141 elif status == '1': #Connected background-color: #ee902c;
142 142 all_status['{}'.format(i+1)] = 1
143 143 color_status['{}'.format(i+1)] = 'class=text-warning'#'bgcolor=#ee902c'
144 144 else: #Disconnected background-color: #ff0000;
145 145 all_status['{}'.format(i+1)] = 0
146 146 color_status['{}'.format(i+1)] = 'class=text-danger'#'bgcolor=#FF0000'
147 147 #------------------------------------------------
148 148
149 149 kwargs = {}
150 150 kwargs['connected_modules'] = str(conf.connected_modules())+'/64'
151 151 kwargs['dev_conf'] = conf
152 152
153 153 if conf.operation_mode == 0:
154 154 kwargs['dev_conf_keys'] = ['label', 'operation_mode']
155 155 else:
156 156 kwargs['dev_conf_keys'] = ['label', 'operation_mode', 'operation_value']
157 157
158 158 kwargs['title'] = 'ABS Configuration'
159 159 kwargs['suptitle'] = 'Details'
160 160 kwargs['button'] = 'Edit Configuration'
161 161
162 162 if conf.active_beam != 0:
163 163 kwargs['active_beam'] = int(conf.active_beam)
164 164
165 165 kwargs['beams'] = beams
166 166 kwargs['modules_status'] = all_status
167 167 kwargs['color_status'] = color_status
168 168 kwargs['module_messages'] = module_messages
169 169 ###### SIDEBAR ######
170 170 kwargs.update(sidebar(conf=conf))
171 171
172 172 return render(request, 'abs_conf.html', kwargs)
173 173
174 174
175 175 def abs_conf_edit(request, id_conf):
176 176
177 177 conf = get_object_or_404(ABSConfiguration, pk=id_conf)
178 178
179 179 beams = ABSBeam.objects.filter(abs_conf=conf)
180 180
181 181 if request.method=='GET':
182 182 form = ABSConfigurationForm(instance=conf)
183 183
184 184 if request.method=='POST':
185 185 form = ABSConfigurationForm(request.POST, instance=conf)
186 186
187 187 if form.is_valid():
188 188 conf = form.save(commit=False)
189 189 conf.save()
190 190 return redirect('url_abs_conf', id_conf=conf.id)
191 191
192 192 ###### SIDEBAR ######
193 193 kwargs = {}
194 194
195 195 kwargs['dev_conf'] = conf
196 196 #kwargs['id_dev'] = conf.id
197 197 kwargs['id_conf'] = conf.id
198 198 kwargs['form'] = form
199 199 kwargs['abs_beams'] = beams
200 200 kwargs['title'] = 'Device Configuration'
201 201 kwargs['suptitle'] = 'Edit'
202 202 kwargs['button'] = 'Save'
203 203
204 204 kwargs['edit'] = True
205 205
206 206 return render(request, 'abs_conf_edit.html', kwargs)
207 207
208 208 @csrf_exempt
209 209 def abs_conf_alert(request):
210 210
211 211 if request.method == 'POST':
212 212 print (request.POST)
213 213 return HttpResponse(json.dumps({'result':1}), content_type='application/json')
214 214 else:
215 215 return redirect('index')
216 216
217 217
218 218 def import_file(request, id_conf):
219 219
220 220 conf = get_object_or_404(ABSConfiguration, pk=id_conf)
221 221 if request.method=='POST':
222 222 form = ABSImportForm(request.POST, request.FILES)
223 223 if form.is_valid():
224 224 try:
225 225 parms = conf.import_from_file(request.FILES['file_name'])
226 226
227 227 if parms:
228 228 conf.update_from_file(parms)
229 229 messages.success(request, 'Configuration "%s" loaded succesfully' % request.FILES['file_name'])
230 230 return redirect(conf.get_absolute_url_edit())
231 231
232 232 except Exception as e:
233 233 messages.error(request, 'Error parsing file: "%s" - %s' % (request.FILES['file_name'], e))
234 234
235 235 else:
236 236 messages.warning(request, 'Your current configuration will be replaced')
237 237 form = ABSImportForm()
238 238
239 239 kwargs = {}
240 240 kwargs['form'] = form
241 241 kwargs['title'] = 'ABS Configuration'
242 242 kwargs['suptitle'] = 'Import file'
243 243 kwargs['button'] = 'Upload'
244 244 kwargs['previous'] = conf.get_absolute_url()
245 245
246 246 return render(request, 'abs_import.html', kwargs)
247 247
248 248
249 249 def start(request, id_conf, id_beam):
250 250
251 251 conf = get_object_or_404(ABSConfiguration, pk=id_conf)
252 252 beams_list = ABSBeam.objects.filter(abs_conf=conf)
253 253 if id_beam>=len(beams_list):
254 254 return HttpResponse(json.dumps({'result':0}), content_type='application/json')
255 255 conf.start_device(id_beam)
256 256
257 257 for i, beam in enumerate(beams_list):
258 258 if i==int(id_beam):
259 259 conf.active_beam = beam.pk
260 conf.save()
260 261 break
261 262
262 263 return HttpResponse(json.dumps({'result':1}), content_type='application/json')
263 264
264 265
265 266 def send_beam(request, id_conf, id_beam):
266 267
267 268 conf = get_object_or_404(ABSConfiguration, pk=id_conf)
268 269
269 270 abs = Configuration.objects.filter(pk=conf.device.conf_active).first()
270 271 if abs!=conf:
271 272 url = '#' if abs is None else abs.get_absolute_url()
272 273 label = 'None' if abs is None else abs.label
273 274 messages.warning(
274 275 request,
275 276 mark_safe('The current configuration has not been written in the modules, the active configuration is <a href="{}">{}</a>'.format(
276 277 url,
277 278 label
278 279 ))
279 280 )
280 281 return redirect(conf.get_absolute_url())
281 282
282 283 beam = get_object_or_404(ABSBeam, pk=id_beam)
283 284
284 285 if request.method == 'POST':
285 286
286 287 beams_list = ABSBeam.objects.filter(abs_conf=conf)
287 288 conf.active_beam = id_beam
288 289
289 290 i = 0
290 291 for b in beams_list:
291 292 if b.id == int(id_beam):
292 293 break
293 294 else:
294 295 i += 1
295 296 beam_pos = i + 1 #Estandarizar
296 297 print ('%s Position: %s') % (beam.name, str(beam_pos))
297 298 conf.send_beam(beam_pos)
298 299
299 300 return redirect('url_abs_conf', conf.id)
300 301
301 302 kwargs = {
302 303 'title': 'ABS',
303 304 'suptitle': conf.label,
304 305 'message': 'Are you sure you want to change ABS Beam to: {}?'.format(beam.name),
305 306 'delete': False
306 307 }
307 308 kwargs['menu_configurations'] = 'active'
308 309
309 310 return render(request, 'confirm.html', kwargs)
310 311
311 312
312 313 def add_beam(request, id_conf):
313 314
314 315 conf = get_object_or_404(ABSConfiguration, pk=id_conf)
315 316 confs = Configuration.objects.all()
316 317
317 318 if request.method=='GET':
318 319 form = ABSBeamAddForm()
319 320
320 321 if request.method=='POST':
321 322 form = ABSBeamAddForm(request.POST)
322 323
323 324 beam_data = get_values_from_form(request.POST)
324 325
325 326 new_beam = ABSBeam(
326 327 name = beam_data['name'],
327 328 antenna = json.dumps(beam_data['antenna']),
328 329 abs_conf = conf,
329 330 tx = json.dumps(beam_data['tx']),
330 331 rx = json.dumps(beam_data['rx']),
331 332 ues = json.dumps(beam_data['ues']),
332 333 only_rx = json.dumps(beam_data['only_rx'])
333 334 )
334 335 new_beam.save()
335 336 messages.success(request, 'Beam: "%s" has been added.' % new_beam.name)
336 337
337 338 return redirect('url_edit_abs_conf', conf.id)
338 339
339 340 ###### SIDEBAR ######
340 341 kwargs = {}
341 342
342 343 #kwargs['dev_conf'] = conf.device
343 344 #kwargs['id_dev'] = conf.device
344 345 #kwargs['previous'] = conf.get_absolute_url_edit()
345 346 kwargs['id_conf'] = conf.id
346 347 kwargs['form'] = form
347 348 kwargs['title'] = 'ABS Beams'
348 349 kwargs['suptitle'] = 'Add Beam'
349 350 kwargs['button'] = 'Add'
350 351 kwargs['no_sidebar'] = True
351 352 kwargs['edit'] = True
352 353
353 354 return render(request, 'abs_add_beam.html', kwargs)
354 355
355 356
356 357 def edit_beam(request, id_conf, id_beam):
357 358
358 359 conf = get_object_or_404(ABSConfiguration, pk=id_conf)
359 360 beam = get_object_or_404(ABSBeam, pk=id_beam)
360 361
361 362 if request.method=='GET':
362 363 form = ABSBeamEditForm(initial={'beam': beam})
363 364
364 365 if request.method=='POST':
365 366 form = ABSBeamEditForm(request.POST)
366 367
367 368 beam_data = get_values_from_form(request.POST)
368 369
369 370 beam.dict_to_parms(beam_data)
370 371 beam.save()
371 372
372 373 messages.success(request, 'Beam: "%s" has been updated.' % beam.name)
373 374
374 375 return redirect('url_edit_abs_conf', conf.id)
375 376
376 377 ###### SIDEBAR ######
377 378 kwargs = {}
378 379
379 380 kwargs['id_conf'] = conf.id
380 381 kwargs['form'] = form
381 382 kwargs['title'] = 'ABS Beams'
382 383 kwargs['suptitle'] = 'Edit Beam'
383 384 kwargs['button'] = 'Save'
384 385 kwargs['no_sidebar'] = True
385 386
386 387 #kwargs['previous'] = conf.get_absolute_url_edit()
387 388 kwargs['edit'] = True
388 389
389 390 return render(request, 'abs_edit_beam.html', kwargs)
390 391
391 392
392 393
393 394 def remove_beam(request, id_conf, id_beam):
394 395
395 396 conf = get_object_or_404(ABSConfiguration, pk=id_conf)
396 397 beam = get_object_or_404(ABSBeam, pk=id_beam)
397 398
398 399 if request.method=='POST':
399 400 if beam:
400 401 try:
401 402 beam.delete()
402 403 messages.success(request, 'Beam: "%s" has been deleted.' % beam)
403 404 except:
404 405 messages.error(request, 'Unable to delete beam: "%s".' % beam)
405 406
406 407 return redirect('url_edit_abs_conf', conf.id)
407 408
408 409 ###### SIDEBAR ######
409 410 kwargs = {}
410 411
411 412 kwargs['object'] = beam
412 413 kwargs['delete'] = True
413 414 kwargs['title'] = 'Delete'
414 415 kwargs['suptitle'] = 'Beam'
415 416 kwargs['previous'] = conf.get_absolute_url_edit()
416 417 return render(request, 'confirm.html', kwargs)
417 418
418 419
419 420
420 421 def plot_patterns(request, id_conf, id_beam=None):
421 422
422 423 kwargs = {}
423 424 conf = get_object_or_404(ABSConfiguration, pk=id_conf)
424 425 beams = ABSBeam.objects.filter(abs_conf=conf)
425 426
426 427 if id_beam:
427 428 beam = get_object_or_404(ABSBeam, pk=id_beam)
428 429 kwargs['beam'] = beam
429 430
430 431 ###### SIDEBAR ######
431 432
432 433 kwargs['dev_conf'] = conf.device
433 434 kwargs['id_dev'] = conf.device
434 435 kwargs['id_conf'] = conf.id
435 436 kwargs['abs_beams'] = beams
436 437 kwargs['title'] = 'ABS Patterns'
437 438 kwargs['suptitle'] = conf.name
438 439 kwargs['no_sidebar'] = True
439 440
440 441 return render(request, 'abs_patterns.html', kwargs)
441 442
442 443
443 444 def plot_pattern(request, id_conf, id_beam, antenna):
444 445
445 446 if antenna=='down':
446 447 sleep(3)
447 448
448 449 conf = get_object_or_404(ABSConfiguration, pk=id_conf)
449 450 beam = get_object_or_404(ABSBeam, pk=id_beam)
450 451 just_rx = 1 if json.loads(beam.only_rx)[antenna] else 0
451 452 phases = json.loads(beam.antenna)['antenna_{}'.format(antenna)]
452 453 gain_tx = json.loads(beam.tx)[antenna]
453 454 gain_rx = json.loads(beam.rx)[antenna]
454 455 ues = json.loads(beam.ues)[antenna]
455 456 newOverJro = overJroShow(beam.name)
456 457 fig = newOverJro.plotPattern2(datetime.today(), phases, gain_tx, gain_rx, ues, just_rx)
457 458 buf = io.BytesIO()
458 459 fig.savefig(buf, format='png')
459 460 response = HttpResponse(buf.getvalue(), content_type='image/png')
460 461 return response
461 462
@@ -1,151 +1,156
1 1 '''
2 2 Created on Dec 2, 2014
3 3
4 4 @author: Miguel Urco
5 5
6 6 eth_device decorator is used to implement an api to ethernet devices.
7 7 When eth_device decorator is used it adds two parameters to any function (ip and port)
8 8
9 9 #Definition
10 10
11 11 @eth_device
12 12 def enable_rf()
13 13 cmd = "xxxxx"
14 14 payload = "xxxxxx"
15 15
16 16 return cmd, payload
17 17
18 18 #How to call this function:
19 19 answer = enable_rf(ip, port)
20 20
21 21 '''
22 22 import json
23 23 from devices.dds import data
24 24
25 from devices.jro_device import eth_device, IdClass
25 from devices.jro_device import eth_device, eth_devices, IdClass
26 26
27 27 ID_CLASS = IdClass["dds"]
28 28
29 29 CMD_RESET =0X01
30 30 CMD_ENABLE =0X02
31 31 CMD_CHANGEIP =0X03
32 32 CMD_STATUS =0X04
33 33 CMD_ECHO =0XFE
34 34
35 35 DDS_CMD_RESET =0X10
36 36 DDS_CMD_ENABLE_RF =0x11
37 37 # DDS_CMD_MULTIPLIER =0X12
38 38 # DDS_CMD_MODE =0x13
39 39 # DDS_CMD_FREQUENCY_A =0X14
40 40 # DDS_CMD_FREQUENCY_B =0x15
41 41 # DDS_CMD_PHASE_A =0X16
42 42 # DDS_CMD_PHASE_B =0x17
43 43 # DDS_CMD_AMPLITUDE_1 =0X19 #Se han invertido la posicion de los canales
44 44 # DDS_CMD_AMPLITUDE_2 =0x18 #en el PCB
45 45
46 46 DDS_CMD_WRITE =0x50
47 47 DDS_CMD_READ =0x8000
48 48
49 49 @eth_device(ID_CLASS)
50 50 def reset():
51 51
52 52 cmd = CMD_RESET
53 53 payload = ""
54 54
55 55 return cmd, payload
56 56
57 @eth_device(ID_CLASS)
57 @eth_devices(ID_CLASS)
58 58 def change_ip(new_ip, mask="255.255.255.0", gateway="0.0.0.0"):
59 59
60 60 cmd = CMD_CHANGEIP
61 payload = new_ip + '/' + mask + '/' + gateway
61 payload = b''
62 payload += new_ip.encode()
63 payload += b'/'
64 payload += mask.encode()
65 payload += b'/'
66 payload += gateway.encode()
62 67
63 68 return cmd, payload
64 69
65 70 @eth_device(ID_CLASS)
66 71 def status():
67 72
68 73 cmd = CMD_STATUS
69 74 payload = b''
70 75 return cmd, payload
71 76
72 77 @eth_device(ID_CLASS)
73 78 def echo():
74 79
75 80 cmd = CMD_ECHO
76 81 payload = ""
77 82
78 83 return cmd, payload
79 84
80 85 @eth_device(ID_CLASS)
81 86 def enable_rf():
82 87
83 88 cmd = DDS_CMD_ENABLE_RF
84 89 payload = chr(0x01).encode()
85 90
86 91 return cmd, payload
87 92
88 93 @eth_device(ID_CLASS)
89 94 def disable_rf():
90 95
91 96 cmd = DDS_CMD_ENABLE_RF
92 97 payload = chr(0x00).encode()
93 98
94 99 return cmd, payload
95 100
96 101 @eth_device(ID_CLASS)
97 102 def read_all_device():
98 103
99 104 payload = ""
100 105
101 106 return DDS_CMD_READ, payload
102 107
103 108 @eth_device(ID_CLASS)
104 109 def write_all_device(payload):
105 110
106 111 return DDS_CMD_WRITE, payload
107 112
108 113 def read_config(ip, port):
109 114 """
110 115 Output:
111 116 parms : Dictionary with keys
112 117 multiplier :
113 118 frequencyA :
114 119 frequencyB :
115 120 frequencyA_Mhz :
116 121 frequencyB_Mhz :
117 122 modulation :
118 123 phaseA_degrees :
119 124 phaseB_degrees :
120 125 amplitudeI :
121 126 amplitudeQ :
122 127
123 128 """
124 129 payload = read_all_device(ip, port)
125 130
126 131 return data.dds_str_to_dict(payload)
127 132
128 133 def write_config(ip, port, parms):
129 134 """
130 135 Input:
131 136 ip :
132 137 port :
133 138 parms : Dictionary with keys
134 139 multiplier : 4 to 20
135 140 frequencyA : 0 to (2**48-1) equivalent to: 0 - "Master clock"
136 141 frequencyB : 0 to (2**48-1) equivalent to: 0 - "Master clock"
137 142 modulation : 0 to 3
138 143 phaseA_degrees : 0 - 360 degrees
139 144 phaseB_degrees : 0 - 360 degrees
140 145 amplitudeI : 0 to (2**12-1) equivalent to: 0 - 100%
141 146 amplitudeQ : 0 to (2**12-1) equivalent to: 0 - 100%
142 147
143 148 """
144 149
145 150 payload = data.dict_to_dds_str(parms)
146 151 answer = write_all_device(ip, port, payload)
147 152 return answer
148 153
149 154 if __name__ == '__main__':
150 155
151 156 print(read_config("127.0.0.1", 2000))
@@ -1,414 +1,429
1 1 '''
2 2 Created on Dec 2, 2014
3 3
4 4 @author: Miguel Urco
5 5 '''
6 6 import time
7 7 import struct
8 8 import socket
9 9
10 10 DEBUG = False
11 11 CMD_RESET =0X01
12 12 CMD_ENABLE =0X02
13 13 CMD_CHANGEIP =0X03
14 14
15 15 IdClass={
16 16 "rc" : 0x01,
17 17 "dds" : 0x02,
18 18 "jars" : 0x03,
19 19 "usrp" : 0x04,
20 20 "echotek" : 0x05,
21 21 "abs" : 0x06,
22 22 "clk_gen" : 0x07
23 23 }
24 24
25 25 def ascii2hex(cadena):
26 26
27 27 hex_cad = ''
28 28 for c in cadena:
29 29 hex_cad += hex(ord(c))[2:].rjust(2,'0') + ' '
30 30
31 31 return hex_cad
32 32
33 33 def ping(host):
34 34 """
35 35 Returns True if host responds to a ping request
36 36 """
37 37 import os, platform
38 38
39 39 # Ping parameters as function of OS
40 40 ping_str = "-n 1" if platform.system().lower()=="windows" else "-c 1"
41 41
42 42 # Ping
43 43 return os.system("ping " + ping_str + " " + host) == 0
44 44
45 45 class IPData(object):
46 46
47 47 '''
48 48 Clase para manejar la trama de datos provenientes del/hacia un dispositivo Ethernet.
49 49 La trama de datos es la siguiente:
50 50
51 51 **********************************
52 52 ** FORMATO GENERAL DE UNA TRAMA **
53 53 **********************************
54 54
55 55 1. Cabecera (5 bytes): Secuencia Fija que deber ser "$JRO$"
56 56 2. Longitud (3 bytes): Cantidad de bytes de la Data, contados desde IdClass hasta el Xor
57 57 3. Id class (1 byte) : Clase de dispositivo a configurar. Por defecto 0
58 58 4. Id device (1 byte): Identificar del dispositivo a configurar. Por defecto 0
59 59 5. Cmd (2 bytes): Identificador del comando a ejecutarse.
60 60 3. Payload (n bytes): Carga Util conteniendo secuencia,comandos y parametros
61 61 4. Xor (1 byte): Byte de revision de consistencia de la data al aplicar Xor a todos los bytes,
62 62 desde la longitud hasta el payload.
63 63
64 64 '''
65 65 __HEADER = "$JRO$"
66 66
67 67 def __init__(self, ip, port, id_class=0, id_dev=0):
68 68 '''
69 69 '''
70 70 self.id_class = id_class
71 71 self.id_dev = id_dev
72 72
73 73 self.address = (str(ip), int(port))
74 74
75 75 self.__iniVariables()
76 76
77 77 def __iniVariables(self):
78 78
79 79 self.tx_buffer = None
80 80 self.rx_buffer = None
81 81
82 82 #self.header = None
83 83 self.len = None
84 84 self.cmd = None
85 85 self.payload = None
86 86
87 87 self.invalid = True
88 88 self.errormsg = ''
89 89 self.hasPayload = False
90 90
91 91 def __getXor(self, cadena):
92 92 '''
93 93 '''
94 94 #trama = '%03d' %lenght + ipPayload
95 95 xor = 0
96 96 for character in cadena:
97 97 xor = xor ^ ord(character)
98 98
99 99 # xor_hex = hex(xor)
100 100 # xor_hex = xor_hex[2:]
101 101 # xor_hex = xor_hex.rjust(2,'0')
102 102
103 103 return xor
104 104
105 105 def __verifyXor(self, cadena):
106 106
107 107 xor = self.__getXor(cadena)
108 108
109 109 if xor != 0:
110 110 return 0
111 111
112 112 return 1
113 113
114 114 def __encoder(self, cmd, payload):
115 115 '''
116 116 Inputs:
117 117 cmd : Entero que indica el tipo de comando
118 118 payload : Cadena de caracteres con informacion, depende del comando
119 119
120 120 '''
121 121
122 122 #seq = '%04d' %(sequence)
123 123 #conf = '%04d' %(confcode)
124 124
125 125 #Number to Cad: 2 Bytes <> H, 4 Bytes <> I
126 126 cmd_cad = struct.pack(">H", cmd)
127 127
128 128 data = chr(self.id_class).encode() + chr(self.id_dev).encode() + cmd_cad + payload
129 129
130 130 len_data = len(data) + 1 # + xor
131 131 len_cad = struct.pack('>I', len_data)
132 132
133 133 lenAndData = len_cad + chr(self.id_class).encode() + chr(self.id_dev).encode() + cmd_cad + payload
134 134
135 135 lenAndData = list(lenAndData)
136 136
137 137 new = ''
138 138 for u in lenAndData:
139 139 new += chr(u)
140 140
141 141 xor = self.__getXor(new)
142 142
143 143 trama = self.__HEADER + new + chr(xor)
144 144
145 145 self.tx_buffer = trama
146 146
147 147 return trama
148 148
149 149 def __decoder(self, rx_buffer):
150 150 '''
151 151 Evalua la trama y la separa en los campos correspondientes
152 152
153 153 4Bytes | 4Bytes | 1Byte | 1 Byte | 2 Bytes | n Bytes | 1 Byte
154 154 Header | Len | Id class | Id dev | Cmd | Payload | Xor
155 155
156 156 '''
157 157 self.invalid = True
158 158 self.hasPayload = False
159 159 self.rx_buffer = rx_buffer
160 160
161 161 try:
162 162 index = rx_buffer.find(self.__HEADER)
163 163 except:
164 164 self.errormsg = "rx_buffer is not a string"
165 165 return 0
166 166
167 167 if index == -1:
168 168 self.errormsg = "No header found: %s" %ascii2hex(rx_buffer)
169 169 return 0
170 170
171 171 #print('???????', flush=True)
172 172
173 173 rx_buffer = rx_buffer[index + len(self.__HEADER):]
174 174
175 175 len_cad = rx_buffer[0:4].encode()
176 176
177 177 len_data = struct.unpack('>I',len_cad)[0]
178 178
179 179 lenAndDataAndXor = rx_buffer[0:len_data + 4] #Incluye los 4 bytes de la longitud
180 180
181 181 dataAndXor = lenAndDataAndXor[4:]
182 182
183 183 if len(dataAndXor) < len_data:
184 184 self.errormsg = "Data length is lower than %s" %(len_data)
185 185 return 0
186 186
187 187 # print self.header, ", ", ascii2hex(lenCad), ", ", ascii2hex(ipDataAndXor), ", ", hex(self.xor)
188 188
189 189 if not self.__verifyXor(lenAndDataAndXor):
190 190 self.errormsg = "Invalid xor: %s" %lenAndDataAndXor[-1]
191 191 return 0
192 192
193 193 self.invalid = False
194 194
195 195 len_payload = len_data - 5 #Decrementar 1B (id_class), 1B (id_dev), 2B (cmd) y 1B (xor)
196 196
197 197 id_class = ord(dataAndXor[0])
198 198 id_dev = ord(dataAndXor[1])
199 199 cmd_cad = dataAndXor[2:4].encode()
200 200 payload = dataAndXor[4:4+len_payload]
201 201
202 202 cmd = struct.unpack('>H',cmd_cad)[0]
203 203
204 204 self.id_class = id_class
205 205 self.id_dev = id_dev
206 206 self.cmd = cmd
207 207
208 208 if len(payload) < 1:
209 209 self.errormsg = "IP data is valid but it hasn't payload"
210 210 return 1
211 211
212 212 self.hasPayload = True
213 213 self.payload = payload
214 214
215 215 self.errormsg = "Successful"
216 216
217 217 return 1
218 218
219 219 def __decoder_api(self, rx_buffer, debug = DEBUG):
220 220 """
221 221 Input:
222 222 rx_buffer : Trama recibida como respuesta a un comando enviada a un dispositivo.
223 223
224 224 Return:
225 225 0 : Trama recibida incorrecta. La cadena "rx_buffer" no ha sido decodificada correctamente.
226 226 -1 : Dispositivo no inicializado. El dispositivo, dds o rc, no ha sido inicializado
227 227 correctamente.
228 228 -2 : Trama enviada no reconocida. La cadena recibida es correcta y el dispositivo ha sido
229 229 inicializaado correctamente pero la trama enviada no ha sido reconocida por el
230 230 dispositivo o el comando enviado no ha sido implementado.
231 231 >0 : Trama enviada y recibida correctamente
232 232 """
233 233
234 234 if not self.__decoder(rx_buffer):
235 235 return "0:Error decoding eth data: " + ascii2hex(self.rx_buffer)
236 236
237 237 # if self.getPayload() == "OK":
238 238 # return 1
239 239 #
240 240 # if self.getPayload() == "NI":
241 241 # return -1
242 242 #
243 243 # if self.getPayload() == "KO":
244 244 # return -2
245 245
246 246 if debug:
247 247 print(ascii2hex(self.rx_buffer))
248 248
249 249 return self.payload
250 250
251 251 def getRxBufferHex(self):
252 252
253 253 if self.rx_buffer == None:
254 254 return ''
255 255
256 256 cad = ascii2hex(self.rx_buffer)
257 257
258 258 return cad
259 259
260 260 def getTxBufferHex(self):
261 261
262 262 if self.tx_buffer == None:
263 263 return ''
264 264
265 265 cad = ascii2hex(self.tx_buffer)
266 266
267 267 return cad
268 268
269 269 def isInvalid(self):
270 270
271 271 return self.invalid
272 272
273 273 def getCmd(self):
274 274 return self.cmd
275 275
276 276 def getPayload(self):
277 277 return self.payload
278 278
279 279 def getErrorMessage(self):
280 280
281 281 return self.errormsg
282 282
283 283 def getTxBuffer(self):
284 284
285 285 return self.tx_buffer
286 286
287 287 def getRxBuffer(self):
288 288
289 289 return self.rx_buffer
290 290
291 291 def __encodeIpCmd(self, ip, mask, gateway):
292 292
293 293 payload = ip + '/' + mask + '/' + gateway
294 294 return self.__encoder(CMD_CHANGEIP, payload)
295 295
296 296 def __encodeResetCmd(self):
297 297
298 298 payload = ""
299 299 return self.__encoder(CMD_RESET, payload)
300 300
301 301 def __sendTCPData(self, cadena=b''):
302 302
303 303 sck = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
304 304 sck.settimeout(3)
305 305
306 306
307 307 try:
308 308 sck.connect(self.address)
309 309 except:
310 310 return None
311 311
312 312 #print('trama', cadena.encode('raw_unicode_escape'), flush=True)
313 313 sck.send(cadena.encode('raw_unicode_escape'))
314 314
315 315 rx_buffer = b''
316 316 ini = time.time()
317 317
318 318 try:
319 319 while True:
320 320
321 321 if time.time() - ini > 0.5:
322 322 break
323 323
324 324 try:
325 325 tmp = sck.recv(4096)
326 326 except:
327 327 break
328 328
329 329 if len(tmp) < 1:
330 330 continue
331 331
332 332 ini = time.time()
333 333 rx_buffer += tmp
334 334
335 335 finally:
336 336 sck.close()
337 337
338 338
339 339 rx_buffer = list(rx_buffer)
340 340
341 341 #print('-**********-')
342 342 #print(rx_buffer, flush=True)
343 343 #print('-**********-')
344 344
345 345 new = ''
346 346 for u in rx_buffer:
347 347 new += chr(u)
348 348
349 349 return new
350 350
351 351 def changeIP(self, ip, mask, gateway):
352 352
353 353 tx_buffer = self.__encodeIpCmd(ip, mask, gateway)
354 354 rx_buffer = self.__sendTCPData(tx_buffer)
355 355
356 356 sts = self.__decoder_api(rx_buffer)
357 357
358 358 if sts > 0:
359 359 self.address = (ip, self.address[1])
360 360
361 361 return sts
362 362
363 363 def reset(self):
364 364
365 365 tx_buffer = self.__encodeResetCmd()
366 366 rx_buffer = self.__sendTCPData(tx_buffer)
367 367
368 368 return self.__decoder_api(rx_buffer)
369 369
370 370 def sendData(self, cmd, payload, server=False):
371 371
372 372 if server:
373 373 tx_buffer = self.__encoder(cmd, payload)
374 374
375 375 print('TX:{}'.format(ascii2hex(tx_buffer)))
376 376
377 377 self.client_connection.sendall(tx_buffer)
378 378
379 379 else:
380 380
381 381 tx_buffer = self.__encoder(cmd, payload)
382 382
383 383 print('TX:{}'.format(ascii2hex(tx_buffer)))
384 384
385 385 rx_buffer = self.__sendTCPData(tx_buffer)
386 386
387 387 if not rx_buffer:
388 388 msg = "0:Could not connect to Device %s" %str(self.address)
389 389 return msg
390 390
391 391 print('RX:{}'.format(ascii2hex(rx_buffer)))
392 392
393 393 return self.__decoder_api(rx_buffer)
394 394
395 395 def receiveData(self, rx_buffer):
396 396
397 397 print('RX:{}'.format(ascii2hex(rx_buffer)))
398 398
399 399 return self.__decoder(rx_buffer)
400 400
401 401
402 402 def eth_device(id_class):
403 403 def inner_func(func):
404 404 def func_wrapper(ip, port, *args):
405 405
406 406 cmd, payload = func(*args)
407 407
408 408 ipObj = IPData(ip, port, id_class=id_class)
409 409 rx = ipObj.sendData(cmd, payload)
410 410
411 411 return rx
412 412
413 413 return func_wrapper
414 414 return inner_func
415
416 def eth_devices(id_class):
417 def inner_func(func):
418 def func_wrapper(ip, port, **kwargs):
419
420 cmd, payload = func(**kwargs)
421
422 ipObj = IPData(ip, port, id_class=id_class)
423 rx = ipObj.sendData(cmd, payload)
424
425 return rx
426
427 return func_wrapper
428 return inner_func
429
General Comments 0
You need to be logged in to leave comments. Login now