@@ -116,6 +116,16 @@ def _receive(self, what, address, **kwargs):
116116
117117 print ('_receive: please override me.' )
118118
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+
119129 def _send_multiple (self , what , values , address ):
120130 """Send (write) multiple values to another host.
121131
@@ -230,6 +240,27 @@ def __init__(self, protocol):
230240
231241 # TODO: start UDP enip server
232242
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+
233264 @classmethod
234265 def _tuple_to_cpppo_tag (cls , what , value = None , serializer = ':' ):
235266 """Returns a cpppo string to read/write a server.
@@ -277,7 +308,7 @@ def _tuple_to_cpppo_tags(cls, tags, serializer=':'):
277308 tags_string += '='
278309 tags_string += str (tag [- 1 ])
279310 tags_string += ' '
280- print ('DEBUG enip server tags_string: ' , tags_string )
311+ # print('DEBUG enip server tags_string: ', tags_string)
281312
282313 return tags_string
283314
@@ -326,7 +357,7 @@ def _start_server_cmd(cls, address='localhost:44818',
326357 """
327358
328359 CMD = sys .executable + ' -m cpppo.server.enip '
329- PRINT_STDOUT = '--print '
360+ PRINT_STDOUT = '--no- print '
330361 HTTP = '--web %s:80 ' % address [0 :address .find (':' )]
331362 # print 'DEBUG: enip _start_server_cmd HTTP: ', HTTP
332363 ADDRESS = '--address ' + address + ' '
@@ -349,6 +380,32 @@ def _start_server_cmd(cls, address='localhost:44818',
349380
350381 return cmd
351382
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+
352409 @classmethod
353410 def _stop_server (cls , server ):
354411 """Stop an enip server.
@@ -407,12 +464,12 @@ def _receive(self, what, address='localhost:44818', **kwargs):
407464 tag_string = ''
408465 tag_string = EnipProtocol ._tuple_to_cpppo_tag (what )
409466
410- print ("DEBUG " + tag_string )
467+ # print("DEBUG " + tag_string)
411468
412469 cmd = shlex .split (
413470 self ._client_cmd +
414471 '--log ' + self ._client_log +
415- '--address ' + address +
472+ ' --print --address ' + address +
416473 ' ' + tag_string
417474 )
418475 # print 'DEBUG enip _receive cmd shlex list: ', cmd
@@ -423,21 +480,61 @@ def _receive(self, what, address='localhost:44818', **kwargs):
423480
424481 # client.communicate is blocking
425482 raw_out = client .communicate ()
426- print ('DEBUG1 ' , raw_out )
483+ # print('DEBUG1 ', raw_out)
427484
428485 # value is stored as first tuple element
429486 # between a pair of square brackets
430-
487+
431488 raw_string = raw_out [0 ]
432- print ("DEBUG2 " + str (raw_string ))
489+ # print("DEBUG2 " + str(raw_string))
433490 raw_string = str (raw_string )
434491 out = raw_string [(raw_string .find ('[' ) + 1 ):raw_string .find (']' )]
435- print ("DEBUG4 " + out )
492+ # print("DEBUG4 " + out)
436493 return out
437494
438495 except Exception as error :
439496 print ('ERROR enip _receive: ' , error )
440497
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+
441538# }}}
442539
443540
@@ -821,5 +918,23 @@ def _receive(self, what, address='localhost:502', **kwargs):
821918
822919 except Exception as error :
823920 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' )
824939#
825940# }}}
0 commit comments