![]() |
email:
call: 1-780-784-4444 |
| You are here: Home > Downloads & Resources > Articles | |
Understanding OPC Server development using .NETAuthor: Advosol Inc.
|
| Server Type | Main Module | Starts: | Runs as: |
| Out-of-process COM server | EXE | When a client connects | COM server |
| Windows Service | EXE | At Windows startup or when client connects | Windows service (accessed as COM server) |
| XML DA web service | DLL | At access from a client | Web Service |
| XML DA self-hosted WCF | EXE | Started as Process | WCF Service or Web Service |
With the application part of the OPC server in a DLL the same DLL can be used with all type of servers. The generic server is built for the appropriate server type.
How much server functionality can be handled in the generic server part depends on the implemented OPC specification.
The Advosol .NET server toolkits are designed as follows:
| OPC Specification | Generic server functionality |
| DA (Data Access) | The generic server maintains a data cache and handles the client notifications whenever necessary due to value changes or client actions. Basically the application part can simply write new values into the cache. The usage is very simple but still highly flexible. The set of items in the cache may be static or dynamic and the generic server can be configured for optimized handling in applications with either, many items and rather few changes or a lower number of items with a high data change rate. |
| XML DA | The XML DA specification defines functionality similar to the OPC DA specification. The XML DA server toolkit has a generic part with the same customization DLL interface and can use the same application DLLs as the OPC DA server toolkit. |
| AE (Alarms & Events) | The OPC AE specification allows the handling of very different kind of events. Not much functionality can be implemented in the generic server without imposing restrictions. The generic server is basically only a .Net wrapper for client calls and OnEvent callbacks. |
| HDA (Historical Data Access | The many data selection options defined in the OPC HDA specification may have to be handled in the data base query or in an application specific way. The generic server is therefore basically only a .Net wrapper for client calls and callbacks. |
The best solution is to implement the application in two processes, the main application in one and the OPC server in another. The inter-process communication can be implemented with .NET2 Remoting classes or with .NET3 WCF classes (Windows Communication Foundation).
This approach works identically with different application types such as:
and different OPC server types:
The OPC server has two interfaces:
WCF based data exchange is simple to implement and highly flexible. The type of communication is defined in the application configuration file. For on-machine data exchange the high performance "Named Pipe" binding is recommended.
|
|
|
<system.serviceModel> |
|
WCF Client Configuration |
|
<system.serviceModel> |
Interface Definition
The interface is internal between the application and the OPC server implementation and can be defined in any way. The definition is used by the service and client application. It defines the methods the WCF client can call for the data exchange.
public class
ServerAccess : ServerAccessChn
{
// method to write an item value into
the OPC DA / XML DA server cache
public int SetItemValue(string
itemName, object val)
{
ItemDef
itm = (ItemDef)AppPlugin.CacheItemIndex[itemName];
if (itm ==
null)
return HRESULTS.OPC_E_INVALIDITEMID;
else
{
try
{
object v = Convert.ChangeType(val, AppPlugin.Items[itm.Handle].Value.GetType());
// write new value into the server cache
return GenericServer.SetItemValue(itm.Handle,
v, (short)OPCQuality.GOOD,
DateTime.Now);
}
catch
{
return HRESULTS.OPC_E_BADTYPE;
}
}
}
}
ServiceHost customerServiceHost = new ServiceHost(typeof(ServerAccess));
customerServiceHost.Open();
private void Form1_Load(object sender, System.EventArgs
e)
{
// activate the WCF channel to the OPC
server
ChannelFactory<ServerAccessChn> fact = new ChannelFactory<ServerAccessChn>("ServerAccess");
SrvAcc = fact.CreateChannel();
}
ServerAccessChn SrvAcc;
private void
btnWrite1_Click(object sender, System.EventArgs e)
{
int rtc =
SrvAcc.SetItemValue(cbItemName1.Text, tbItem1.Text);
}
Advosol Inc © 2007
Reproduced with permission
| You are here: Home > Downloads & Resources > Articles |