nonnonymousnonk has asked for the wisdom of the Perl Monks concerning the following question:

Hi Monks,

Has anyone per chance worked at all with OPC & perl? Specifically the package Win32::OLE::OPC. I'm having a mare of a time with it. My latest problem is writing data, here's the relavent code:

my $itemdata = OPCItemRead ($rightdata[0], $i+1); $rightdata[0]->{lastvalues}->[$i] = $itemdata->{Value}; OPCItemWrite($rightdata[0], $i+1, $rightdata[0]->{lastvalues}->[$i +] + 1);
And the subs

sub OPCItemRead { my $groupdata = shift; my $itemno = shift; my $items; my $data; # reference to the ha +sh of data returned by Read() $items = $groupdata->{grouphandle}->OPCItems(); $data = $items->Item($itemno)->Read($OPCDevice); } sub OPCItemWrite { my $groupdata = shift; my $itemno = shift; my $newvalue = shift; my $items; $items = $groupdata->{grouphandle}->OPCItems(); $items->Item($itemno)->Write($newvalue); }
The read function works absolutely fine, the write always gives:
OPC::Item::Write Matrikon.OPC.DDE: Win32::OLE(0.1707) error 0x80070057: "The parameter is incorrect" in METHOD/PROPERTYGET "Write" at C:/Program Files/Perl/lib/Win32/OLE/OPC.pm line 1666
If I stop the debugger in the write function just before the write $groupdata, $itemno and $newvalue all look fine. If I do this
x $items->Item($itemno)->Read($OPCDevice)
I get the expected data hash so I'm sure everything is set up correctly. As soon as I execute the write up pops this more verbose version of the same error:
OPC::Item::Write Matrikon.OPC.DDE: Win32::OLE(0.1707) error 0x80070057: "The parameter is incorrect" in METHOD/PROPERTYGET "Write" at C:/Program Files/Perl/lib/Win32/OLE/OPC.pm line 1666 at C:/Program Files/Perl/lib/Win32/OLE/OPC.pm line 123 Win32::OLE::OPC::_check_error('OPC::Item::Write Matrikon.OPC.D +DE') called at C:/Program Files/Perl/lib/Win32/OLE/OPC.pm line 1666 Win32::OLE::OPC::Item::Write('Win32::OLE::OPC::Item=HASH(0x22c +2360)', 11) called at opccompare.pl line 542 main::OPCItemWrite('HASH(0x2291d14)', 5, 11) called at opccomp +are.pl line 151 main::(opccompare.pl:154): if (not($debug + =~ m/quiet/)) {
All the man for this method says is
<b>Write(VALUE)</b> Write VALUE to this item.
So taking the error message at face value perhaps I'm expressing VALUE incorrectly. I've tried passing a ref to the data instead of the data value and it makes no difference. I've tried a bare value, a quoted value and a double quoted value. I've tried using a hash like the Read() returns or a ref to that hash. Apart from Swahili, Sanskrit or Welsh I've expressed VALUE in every way I can think of. Here's an online version of the help http://www.opcconnect.com/perl/OPC.html#opcitem

The example supplied with the package, groups.pl, gives exactly the same error for writes. Any monks in the monestary familiar with OPC?

Cheers
nonk

Replies are listed 'Best First'.
Re: Win32::OLE error
by Anonymous Monk on Oct 15, 2007 at 11:16 UTC

    Try turning the last parameter to your OPCItemWrite call into a string. Some servers are sensitive to the actual type of the data in the variant. I think you might have tried that though.

    Someone else had a similar problem, he started out with this code (which gave the error):

    use Win32::OLE::OPC; use CGI qw(:all); $opcintf = Win32::OLE::OPC->new('OPC.Automation','hci.phd'); $group = $opcintf->OPCGroups->Add('sanitize_mode'); $items = $group->OPCItems(); $reset_item = $items->AddItems("6440SAN2.PV", 999); $reset_item->Write('SANITIZE');

    and this is the code once he got it working:

    use Win32::OLE::OPC; use CGI qw(:all); $opcintf = Win32::OLE::OPC->new('OPC.Automation','hci.phd'); $group = $opcintf->OPCGroups->Add('san_grp'); my $items = $group->OPCItems; $items->AddItem( '6440SAN2.PV', 0 ); $item = $items->Item(1); $item->Write('NORMAL');

    You don't show how you are creating the groups, that might have something to do with it.

      I was just trying this as well with the same problem. Since most of the values I am trying to write are VT_R4, I changed the line 1559 in the OPC.pm module from: my $value = Variant(VT_VARIANT|VT_BYREF, shift); to my $value = Variant(VT_R4|VT_BYREF, shift); and voila!! it works fine. And this mod begs the question, What about other types?...
      Since most OPC servers are pretty good at doing the type conversions, try changing the VT_R4 described previously to VT_BSTR. That should take your scalar value as a number or string and pass it to the OPC Server as a string. The OPC server should then be able to decode it back to whatever it needs. It worked with my OPC Server that expected VT_R4 data.