自动控可能大都是用wincc来完成的,由于当时我对wincc 不熟悉,所以想用自己的熟悉的编成工具来完成计算机到西门子plc的控制,于是我翻遍了互联网,在外国一个网站http://www.viscomvisual.com/dotnet/上找到了一个 OPCClient 并且包含代码,自己分析了他们提供的代码,然后自己写了一个简单的opcclient, 把plc内部的控制过程通过pc来实现,并且很快完成了目标程序,但是甲方要求必须使用wincc,我只好放弃了自己编写的opcclient ,最后通过自己的努力用wincc完成了所有的项目,但是对于自己来说这是一个锻炼的机会。今天我把我查找的网址和部分代码贴出来,大家共同学习,同时感谢http://www.viscomvisual.com。如果下面的代码侵害了你们的利益,请和我联系,我会及时这个删除这个帖子,我只是通过学习和分析了下面的源码,并没有照抄和用于商业应用。谢谢大家和我共同讨论。
public bool DoInit()
{
try
{
SelServer frmSelSrv = new SelServer( ); // create form and let user select a name
frmSelSrv.ShowDialog( this );
if( frmSelSrv.selectedOpcSrv == null )
this.Close();
selectedOpcSrv = frmSelSrv.selectedOpcSrv; // OPC server ProgID
txtServer.Text = selectedOpcSrv;
// ---------------
theSrv = new OpcServer();
if( ! DoConnect( selectedOpcSrv ) )
return false;
// add event handler for server shutdown
theSrv.ShutdownRequested += new ShutdownRequestEventHandler( this.theSrv_ServerShutDown );
// precreate the only OPC group in this example
if( ! CreateGroup() )
return false;
// browse the namespace of the OPC-server
if( ! DoBrowse() )
return false;
}
catch( Exception e ) // exceptions MUST be handled
{
MessageBox.Show( this, "init error! " + e.ToString(), "Exception", MessageBoxButtons.OK, MessageBoxIcon.Warning );
return false;
}
return true;
}
// connect to OPC server via ProgID
public bool DoConnect( string progid )
{
try
{
theSrv.Connect( progid );
Thread.Sleep( 100 );
theSrv.SetClientName( "DirectOPC " + thisprocess.Id ); // set my client name (exe+process no)
// MessageBox.Show("DirectOPC " + thisprocess.Id);
SERVERSTATUS sts;
theSrv.GetStatus( out sts );
// get infos about OPC server
StringBuilder sb = new StringBuilder( sts.szVendorInfo, 200 );
sb.AppendFormat( " ver:{0}.{1}.{2}", sts.wMajorVersion, sts.wMinorVersion, sts.wBuildNumber );
txtServerInfo.Text = sb.ToString();
// set status bar text to show server state
sbpTimeStart.Text = DateTime.FromFileTime( sts.ftStartTime ).ToString();
sbpStatus.Text = sts.eServerState.ToString();
}
catch( COMException )
{
MessageBox.Show( this, "connect error!", "Exception", MessageBoxButtons.OK, MessageBoxIcon.Warning );
return false;
}
return true;
}
public bool CreateGroup()
{
try
{
// add our only working group
theGrp = theSrv.AddGroup( "OPCdotNET-Group", true, 500 );
// add event handler for data changes
theGrp.DataChanged += new DataChangeEventHandler( this.theGrp_DataChange );
theGrp.WriteCompleted += new WriteCompleteEventHandler( this.theGrp_WriteComplete );
}
catch( COMException )
{
MessageBox.Show( this, "create group error!", "Exception", MessageBoxButtons.OK, MessageBoxIcon.Warning );
return false;
}
return true;
}
// event handler: called if any item in group has changed values
protected void theGrp_DataChange( object sender, DataChangeEventArgs e )
{
Trace.WriteLine( "theGrp_DataChange id=" + e.transactionID.ToString() + " me=0x" + e.masterError.ToString( "X" ) );
foreach( OPCItemState s in e.sts )
{
if( s.HandleClient != itmHandleClient ) // only one client handle
continue;
Trace.WriteLine( " item error=0x" + s.Error.ToString( "X" ) );
if( HRESULTS.Succeeded( s.Error ) )
{
Trace.WriteLine( " val=" + s.DataValue.ToString() );
txtItemValue.Text = s.DataValue.ToString(); // update screen
txtItemQual.Text = OpcGroup.QualityToString( s.Quality );
txtItemTimeSt.Text = DateTime.FromFileTime( s.TimeStamp ).ToString();
}
else
{
txtItemValue.Text = "ERROR 0x" + s.Error.ToString( "X" );
txtItemQual.Text = "error";
txtItemTimeSt.Text = "error";
}
}
}
// event handler: called if asynch write finished
protected void theGrp_WriteComplete( object sender, WriteCompleteEventArgs e )
{
foreach( OPCWriteResult w in e.res )
{
if( w.HandleClient != itmHandleClient ) // only one client handle
continue;
if( HRESULTS.Failed( w.Error ) )
txtItemWriteRes.Text = "ERROR 0x" + w.Error.ToString( "X" );
else
txtItemWriteRes.Text = "ok";
}
}
public bool DoBrowse()
{
try
{
OPCNAMESPACETYPE opcorgi = theSrv.QueryOrganization();
// fill TreeView with all
treeOpcItems.Nodes.Clear();
TreeNode tnRoot = new TreeNode( rootname, 0, 1 );
if( opcorgi == OPCNAMESPACETYPE.OPC_NS_HIERARCHIAL )
{
theSrv.ChangeBrowsePosition( OPCBROWSEDIRECTION.OPC_BROWSE_TO, "" ); // to root
RecurBrowse( tnRoot, 1 );
}
treeOpcItems.Nodes.Add( tnRoot );
tnRoot.ExpandAll(); // expand all nodes ([+] -> [-])
tnRoot.EnsureVisible(); // make the root visible
// preselect root (dummy)
treeOpcItems.SelectedNode = tnRoot; // force treeOpcItems_AfterSelect
}
catch( COMException /* eX */ )
{
MessageBox.Show( this, "browse error!", "DoBrowse", MessageBoxButtons.OK, MessageBoxIcon.Warning );
return false;
}
return true;
}
// recursively call the OPC namespace tree
public bool RecurBrowse( TreeNode tnParent, int depth )
{
try
{
ArrayList lst;
theSrv.Browse( OPCBROWSETYPE.OPC_BRANCH, out lst );
if( lst == null )
return true;
if( lst.Count < 1 )
return true;
foreach( string s in lst )
{
TreeNode tnNext = new TreeNode( s, 0, 1 );
theSrv.ChangeBrowsePosition( OPCBROWSEDIRECTION.OPC_BROWSE_DOWN, s );
RecurBrowse( tnNext, depth + 1 );
theSrv.ChangeBrowsePosition( OPCBROWSEDIRECTION.OPC_BROWSE_UP, "" );
tnParent.Nodes.Add( tnNext );
}
}
catch( COMException /* eX */ )
{
MessageBox.Show( this, "browse error!", "RecurBrowse", MessageBoxButtons.OK, MessageBoxIcon.Warning );
return false;
}
return true;
}
public bool ViewItem( string opcid )
{
try
{
RemoveItem(); // first remove previous item if any
itmHandleClient = 1234;
OPCItemDef[] aD = new OPCItemDef[1];
aD[0] = new OPCItemDef( opcid, true, itmHandleClient, VarEnum.VT_EMPTY );
OPCItemResult[] arrRes;
theGrp.AddItems( aD, out arrRes );
if( arrRes == null )
return false;
if( arrRes[0].Error != HRESULTS.S_OK )
return false;
btnItemMore.Enabled = true;
itmHandleServer = arrRes[0].HandleServer;
itmAccessRights = arrRes[0].AccessRights;
itmTypeCode = VT2TypeCode( arrRes[0].CanonicalDataType );
txtItemID.Text = opcid;
txtItemDataType.Text = DUMMY_VARIANT.VarEnumToString( arrRes[0].CanonicalDataType );
if( (itmAccessRights & OPCACCESSRIGHTS.OPC_READABLE) != 0 )
{
int cancelID;
theGrp.Refresh2( OPCDATASOURCE.OPC_DS_DEVICE, 7788, out cancelID );
}
else
txtItemValue.Text = "no read access";
if( itmTypeCode != TypeCode.Object ) // Object=failed!
{
// check if write is premitted
if( (itmAccessRights & OPCACCESSRIGHTS.OPC_WRITEABLE) != 0 )
btnItemWrite.Enabled = true;
}
}
catch( COMException )
{
MessageBox.Show( this, "AddItem OPC error!", "ViewItem", MessageBoxButtons.OK, MessageBoxIcon.Warning );
return false;
}
return true;
}
// remove previous OPC item if any
public bool RemoveItem()
{
try
{
if( itmHandleClient != 0 )
{
itmHandleClient = 0;
txtItemID.Text = ""; // clear screen texts
txtItemValue.Text = "";
txtItemDataType.Text = "";
txtItemQual.Text = "";
txtItemTimeSt.Text = "";
txtItemSendValue.Text = "";
txtItemWriteRes.Text = "";
btnItemWrite.Enabled = false;
btnItemMore.Enabled = false;
int[] serverhandles = new int[1] { itmHandleServer };
int[] remerrors;
theGrp.RemoveItems( serverhandles, out remerrors );
itmHandleServer = 0;
}
}
catch( COMException )
{
MessageBox.Show( this, "RemoveItem OPC error!", "RemoveItem", MessageBoxButtons.OK, MessageBoxIcon.Warning );
return false;
}
return true;
}