Zugriff mt Win32::OLE und PI-SDK auf PI-DB

22/01/2015 - 14:48 von michael.menge | Report spam
Hallo,

ich versuche, mit OLE und dem PI-SDK der Firma Osisoft Daten aus deren PI-Datenbank zu lesen.
Es gelingt mir, Snapshotdaten eines PI-Tags zu lesen, aber beim Aufruf der Methode "RecordedValues" erhalte ich immer die Fehlermeldung
"win32::OLE(0.1711) error 0x80020005: "Typkonflikt"
in METHOD/PROPERTYGET "RecordedValues" argument "BoundaryType" at Pi.pl line ..
Möglicherweise liegt der Fehler darin, daß Perl Parameter immer per Referenz übergibt, das Argument "BoundaryType" aber per Value übergeben werden muß.

Im PI-Help-Utility findet man:

RecordedValues Method (PIData object)

This method returns compressed values for the requested time range from the archive as a PIValues collection.
Syntax
object.RecordedValues StartTime, EndTime, BoundaryType, [FilterExp], [ShowFiltered], [AsyncStatus]

The RecordedValues method syntax has these parts:
Part Description
object An object expression that evaluates to a PIData object.
StartTime A Variant containing the time. See the Settings section for allowable values.
EndTime A Variant containing the time. See the Settings section for allowable values. When ...
BoundaryType A value from the BoundaryTypeConstants enumeration type that determines how the times and values of the returned end points are determined.


Die BoundaryTypeConstants kann man auslesen (my $piConst = Win32::OLE::Const->Load($PI);),
mögliche Werte sind 0,1,2,3 und sollten als .NET-Enumeration vom Typ int sein (4 Bytes).

Ich habe mehrere Aufrufmöglichkeiten ausprobiert, aber die Fehlermeldung bleibt.
Hier ein Auszug der Perl-Codes:

#! /usr/bin/perl
use warnings;
use strict;
use Win32::OLE;
use Win32::OLE::Const;
use Win32::OLE::Variant;

my $PI = Win32::OLE->new('PISDK.PISDK') or die "PISDK Error: ",Win32::OLE->LastError();
my $piConst = Win32::OLE::Const->Load($PI);
#print "PiConst: $_ \t= $piConst->{$_}"
for (sort(keys(%$piConst))); # print all constants

my $server = $PI->Servers->Item("Servername") or
die "No PI server Objekt: ",Win32::OLE->LastError(),"";
my $status = $server->Open("UID=Username;PWD=Userpassword");

print_point ('PI-Tag_Name');

sub print_point {
my $piTag = $_[0];
my $point = $server->PIPoints->item($piTag);
print "piTag: $piTag Point: $point";
unless ($point) {
print "piTag $piTag kann nicht gelesen werden";
return;
}
print "\t$_ = $point->{$_}" for(sort(keys(%$point))); # ok
print "\tData: $_ = $point->Data->{$_}"
for(sort(keys(%{$point->{Data}}))); # ok
print "\tData-Snapshot: $_ = $point->Data->Snapshot->{$_}"
for(sort(keys(%{$point->Data->{Snapshot}}))); # ok
my $startTime = Variant(VT_DATE,'05.01.2015 12:00:00');
my $endTime = Variant(VT_DATE,'07.01.2015 23:45:00');
my $btFlag = Variant(VT_I4,$piConst->{btInside});
$Win32::OLE::Warn = 3;
my $recValues = $point->Data->RecordedValues
($startTime,$endTime,$btFlag); # error "Typkonflikt" at argument "BoundaryType"
my $recValues = $point->Data->RecordedValues
($startTime,$endTime,$piConst->{btInside}); # same error
my $recValues = $point->Data->RecordedValues
('05.01.2015 12:00:00','07.01.2015 12:00:00',0); # same error
my $recValues = $point->Data->RecordedValues
( {StartTime => "05.01.2015 12:00:00", # same error
EndTime => "07.01.2015 12:00:00",
BoundaryType => Variant(VT_I4,0)} ); # BoundaryType => 0}
}
 

Lesen sie die antworten

#1 michael.menge
02/02/2015 - 17:39 | Warnen spam
On Thursday, January 22, 2015 at 2:48:06 PM UTC+1, wrote:
Hallo,

