@@ -116,6 +116,16 @@ def _receive(self, what, address, **kwargs):
116
116
117
117
print ('_receive: please override me.' )
118
118
119
+
120
+ def _receive_multiple (self , what , address , ** kwargs ):
121
+ """Receive (read) a list of values from another host.
122
+
123
+ :address: to receive from
124
+ :what: list to ask for
125
+ """
126
+
127
+ print ('_receive_multiple: please override me.' )
128
+
119
129
def _send_multiple (self , what , values , address ):
120
130
"""Send (write) multiple values to another host.
121
131
@@ -230,6 +240,27 @@ def __init__(self, protocol):
230
240
231
241
# TODO: start UDP enip server
232
242
243
+ @classmethod
244
+ def _tuple_to_cpppo_tag_multiple (cls , what , values = None , serializer = ':' ):
245
+ """Returns a list of cpppo strings to read/write a server.
246
+
247
+ Can be used both to generate cpppo scalar read query, like
248
+ SENSOR1:1, and scalar write query, like ACTUATOR1=1.
249
+
250
+ Value correctness is up the client and it is blindly
251
+ converted to string and appended to the cpppo client query.
252
+ """
253
+ tag_string = ''
254
+
255
+ if values == None :
256
+ for i in range (len (what )):
257
+ tag_string += what [i ][0 ] + EnipProtocol ._SERIALIZER + str (what [i ][1 ]) + " "
258
+ else :
259
+ for i in range (len (what )):
260
+ tag_string += what [i ][0 ] + EnipProtocol ._SERIALIZER + str (what [i ][1 ]) + "=" + str (values [i ]) + " "
261
+
262
+ return tag_string
263
+
233
264
@classmethod
234
265
def _tuple_to_cpppo_tag (cls , what , value = None , serializer = ':' ):
235
266
"""Returns a cpppo string to read/write a server.
@@ -277,7 +308,7 @@ def _tuple_to_cpppo_tags(cls, tags, serializer=':'):
277
308
tags_string += '='
278
309
tags_string += str (tag [- 1 ])
279
310
tags_string += ' '
280
- print ('DEBUG enip server tags_string: ' , tags_string )
311
+ # print('DEBUG enip server tags_string: ', tags_string)
281
312
282
313
return tags_string
283
314
@@ -326,7 +357,7 @@ def _start_server_cmd(cls, address='localhost:44818',
326
357
"""
327
358
328
359
CMD = sys .executable + ' -m cpppo.server.enip '
329
- PRINT_STDOUT = '--print '
360
+ PRINT_STDOUT = '--no- print '
330
361
HTTP = '--web %s:80 ' % address [0 :address .find (':' )]
331
362
# print 'DEBUG: enip _start_server_cmd HTTP: ', HTTP
332
363
ADDRESS = '--address ' + address + ' '
@@ -349,6 +380,32 @@ def _start_server_cmd(cls, address='localhost:44818',
349
380
350
381
return cmd
351
382
383
+ def _send_multiple (self , what , values , address , ** kwargs ):
384
+ """Send (write) a list of values to another host.
385
+ It is a blocking operation the parent process will wait till the child
386
+ cpppo process returns.
387
+ :what: list of tuple addressing what
388
+ :values: sent
389
+ :address: ip[:port]
390
+ """
391
+
392
+ tag_string = ''
393
+ tag_string = EnipProtocol ._tuple_to_cpppo_tag_multiple (what , values )
394
+
395
+ cmd = shlex .split (
396
+ self ._client_cmd +
397
+ '--log ' + self ._client_log +
398
+ '--address ' + address +
399
+ ' ' + tag_string
400
+ )
401
+
402
+ try :
403
+ client = subprocess .Popen (cmd , shell = False )
404
+ client .wait ()
405
+
406
+ except Exception as error :
407
+ print ('ERROR enip _send multiple: ' ), error
408
+
352
409
@classmethod
353
410
def _stop_server (cls , server ):
354
411
"""Stop an enip server.
@@ -407,12 +464,12 @@ def _receive(self, what, address='localhost:44818', **kwargs):
407
464
tag_string = ''
408
465
tag_string = EnipProtocol ._tuple_to_cpppo_tag (what )
409
466
410
- print ("DEBUG " + tag_string )
467
+ # print("DEBUG " + tag_string)
411
468
412
469
cmd = shlex .split (
413
470
self ._client_cmd +
414
471
'--log ' + self ._client_log +
415
- '--address ' + address +
472
+ ' --print --address ' + address +
416
473
' ' + tag_string
417
474
)
418
475
# print 'DEBUG enip _receive cmd shlex list: ', cmd
@@ -423,21 +480,61 @@ def _receive(self, what, address='localhost:44818', **kwargs):
423
480
424
481
# client.communicate is blocking
425
482
raw_out = client .communicate ()
426
- print ('DEBUG1 ' , raw_out )
483
+ # print('DEBUG1 ', raw_out)
427
484
428
485
# value is stored as first tuple element
429
486
# between a pair of square brackets
430
-
487
+
431
488
raw_string = raw_out [0 ]
432
- print ("DEBUG2 " + str (raw_string ))
489
+ # print("DEBUG2 " + str(raw_string))
433
490
raw_string = str (raw_string )
434
491
out = raw_string [(raw_string .find ('[' ) + 1 ):raw_string .find (']' )]
435
- print ("DEBUG4 " + out )
492
+ # print("DEBUG4 " + out)
436
493
return out
437
494
438
495
except Exception as error :
439
496
print ('ERROR enip _receive: ' , error )
440
497
498
+ def _receive_multiple (self , what , address = 'localhost:44818' , ** kwargs ):
499
+ """Receive (read) a value from another host.
500
+ It is a blocking operation the parent process will wait till the child
501
+ cpppo process returns.
502
+ :what: list to ask for
503
+ :address: to receive from
504
+ :returns: tag value as a `str`
505
+ """
506
+
507
+ tag_string = ''
508
+ tag_string = EnipProtocol ._tuple_to_cpppo_tag_multiple (what )
509
+
510
+ cmd = shlex .split (
511
+ self ._client_cmd +
512
+ '--log ' + self ._client_log +
513
+ ' --print --address ' + address +
514
+ ' ' + tag_string
515
+ )
516
+
517
+ try :
518
+ client = subprocess .Popen (cmd , shell = False ,
519
+ stdout = subprocess .PIPE )
520
+
521
+ # client.communicate is blocking
522
+ raw_out = client .communicate ()
523
+ # print(f'DEBUG enip _receive_multiple {raw_out}: ', raw_out)
524
+
525
+ # value is stored as first tuple element
526
+ # between a pair of square brackets
527
+ values = []
528
+ raw_string = raw_out [0 ]
529
+ split_string = raw_string .split (b"\n " )
530
+ for word in split_string :
531
+ values .append (word [(word .find (b'[' ) + 1 ):word .find (b']' )])
532
+ values .pop ()
533
+ return values
534
+
535
+ except Exception as error :
536
+ print ('ERROR enip _receive_multiple: ' , error )
537
+
441
538
# }}}
442
539
443
540
@@ -821,5 +918,23 @@ def _receive(self, what, address='localhost:502', **kwargs):
821
918
822
919
except Exception as error :
823
920
print ('ERROR modbus _receive: ' , error )
921
+
922
+ def _receive_multiple (self , what , address , ** kwargs ):
923
+ """Receive (read) a value from another host.
924
+
925
+ :address: to receive from
926
+ :what: to ask for
927
+ """
928
+
929
+ raise NotImplementedError ('Multiple receiving is not yet implemented for Modbus' )
930
+
931
+ def _send_multiple (self , what , values , address , ** kwargs ):
932
+ """Send (write) multiple values to another host.
933
+
934
+ :address: to receive from
935
+ :what: to ask for
936
+ """
937
+
938
+ raise NotImplementedError ('Multiple sending is not yet implemented for Modbus' )
824
939
#
825
940
# }}}
0 commit comments