#!d:/win32apps/perl/bin/perl.exe -w
# Copyright (c) 1999-2001 by Martin Tomes. All rights reserved.
# This program is free software; you can redistribute it and/or modify it
# under the same terms as Perl itself.
# Put the path to your perl interpreter above if you are using bash as your
# shell.
# $Id: groups.pl,v 1.3 2001/01/11 10:40:40 martinto Exp $
# This example uses groups, group, items and item objects to get and set data
# from the server. You will have to supply the OPC path names of some items
# and the server they are in for this to do anything.
# It is assumed that you are using the FactorySoft OPC automation DLL which
# has the progid 'OPC.Automation'.
use strict;
use Win32::OLE::OPC qw(GetOPCServers $OPCCache $OPCDevice);
#use Win32::OLE::OLE;
#use Win32::OLE::Const;
#use Win32::OLE::Enum;
#use Win32::OLE::Lite;
#use Win32::OLE::NLS;
#use Win32::OLE::TypeInfo;
#use Win32::OLE::Variant;
use Sys::Hostname;
my $server;
my @items_read;
my %items_write;
if (hostname =~ /eurotherm.co.uk$/) {
$server = 'Kepware.KEPServerEX.V5';
@items_read = ('Channel1.Device2.lockout_test');
%items_write = ('Channel1.Device2.lockout_test' => '0');
} else {
# Put your values in here.
$server = 'Kepware.KEPServerEX.V5';
@items_read = ('Channel1.Device2.lockout_test');
%items_write = ('Channel1.Device2.lockout_test' => '0');
}
die "No server specified" unless ($server);
die "No read items specified" unless (@items_read);
die "No write items specified" unless (%items_write);
my @available_servers = GetOPCServers('OPC.Automation');
my $found_server = 0;
for my $name (@available_servers) {
$found_server = 1 if (lc($name) eq lc($server));
}
unless ($found_server) {
print "Cannot find server $server, valid choices are: ";
print join " ", @available_servers;
print "\n";
exit 1;
}
# Connect to the selected server.
my $opcintf = Win32::OLE::OPC->new('OPC.Automation', $server)
or die "Failed to connect to $server: @!";
# Map the names given in items_read and items_write to item id's.
foreach my $name (@items_read) {
# Perl sets $name to be a reference to the element in @items_read so you can
# modify it like this.
$name = $opcintf->GetItemIdFromName($name);
}
my %new_write;
foreach my $key (keys %items_write) {
my $itemid = $opcintf->GetItemIdFromName($key);
$new_write{$itemid} = $items_write{$key};
}
undef %items_write;
%items_write = %new_write;
undef %new_write;
# Fetch the OPCGroups collection as an object. The object returned is a
# reference to a hash blessed into the Win32::OLE::OPC::Groups class.
my $groups = $opcintf->OPCGroups;
# Add an anonymous group. You can pass a string parameter to
# Win32::OLE::OPC::Groups::Add(), in which case the new group takes on the
# name passed in. This returns a reference to a hash blessed into the
# Win32::OLE::OPC::Group class.
my $groupanon = $groups->Add();
# Get the items collection from the group object. This returns a reference to
# a hash blessed into the Win32::OLE::OPC::Items class.
my $items = $groupanon->OPCItems;
# Each item has an id which is assigned by the client. Generate an id for
# each item in @items_read.
my @itemids;
my $counter=0;
for my $item (@items_read) {
push @itemids, $counter++;
}
# This adds all the items in one call.
$items->AddItems($#items_read+1, [@items_read], [@itemids]);
# Now add the items to write.
my $groupwrite = $groups->Add('write');
my $witems = $groupwrite->OPCItems;
for my $item (keys(%items_write)) {
$witems->AddItem($item, $counter++);
}
# Now show the properties of each of the above objects.
sub PrintProperties {
my $properties = shift; # Takes a reference to the properties.
# Loop through the keys.
for my $prop (keys %$properties) {
if (defined($properties->{$prop})) {
printf "%24s: %s\n", $prop, $properties->{$prop};
} else {
printf "%24s: Undefined\n", $prop;
}
}
}
my %props;
%props = $groups->Properties;
print "OPCGroups Properties\n=================\n";
PrintProperties(\%props);
print "\n";
%props = $groupanon->Properties;
print "OPCGroup Properties\n=================\n";
PrintProperties(\%props);
print "\n";
%props = $items->Properties;
print "OPCItems (read) Properties\n=================\n";
PrintProperties(\%props);
print "\n";
%props = $witems->Properties;
print "OPCItems (write) Properties\n=================\n";
PrintProperties(\%props);
print "\n";
# Now print out the item properties and values for the anonymous group.
#for (my $i = 1; $i <= ($#items_read+1); $i++) {
# my $item = $items->Item($i);
# if (defined($item)) {
# %props = $item->Properties;
# print "OPCItem Properties\n=================\n";
# PrintProperties(\%props);
# print "OPCItem Data\n=================\n";
# PrintProperties($item->Read($OPCDevice)); # Reads from the device.
# print "\n";
# }
#}
# Now read, write and re-read these.
$counter = 1;
for my $item_name (keys(%items_write)) {
my $item = $items->Item($counter++); # Assume they are in order!
if (defined($item)) {
# Read everything.
%props = $item->Properties;
print "OPCItem Properties\n=================\n";
PrintProperties(\%props);
print "OPCItem Data\n=================\n";
PrintProperties($item->Read($OPCDevice)); # Reads from the device.
my $curval = $item->Read($OPCCache)->{'Value'};
$item->Write($items_write{$item_name});
sleep(2);
my $newval = $item->Read($OPCDevice)->{'Value'};
printf "%24s: %s\n", 'New Value', $newval;
$item->Write($items_write{$item_name});
$newval = $item->Read($OPCDevice)->{'Value'};
printf "%24s: %s\n", 'Set back to', $newval;
}
}
# Now get the server handle for each item and remove it from the items list.
my @server_handles;
for (my $i = 1; $i <= ($#items_read+1); $i++) {
my $item = $items->Item($i);
if (defined($item)) {
push @server_handles, $item->ServerHandle;
}
}
$counter = 1;
for my $item_name (keys(%items_write)) {
my $item = $witems->Item($counter++); # Assume they are in order!
if (defined($item)) {
push @server_handles, $item->ServerHandle;
}
}
$items->Remove(\@server_handles);
####
sub Write {
my $self = shift;
my $value = Variant(VT_VARIANT|VT_BYREF, shift);
$self->{item}->Write($value);
&Win32::OLE::OPC::_check_error("OPC::Item::Write " . $self->{_serverprogid});
}