exception while writing to a variable

  • Georges Schutz
    Georges Schutz

    Hi all
    I have a OPC server from CoDeSys that is connected to several PLCs.
    I use the Graybox.OPC.DAWrapper class to connect to this server.

    In normal operation everything is fine for reading and writing to the variables.

    One of the PLCs is connected via a DSL ligne which from time to time is rebooted by the operator.
    During this period the server reports "Bad" status for the variables of the PLC while reading using opc.read(tags)

    But if I write to one of the variables of this not connected PLC the opc.write(tagValuePair) is throwing an exception.
    --- in short --
    File "C:\python27\lib\site-packages\OpenOPC.py", line 798, in iwrite
      if errors == 0:
    IndexError: list index out of range

    I use 1.2.0 version of OpenOPC
    I would have expected that this write process would end up with an "unsuccessful" Status.

    So I debugged the code an analysed it a bit :-)
    exception is thrown at that line because the errors list is empty  and n is 0.
    The main reason of this situation is that some lines before the SyncWrite() call raises an exception and errors is initialized to errors =  before.
    --- code part line 790 - 793 --
              errors = opc_group.SyncWrite(len(server_handles)-1, server_handles, valid_values)

    Now my questions:
    1. could it be OK from OPC viewpoint that SyncWrite() ends with an exception if the target variable PLC is unavailable?
    2. could it be a compatibility problem between the Graybox Wrapper and the CoDeSys COM API?
    3. Is there a philosophical reason why all COM call exceptions are simply ignored here?
    4. I think the overall try: except: of the iwrite() method targeting the pythoncom.com_error class is useless for all this COM calls that have an own try: except: with pass in the except stage.

    It would relay be helpful if someone could give me a hint on this.

    Thanks allot for all

    Georges Schutz

  • Georges,

    Normally, the OPC Server will return an error upon a failed write.  If your error list is empty and the write failed, then that is something that is dependant upon the OPC Server itself (CoDeSys). 

    Using 'try / except' where the except functionality is 'pass', is not useless if your intent is to maintain robust communication that "self-heals".   Think of the case where the network is momentarily interrupted, or a PLC is power cycled.  During this instance, various reads and writes may fail, go crazy, or otherwise break part way through.  It is useful to have the 'try / except' (with pass on exception) functionality, so that as soon as the device comes back online the program is able to self-heal and recover gracefully without any human intervention.  It is more a matter of maintaining continuous operation than reporting every single little anamoly that occurs.

    - Vince.

  • Georges Schutz
    Georges Schutz

    Hi Vince,
    Thank you for your reply.

    "Self-healing" is exactly what I would expect but this is not happening due to the pass in the except case.

    Here the reason (at least as I understood the code):
    - before SyncWrite() the errors variable is initialized to:  errors =  #len(errors) == 0
    - if SyncWrite() raises an exception errors stays empty
    - in the following code
    --- File "C:\python27\lib\site-packages\OpenOPC.py", line 795 - 805, see iwrite ---
                n = 0
                for tag in tags:
                   if tag in valid_tags:
                      if errors == 0:
                         status = 'Success'
                         status = 'Error'
                      if include_error:  error_msgs = self._opc.GetErrorString(errors)
                      n += 1
                      status = 'Error'

    n is initialized to 0 and both tags and valid_tags all contains "correct" information.
    The assess to errors will raise the
    IndexError: list index out of range

    What would probably work out is if in the except path errors would be filled with the correct number of items being each different from 0 (but what value to use see GetErrorString(errors) in the code)

    As I am not an OPC-expert nor an COM-expert, I have some problems to really understand all the code that is previously tags, valid_tags, server_handles, …
    I would have proposed some thing like
    In the debugger I see that the exception is a com_error: (-2147352567, 'Exception occured.', (0,None,None,None,0,-2147467259),None)
    According to pythoncom.GetScodeString(-2147467259) this means 'Unspecified error' :-(

    For the moment I handle the situation with a try - except around my opc.write() call.
    But for "Self-healing" purpose I would expect OpenOPC to handle this situation inside.

    Georges Schutz