0

I'm working on an interface to OSISoft's PISDK through win32com. I'm trying to use one of IPICalculation's functions, but since IPICalculation is a secondary interface, I'm having problems getting it to work.

What I have so far is:

from win32com.client import Dispatch, CastTo
from win32com.client.gencache import EnsureModule

tagname = 'sometag'
pisdk = Dispatch('PISDK.PISDK')
pisdk2 = EnsureModule('{0EE075CE-8C31-11D1-BD73-0060B0290178}',
                      0, 1, 1, bForDemand=False)
pi_server = pisdk.Servers.DefaultServer
tag_pipoint = pi_server.PIPoints(tagname)
# Using secondary interface IPIData2 works:
data = CastTo(tag_pipoint.Data, 'IPIData2')
# However, trying to use IPICalculation doesn't work:
server = CastTo(pi_server, 'IPICalculation')
# Traceback (most recent call last):
# ...
#  File "C:\Users\MyUser\AppData\Local\Temp\gen_py\3.7\0EE075CE-8C31-11D1-BD73-0060B0290178x0x1x1\IPICalculation.py", line 49, in <module>
#    win32com.client.CLSIDToClass.RegisterCLSID( "{F293A835-D998-11D3-853F-00C04F45D1DA}", IPICalculation )
# NameError: name 'IPICalculation' is not defined

A quick look at the affected generated files (in %LOCALAPPDATA%\Temp\gen_py) reveals that while the IPIData2.py file declares the IPIData2 class, there is no equivalent in the IPICalculation.py file.

For me, it appears to be a bug in win32com and makepy, but I'm not really sure.

I have also digged through the net and found an alternative way to do this, which also fails:

import pythoncom
iface = pi_server._oleobj_.QueryInterface(pythoncom.IID_IDispatch)
CastTo(iface, 'IPICalculation')  # Fails

Other side-notes:

  • I have also tried running makepy in the type library
  • I have tried EnsureDispatch without success
  • The VBA example for using the IPICalculation interface can be found here

I'm trying this on Python 3.7.3, 64-bit, Anaconda Distribution, Windows 10 64-bit, PISDK 1.3 Type Library, PISDK.dll 64-bit version 1.4.6.494.

Ronan Paixão
  • 8,297
  • 1
  • 31
  • 27

1 Answers1

0

Caveat: This is not really an answer because it ditches win32com in favor of comtypes, which I don't want to do because my code already does a lot of win32com stuff and I don't want to port everything nor do I want to have both as dependencies.

However, it works and I leave it here for those that want a working solution.

import comtypes
import comtypes.client

ctsdk = comtypes.client.CreateObject("PISDK.PISDK")
ctpisdk2 = comtypes.gen._0EE075CE_8C31_11D1_BD73_0060B0290178_0_1_1
ctserver = ctsdk.Servers.DefaultServer
ctipicalc = ctserver.QueryInterface(ctpisdk2.IPICalculation)  # This works, so I can proceed:
print(ctipicalc.TimedCalculate(['*'], "'%s'" % tagname)[1].Value)
Ronan Paixão
  • 8,297
  • 1
  • 31
  • 27