
org.openscada.opc.lib.da.Group Maven / Gradle / Ivy
The newest version!
/*
* This file is part of the openSCADA project
* Copyright (C) 2006-2010 TH4 SYSTEMS GmbH (http://th4-systems.com)
* Copyright (C) 2014 IBH SYSTEMS GmbH (http://ibh-systems.com)
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.openscada.opc.lib.da;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import org.jinterop.dcom.common.JIException;
import org.openscada.opc.dcom.common.EventHandler;
import org.openscada.opc.dcom.common.KeyedResult;
import org.openscada.opc.dcom.common.KeyedResultSet;
import org.openscada.opc.dcom.common.Result;
import org.openscada.opc.dcom.common.ResultSet;
import org.openscada.opc.dcom.da.IOPCDataCallback;
import org.openscada.opc.dcom.da.OPCDATASOURCE;
import org.openscada.opc.dcom.da.OPCITEMDEF;
import org.openscada.opc.dcom.da.OPCITEMRESULT;
import org.openscada.opc.dcom.da.OPCITEMSTATE;
import org.openscada.opc.dcom.da.impl.OPCAsyncIO2;
import org.openscada.opc.dcom.da.impl.OPCGroupStateMgt;
import org.openscada.opc.dcom.da.impl.OPCItemMgt;
import org.openscada.opc.dcom.da.impl.OPCSyncIO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Group
{
private static Logger _log = LoggerFactory.getLogger ( Group.class );
private static Random _random = new Random ();
private Server _server = null;
private final int _serverHandle;
private OPCGroupStateMgt _group = null;
private OPCItemMgt _items = null;
private OPCSyncIO _syncIO = null;
private final Map _itemHandleMap = new HashMap ();
private final Map _itemMap = new HashMap ();
private final Map _itemClientMap = new HashMap ();
Group ( final Server server, final int serverHandle, final OPCGroupStateMgt group ) throws IllegalArgumentException, UnknownHostException, JIException
{
_log.debug ( "Creating new group instance with COM group " + group );
this._server = server;
this._serverHandle = serverHandle;
this._group = group;
this._items = group.getItemManagement ();
this._syncIO = group.getSyncIO ();
}
public void setActive ( final boolean state ) throws JIException
{
this._group.setState ( null, state, null, null, null, null );
}
public void setActive ( final boolean state, final int period ) throws JIException
{
this._group.setState ( period, state, null, null, null, null );
}
/**
* remove the group from the server
*
* @throws JIException
*/
public void remove () throws JIException
{
this._server.removeGroup ( this, true );
}
public boolean isActive () throws JIException
{
return this._group.getState ().isActive ();
}
/**
* Get the group name from the server
*
* @return The group name fetched from the server
* @throws JIException
*/
public String getName () throws JIException
{
return this._group.getState ().getName ();
}
/**
* Change the group name
*
* @param name
* the new name of the group
* @throws JIException
*/
public void setName ( final String name ) throws JIException
{
this._group.setName ( name );
}
/**
* Add a single item. Actually calls {@link #addItems(String[])} with only
* one paraemter
*
* @param item
* The item to add
* @return The added item
* @throws JIException
* The add operation failed
* @throws AddFailedException
* The item was not added due to an error
*/
public Item addItem ( final String item ) throws JIException, AddFailedException
{
final Map items = addItems ( item );
return items.get ( item );
}
/**
* Validate item ids and get additional information to them.
* According to the OPC specification you should first validate the
* items and the add them. The spec also says that when a server
* lets the item pass validation it must also let them pass the add
* operation.
*
* @param items
* The items to validate
* @return A result map of item id to result information (including error
* code).
* @throws JIException
*/
public synchronized Map> validateItems ( final String... items ) throws JIException
{
final OPCITEMDEF[] defs = new OPCITEMDEF[items.length];
for ( int i = 0; i < items.length; i++ )
{
defs[i] = new OPCITEMDEF ();
defs[i].setItemID ( items[i] );
}
final KeyedResultSet result = this._items.validate ( defs );
final Map> resultMap = new HashMap> ();
for ( final KeyedResult resultEntry : result )
{
resultMap.put ( resultEntry.getKey ().getItemID (), new Result ( resultEntry.getValue (), resultEntry.getErrorCode () ) );
}
return resultMap;
}
/**
* Add new items to the group
*
* @param items
* The items (by string id) to add
* @return A result map of id to item object
* @throws JIException
* The add operation completely failed. No item was added.
* @throws AddFailedException
* If one or more item could not be added. Item without error
* where added.
*/
public synchronized Map addItems ( final String... items ) throws JIException, AddFailedException
{
// Find which items we already have
final Map handles = findItems ( items );
final List foundItems = new ArrayList ( items.length );
final List missingItems = new ArrayList ();
// separate missing items from the found ones
for ( final Map.Entry entry : handles.entrySet () )
{
if ( entry.getValue () == null )
{
missingItems.add ( entry.getKey () );
}
else
{
foundItems.add ( entry.getValue () );
}
}
// now fetch missing items from OPC server
final Set newClientHandles = new HashSet ();
final OPCITEMDEF[] itemDef = new OPCITEMDEF[missingItems.size ()];
for ( int i = 0; i < missingItems.size (); i++ )
{
final OPCITEMDEF def = new OPCITEMDEF ();
def.setItemID ( missingItems.get ( i ) );
def.setActive ( true );
Integer clientHandle;
do
{
clientHandle = _random.nextInt ();
} while ( this._itemClientMap.containsKey ( clientHandle ) || newClientHandles.contains ( clientHandle ) );
newClientHandles.add ( clientHandle );
def.setClientHandle ( clientHandle );
itemDef[i] = def;
}
// check the result and add new items
final Map failedItems = new HashMap ();
final KeyedResultSet result = this._items.add ( itemDef );
int i = 0;
for ( final KeyedResult entry : result )
{
if ( entry.getErrorCode () == 0 )
{
final Item item = new Item ( this, entry.getValue ().getServerHandle (), itemDef[i].getClientHandle (), entry.getKey ().getItemID () );
addItem ( item );
foundItems.add ( item.getServerHandle () );
}
else
{
failedItems.put ( entry.getKey ().getItemID (), entry.getErrorCode () );
}
i++;
}
// if we have failed items then throw an exception with the result
if ( failedItems.size () != 0 )
{
throw new AddFailedException ( failedItems, findItems ( foundItems ) );
}
// simply return the result in case of success
return findItems ( foundItems );
}
private synchronized void addItem ( final Item item )
{
_log.debug ( String.format ( "Adding item: '%s', %d", item.getId (), item.getServerHandle () ) );
this._itemHandleMap.put ( item.getId (), item.getServerHandle () );
this._itemMap.put ( item.getServerHandle (), item );
this._itemClientMap.put ( item.getClientHandle (), item );
}
private synchronized void removeItem ( final Item item )
{
this._itemHandleMap.remove ( item.getId () );
this._itemMap.remove ( item.getServerHandle () );
this._itemClientMap.remove ( item.getClientHandle () );
}
protected Item getItemByOPCItemId ( final String opcItemId )
{
final Integer serverHandle = this._itemHandleMap.get ( opcItemId );
if ( serverHandle == null )
{
_log.debug ( String.format ( "Failed to locate item with id '%s'", opcItemId ) );
return null;
}
_log.debug ( String.format ( "Item '%s' has server id '%d'", opcItemId, serverHandle ) );
return this._itemMap.get ( serverHandle );
}
private synchronized Map findItems ( final String[] items )
{
final Map data = new HashMap ();
for ( int i = 0; i < items.length; i++ )
{
data.put ( items[i], this._itemHandleMap.get ( items[i] ) );
}
return data;
}
private synchronized Map findItems ( final Collection handles )
{
final Map itemMap = new HashMap ();
for ( final Integer i : handles )
{
final Item item = this._itemMap.get ( i );
if ( item != null )
{
itemMap.put ( item.getId (), item );
}
}
return itemMap;
}
protected void checkItems ( final Item[] items )
{
for ( final Item item : items )
{
if ( item.getGroup () != this )
{
throw new IllegalArgumentException ( "Item does not belong to this group" );
}
}
}
public void setActive ( final boolean state, final Item... items ) throws JIException
{
checkItems ( items );
final Integer[] handles = new Integer[items.length];
for ( int i = 0; i < items.length; i++ )
{
handles[i] = items[i].getServerHandle ();
}
this._items.setActiveState ( state, handles );
}
protected Integer[] getServerHandles ( final Item[] items )
{
checkItems ( items );
final Integer[] handles = new Integer[items.length];
for ( int i = 0; i < items.length; i++ )
{
handles[i] = items[i].getServerHandle ();
}
return handles;
}
public synchronized Map- write ( final WriteRequest... requests ) throws JIException
{
final Item[] items = new Item[requests.length];
for ( int i = 0; i < requests.length; i++ )
{
items[i] = requests[i].getItem ();
}
final Integer[] handles = getServerHandles ( items );
final org.openscada.opc.dcom.da.WriteRequest[] wr = new org.openscada.opc.dcom.da.WriteRequest[items.length];
for ( int i = 0; i < items.length; i++ )
{
wr[i] = new org.openscada.opc.dcom.da.WriteRequest ( handles[i], requests[i].getValue () );
}
final ResultSet
resultSet = this._syncIO.write ( wr );
final Map- result = new HashMap
- ();
for ( int i = 0; i < requests.length; i++ )
{
final Result
entry = resultSet.get ( i );
result.put ( requests[i].getItem (), entry.getErrorCode () );
}
return result;
}
public synchronized Map- read ( final boolean device, final Item... items ) throws JIException
{
final Integer[] handles = getServerHandles ( items );
final KeyedResultSet
states = this._syncIO.read ( device ? OPCDATASOURCE.OPC_DS_DEVICE : OPCDATASOURCE.OPC_DS_CACHE, handles );
final Map- data = new HashMap
- ();
for ( final KeyedResult
entry : states )
{
final Item item = this._itemMap.get ( entry.getKey () );
final ItemState state = new ItemState ( entry.getErrorCode (), entry.getValue ().getValue (), entry.getValue ().getTimestamp ().asCalendar (), entry.getValue ().getQuality () );
data.put ( item, state );
}
return data;
}
public Server getServer ()
{
return this._server;
}
public synchronized void clear () throws JIException
{
final Integer[] handles = this._itemMap.keySet ().toArray ( new Integer[0] );
try
{
this._items.remove ( handles );
}
finally
{
// in any case clear our maps
this._itemHandleMap.clear ();
this._itemMap.clear ();
this._itemClientMap.clear ();
}
}
public synchronized OPCAsyncIO2 getAsyncIO20 ()
{
return this._group.getAsyncIO2 ();
}
/**
* Set part of the group state
*
* Each of the parameters may be null
in which the parameter is
* not changed.
*
*
* @param requestedUpdateRate
* the requested update rate. Note: that the server may
* return a different update rate.
* @param timeBias
* the new time bias value
* @param percentDeadband
* the new percent deadband value
* @throws JIException
* if anything in the OPC communication or on the server goes
* wrong
* @since 1.3.0
*/
public void setGroupState ( final Integer requestedUpdateRate, final Integer timeBias, final Float percentDeadband ) throws JIException
{
this._group.setState ( requestedUpdateRate, null, timeBias, percentDeadband, null, null );
}
public synchronized EventHandler attach ( final IOPCDataCallback dataCallback ) throws JIException
{
return this._group.attach ( dataCallback );
}
public Item findItemByClientHandle ( final int clientHandle )
{
return this._itemClientMap.get ( clientHandle );
}
public int getServerHandle ()
{
return this._serverHandle;
}
public synchronized void removeItem ( final String opcItemId ) throws IllegalArgumentException, UnknownHostException, JIException
{
_log.debug ( String.format ( "Removing item '%s'", opcItemId ) );
final Item item = getItemByOPCItemId ( opcItemId );
if ( item != null )
{
this._group.getItemManagement ().remove ( item.getServerHandle () );
removeItem ( item );
_log.debug ( String.format ( "Removed item '%s'", opcItemId ) );
}
else
{
_log.warn ( String.format ( "Unable to find item '%s'", opcItemId ) );
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy