このプログラムは1週間テストされ、C#がOPCDAAuto.dllを呼び出してKEPserverとPLC通信をリンクし、OPCを介して市場の主流PLCに接続する方法をついに理解しました。具体的なコードは次のとおりです。プログラムのソースコードまたはプロジェクトプログラムの友人あなたは私に連絡することができます+ V:1357448516。
システムを使用する;
System.Collections.Genericを使用する;
System.Collectionsを使用します。
System.ComponentModelを使用します。
System.Dataを使用します。
System.Drawingを使用します。
System.Linqを使用する;
System.Textを使用します。
System.Windows.Formsを使用する;
OPCAutomationを使用します。
System.Diagnosticsを使用します。
System.Threadingを使用します。
名前空間OPC_Client
{ パブリック部分クラスForm1:フォーム { OPCServer objServer; OPCGroups objGroups; OPCGroup objGroup; OPCItems objItems; OPCItem [] objChangeItem; 配列strItemIDs; 配列lClientHandles;
Array lserverhandles;
Array lErrors;
string State;
// int ltransID_Rd = 1;
// int lCancelID_Rd;
object RequestedDataTypes = null;
object AccessPaths = null;
// Array lerrors_Rd;
Array lErrors_Wt;
int lTransID_Wt = 2;
int lCancelID_QualityState;
int op / / OPCおよびPLCリンクステータス
//ステータス表示列挙
プライベートデリゲートvoidOPCtimer(string text);
// OPCおよびPLCリンクステータス
プライベートデリゲートvoidOPCtoPlcState(int PLCstate);
//タイマー
System.Windows.Forms.Timertim;
// OPCリンクタイマー
System.Windows.Forms.Timer OPCconnectTimer;
public Form1()
{ InitializeComponent(); } private void Form1_Load(object sender、EventArgs e) { // OPCリンクタイマーの初期化 OPCconnectTimer = new System.Windows.Forms.Timer(); OPCconnectTimer .Interval = 1000; OPCconnectTimer.Tick + = new EventHandler(OPCconnectTimer_Tick); OPCconnectTimer.Enabled = true; //リンク状態タイマーを初期化します tim = new System.Windows.Forms.Timer(); // 1Sタイミングタイマーを定義します; tim.Interval = 1500;
tim.Tick + = new EventHandler(theout); //時間切れ後にoutイベントを実行します;
tim.Enabled = true ;; //System.Timers.Timer.Elapsedイベントを実行するかどうか;
//(1)opcを作成しますサーバーオブジェクト
objServer = new OPCServer();
objChangeItem = new OPCItem [4];
}
/// <summary>
///ステータス表示タイマートリガーイベント
/// </ summary>
/// <param name = "source"> </ param>
/// <param name = "e"> </ param>
private void theout(object sender、EventArgs e)
{ tim.Interval = 1500; // OPCリンク状態 State = objServer.ServerState.ToString() ; SetOPCstate(State);
// OPC与PLC链接
状态opcQualityState = opcQualityJudge();
changeLightStatus(opcQualityState);
}
#regionOPC链接状态適
用表示privatevoid SetOPCstate(string text)
{ if(label3.InvokeRequired) { OPCtimer opcdelateTimer = new OPCtimer(InvokeMessage); this.Invoke(opcdelateTimer、text); } else { this.label3.Text = text; } } private void InvokeMessage(string text) {
this.label3.Text = text;
}
#endregion
#regionOPCおよびPLCリンクステータスインジケーターは
privatevoid changeLightStatus(int PLCstate)
{ if(label13.InvokeRequired) { OPCtoPlcState sl = new OPCtoPlcState(InvokeLight); this.Invoke(sl、 PLCstate); } else { スイッチ(PLCstate) { ケース1: this.label13.BackColor = Color.Green; this.label13.Text = "Connected"; break;
ケース0:
this.label13.BackColor = Color.Red;
this.label13.Text = "未未接";
this.Data1.Text = "0";
this.Data2.Text = "0";
ブレーク;
}
}
}
private void InvokeLight(int light)
{ switch(light) { case 1: this.label13.BackColor = Color.Green; this.label13.Text = "已006接"; ブレーク; ケース0:
this.label13.BackColor = Color.Red;
this.label13.Text = "Unconnected" ; this.Data1.Text = "
0";
this.Data2.Text = "0";
break;
}
}
/// <summary>
/// OPCとPLCのリンクステータスを判断します。戻り値1はリンクを意味し、戻り値0は切断を意味します。
///各OPCアイテムの品質情報を順番に判断します。品質が0の変数がある場合、その変数は切断されていると見なされます。
/// </ summary>
/// <returns> </ returns>
private int opcQualityJudge()
{ int [] opcQuality = new int [4]; for(int i = 1; i <4;
if(opcQuality [i]!= 192)
{ return 0; } } return 1; } #endregion // opcサーバーを終了して切断し ますprivatevoid button4_Click(object sender、EventArgs e) { //すべてのグループリソースを解放し ますif(null! = objGroup) { objGroup.DataChange- = new DIOPCGroupEvent_DataChangeEventHandler(KepGroup_DataChange); objGroup.AsyncWriteComplete- = new DIOPCGroupEvent_AsyncWriteCompleteEventHandler(AsyncWriteComplete); objGroup = null;
objServer.OPCGroups.RemoveAll();
}
if(null!= objServer)
{ objServer.Disconnect() ; objServer = null; objItems = null; this.Data1.Text = "0"; this.Data2.Text = "0" ; this.label3.Text = State.ToString(); GC.Collect(); } // kepserverプロセスを閉じます。これはOPC操作とは関係ありません / * foreach(Process oneProcess in Process.GetProcesses()) { if (oneProcess.ProcessName == "ServerMain") oneProcess.Kill();
}
* /
}
//アイテムデータが変更されるたびに、サブスクリプションメソッドを使用します
void KepGroup_DataChange(int TransactionID、int NumItems、ref Array ClientHandles、ref Array ItemValues、ref Array Qualities、ref Array TimeStamps)
{ //テスト用なので、追加しましたトランザクションID番号を表示するためのコンソール出力 //Console.WriteLine("********"+ TransactionID.ToString ()+ "********"); for(int i = 0; i <NumItems; i ++) { if(Convert.ToInt32(ClientHandles.GetValue(i + 1))== 1) { if(ItemValues.GetValue(i + 1)!= null) {
this.Data1.Text = ItemValues.GetValue(i + 1).ToString();
}
}
if(Convert.ToInt32(ClientHandles.GetValue(i + 1))== 2)
{ if(ItemValues.GetValue(i + 1)!= null) { this.Data2.Text = ItemValues.GetValue(i + 1 ).ToString(); //this.label5.Text = Qualities.GetValue(i + 1).ToString(); // int品質; //品質= objChangeItem [2] .Quality; //label5.Text = quality.ToString(); } }
if(Convert.ToInt32(ClientHandles.GetValue(i + 1))== 3)
{ if(ItemValues.GetValue(i + 1)!= null) { this.Data3.Text = ItemValues.GetValue(i + 1)。 ToString(); } } if(Convert.ToInt32(ClientHandles.GetValue(i + 1))== 4) { if(ItemValues.GetValue(i + 1)!= null) { this.Data4.Text = ItemValues.GetValue(i + 1 ).ToString(); } }
if(Convert.ToInt32(ClientHandles.GetValue(i + 1))== 5)
{ if(ItemValues.GetValue(i + 1)!= null) { this.Data5.Text = ItemValues.GetValue(i + 1)。 ToString(); } } if(Convert.ToInt32(ClientHandles.GetValue(i + 1))== 6) { if(ItemValues.GetValue(i + 1)!= null) { this.Data6.Text = ItemValues.GetValue(i + 1 ).ToString(); } } } }
void AsyncReadComplete(int TransactionID、int NumItems、ref Array ClientHandles、ref Array ItemValues、ref Array Qualities、ref Array TimeStamps、ref Array Error )
{ MessageBox.Show( "Read Complete"); label11.Text = "Connect on"; } //非同期データ書き込み命令を送信し ますprivatevoid button3_Click(object sender、EventArgs e) { Array AsyncValue_Wt; Array SerHandles; object [] tmpWtData = new object [3]; //書き込まれるデータはオブジェクトタイプである必要があり、そうでない場合はエラーになります int [] tmpSerHdles = new int [3]; //入力データを配列に割り当て、それを配列型に変換してAsyncValue_Wtに送信します 。tmpWtData[1] =(object)textBox1.Text;
tmpWtData [2] =(object)textBox2.Text;
AsyncValue_Wt =(Array)tmpWtData;
//入力データによって送信されたアイテムに対応するサーバーハンドルを配列に割り当て、それを配列型に変換してに送信します。 SerHandles
tmpSerHdles [1] = Convert .ToInt32(lserverhandles.GetValue(1));
tmpSerHdles [2] = Convert.ToInt32(lserverhandles.GetValue(2));
SerHandles =(Array)tmpSerHdles;
objGroup.AsyncWrite(2、ref SerHandles 、ref AsyncValue_Wt、out lErrors_Wt、lTransID_Wt、out lCancelID_Wt);
// objChangeItem [1] .Writeを使用してこの文でデータを書き込みますが、書き込みイベントはトリガーされません。
objChangeItem [1] = objItems.GetOPCItem(Convert.ToInt32(lserverhandles.GetValue(1))); // objChangeItem [1] .Write(
102);
}
//非同期書き込みの成功
private void AsyncWriteComplete(int TransactionID、int NumItems、ref Array ClientHandles、ref Array Error)
{ MessageBox.Show( "データが正常に書き込まれました!"); } /// <summary> /// OPCの初期化 ///タイミングのタイミング次のイベントがトリガーされます ///起動後、OPCは1秒の遅延後に初期化されます。10秒後、OPCとのリンク遷移を確認します。リンクが切断されている場合は、OPCを再接続して初期化します /// </要約> /// <param name = "sender"> </ param> /// <param name = "e"> </ param> void OPCconnectTimer_Tick(object sender、EventArgs e) { try { OPCconnectTimer.Interval = 10000; if(objServer 。ServerState!= 1)
{ 接続opcサーバー objServer.Connect( "KEPware.KEPServerEx.V4"、 ""); //(2) opcグループのセットを作成します objGroups = objServer.OPCGroups ; //(3)opcグループを作成しますobjGroup = objGroups。 Add(null); //グループグループ名はオプションです //(4)opcタグを追加し ますobjGroup.IsActive = true; //グループをアクティブに設定します。PLCに接続する場合は、非アクティブに設定するのと同じです。 。 objGroup.IsSubscribed =真; //設定非同期通知まで objGroup.UpdateRate = 250; objServer.OPCGroups.DefaultGroupDeadband = 0;
objGroup.DataChange + = new DIOPCGroupEvent_DataChangeEventHandler(KepGroup_DataChange);
objGroup.AsyncReadComplete + = new DIOPCGroupEvent_AsyncReadCompleteEventHandler(AsyncReadComplete);
objGroup.AsyncWriteComplete + = new DIOPCGroupEvent_AsyncWriteCompleteEventHandler(AsyncWriteComplete);
objItems = objGroup.OPCItems; //建立opc¸签集合
文字列[] tmpIDs =新しい文字列[7];
int [] tmpCHandles = new int [7];
for(int i = 1; i <7; i ++)
{ tmpCHandles [i] = i; } tmpIDs [1] = "Channel1.Device1.m0";
tmpIDs [2] = "Channel1.Device1.m03";
tmpIDs [3] = "Channel1.Device1.m1";
strItemIDs =(Array)tmpIDs; //必须変換成Array型、否则不可调用PASSWORDsメソッド
lClientHandles =(Array)tmpCHandles;
//追加opc¸签
objItems.PASSWORDs(3、ref strItemIDs、ref lClientHandles、out lserverhandles、out lErrors、RequestedDataTypes、AccessPaths);
for(int i = 1; i <4; i ++)
{ objChangeItem [i] = objItems.GetOPCItem(Convert.ToInt32(lserverhandles.GetValue(i))); } } } catch(例外ce)
{ objServer.Disconnect(); // ShowMessage sm = new ShowMessage(InsertAlarmMessage); //this.Invoke(sm、ce.Message); } } }
}