ich versuche, mit OLE und dem PI-SDK der Firma Osisoft Daten aus deren PI-Datenbank zu lesen.
Es gelingt mir, Snapshotdaten eines PI-Tags zu lesen, aber beim Aufruf der Methode "RecordedValues" erhalte ich immer die Fehlermeldung
"win32::OLE(0.1711) error 0x80020005: "Typkonflikt"
in METHOD/PROPERTYGET "RecordedValues" argument "BoundaryType" at Pi.pl line ..
Möglicherweise liegt der Fehler darin, daß Perl Parameter immer per Referenz übergibt, das Argument "BoundaryType" aber per Value übergeben werden muß.

Im PI-Help-Utility findet man:

RecordedValues Method (PIData object)

This method returns compressed values for the requested time range from the archive as a PIValues collection.
Syntax
object.RecordedValues StartTime, EndTime, BoundaryType, [FilterExp], [ShowFiltered], [AsyncStatus]

The RecordedValues method syntax has these parts:
Part Description
object An object expression that evaluates to a PIData object.
StartTime A Variant containing the time. See the Settings section for allowable values.
EndTime A Variant containing the time. See the Settings section for allowable values. When ...
BoundaryType A value from the BoundaryTypeConstants enumeration type that determines how the times and values of the returned end points are determined.


Die BoundaryTypeConstants kann man auslesen (my $piConst = Win32::OLE::Const->Load($PI);),
mögliche Werte sind 0,1,2,3 und sollten als .NET-Enumeration vom Typ int sein (4 Bytes).

Ich habe mehrere Aufrufmöglichkeiten ausprobiert, aber die Fehlermeldung bleibt.
Hier ein Auszug der Perl-Codes:

#! /usr/bin/perl
use warnings;
use strict;
use Win32::OLE;
use Win32::OLE::Const;
use Win32::OLE::Variant;

my $PI = Win32::OLE->new('PISDK.PISDK') or die "PISDK Error: ",Win32::OLE->LastError();
my $piConst = Win32::OLE::Const->Load($PI);
#print "PiConst: $_ \t= $piConst->{$_}"
for (sort(keys(%$piConst))); # print all constants

my $server = $PI->Servers->Item("Servername") or
die "No PI server Objekt: ",Win32::OLE->LastError(),"";
my $status = $server->Open("UID=Username;PWD=Userpassword");

print_point ('PI-Tag_Name');

sub print_point {
my $piTag = $_[0];
my $point = $server->PIPoints->item($piTag);
print "piTag: $piTag Point: $point";
unless ($point) {
print "piTag $piTag kann nicht gelesen werden";
return;
}
print "\t$_ = $point->{$_}" for(sort(keys(%$point))); # ok
print "\tData: $_ = $point->Data->{$_}"
for(sort(keys(%{$point->{Data}}))); # ok
print "\tData-Snapshot: $_ = $point->Data->Snapshot->{$_}"
for(sort(keys(%{$point->Data->{Snapshot}}))); # ok
my $startTime = Variant(VT_DATE,'05.01.2015 12:00:00');
my $endTime = Variant(VT_DATE,'07.01.2015 23:45:00');
my $btFlag = Variant(VT_I4,$piConst->{btInside});
$Win32::OLE::Warn = 3;
my $recValues = $point->Data->RecordedValues
($startTime,$endTime,$btFlag); # error "Typkonflikt" at argument "BoundaryType"
my $recValues = $point->Data->RecordedValues
($startTime,$endTime,$piConst->{btInside}); # same error
my $recValues = $point->Data->RecordedValues
('05.01.2015 12:00:00','07.01.2015 12:00:00',0); # same error
my $recValues = $point->Data->RecordedValues
( {StartTime => "05.01.2015 12:00:00", # same error
EndTime => "07.01.2015 12:00:00",
BoundaryType => Variant(VT_I4,0)} ); # BoundaryType => 0}
}



Ich vergaß zu ergànzen:
Bei Microsoft findet sich ein Hinweis auf den Fehler (http://support.microsoft.com/kb/507620/de):
Die Fehlermeldung tritt nur auf, wenn folgende Bedingungen erfüllt sind:
*Der Parameter wird by-reference übergeben
*Der korrespondierende Visual Basic-Datentyp ist entweder Byte, Integer, Single oder Double
Dies Verhalten ist beabsichtigt.

Aber wie den Fehler vermeiden?

Ähnliche fragen