I’m trying to communicate with an OPC DA server and need to write in a tag which is in an array format. We can connect with a simulation server, read tags (int, real, array) and write tags (int, real, str). The problem comes when we need to write in an array tag. The developper of the OpenOPC library (Barry Barnreiter) recommand to use a VARIANT variable because OPC “expect to see a Windows VARIANT structure when writing complex objects such as arrays”.
- I did install Pywin32 (build 217) as suggested here.
- I tried to send a simple integer instead of an array in a VARIANT structure.
Here’s the code:
from win32com.client import VARIANT import pythoncom import OpenOPC opc_local = OpenOPC.open_client() opc_local.connect('Matrikon.OPC.Simulation','localhost') values = VARIANT(pythoncom.VT_ARRAY | pythoncom.VT_R8, [1.0, 2.0, 3.0, 4.0, 5.0, 6.0]) w = opc_local.write(('Bucket Brigade.ArrayOfReal8', values)) print(w)
Here’s the error that we get when the line with opc_local.write gets executed:
AttributeError: 'module' object has no attribute 'VARIANT'
Here’s the entire traceback:
runfile('C:/Users/nadmin/Downloads/sanstitre0.py', wdir='C:/Users/nadmin/Downloads') Traceback (most recent call last): File "<ipython-input-5-6799f41ab928>", line 1, in <module> runfile('C:/Users/nadmin/Downloads/sanstitre0.py', wdir='C:/Users/nadmin/Downloads') File "C:UsersnadminAppDataLocalContinuumanaconda2libsite-packagesspyder_kernelscustomizespydercustomize.py", line 827, in runfile execfile(filename, namespace) File "C:UsersnadminAppDataLocalContinuumanaconda2libsite-packagesspyder_kernelscustomizespydercustomize.py", line 95, in execfile exec(compile(scripttext, filename, 'exec'), glob, loc) File "C:/Users/nadmin/Downloads/sanstitre0.py", line 14, in <module> w = opc_local.write(('Bucket Brigade.ArrayOfReal8', values)) File "C:UsersnadminAppDataLocalContinuumanaconda2libsite-packagesPyrocore.py", line 381, in __call__ return self.__send(self.__name, args, kwargs) File "C:UsersnadminAppDataLocalContinuumanaconda2libsite-packagesPyrocore.py", line 456, in _invokePYRO return self.adapter.remoteInvocation(name, Pyro.constants.RIF_VarargsAndKeywords, vargs, kargs) File "C:UsersnadminAppDataLocalContinuumanaconda2libsite-packagesPyroprotocol.py", line 497, in remoteInvocation return self._remoteInvocation(method, flags, *args) File "C:UsersnadminAppDataLocalContinuumanaconda2libsite-packagesPyroprotocol.py", line 572, in _remoteInvocation answer.raiseEx() File "C:UsersnadminAppDataLocalContinuumanaconda2libsite-packagesPyroerrors.py", line 72, in raiseEx raise self.excObj
And here’s the configuration of the computer:
- Windows 10
- Python 2.7
- Pyro 3.16
- Pywin32 Build 223
- OpenOPC 1.3.1 win32-py27
Advertisement
Answer
You have to change your line opc_local = OpenOPC.open_client()
for opc_local = OpenOPC.client()
. This will make you connect directly to the OPC server, as opposed to using the OpenOPC Gateway Service.
The VARIANT structure is not included inside the Gateway Service exe. Note that the Gateway Service exe is it’s own frozen Python distribution. Thus it only includes the Python modules inside it that it needs to run and nothing else. So by avoiding using the Gateway Service you should not have this problem since you’ll be executing your code entirely using the Python distribution that you installed yourself on your PC.