Este programa se probó durante una semana y finalmente descubrí cómo C # llama a OPCDAAuto.dll para vincular KEPserver y la comunicación del PLC, y puede conectarse a los PLC principales del mercado a través de OPC. El código específico es el siguiente. Si desea probar el código fuente del programa o el amigo del programa del proyecto Puede contactarme + V: 1357448516.
usando el sistema;
usando System.Collections.Generic;
usando System.Collections;
utilizando System.ComponentModel;
utilizando System.Data;
usando System.Drawing;
utilizando System.Linq;
usando System.Text;
usando System.Windows.Forms;
utilizando OPCAutomation;
utilizando System.Diagnostics;
usando System.Threading;
espacio de nombres OPC_Client
{ clase parcial pública Form1: Form { OPCServer objServer; OPCGroups objGroups; OPCGroup objGroup; OPCItems objItems; OPCItem [] objChangeItem; Array strItemIDs; Array lClientHandles;
LServerHandles array;
lErrors array;
Estado cadena;
// int ltransID_Rd = 1;
// int lCancelID_Rd;
objeto RequestedDataTypes = null;
objeto AccessPaths = null;
// matriz lerrors_Rd;
matriz de lErrors_Wt;
int lTransID_Wt = 2;
int lCancelID_QualityState;
int op / / Estado de enlace de OPC y PLC
// Enumeración de visualización de estado
delegado privado void OPCtimer (texto de cadena);
// Estado de enlace de OPC y PLC
delegado privado void OPCtoPlcState (int PLCstate);
// Temporizador
System.Windows.Forms.Timer tim;
// Temporizador de enlace OPC
System.Windows.Forms.Timer OPCconnectTimer;
public Form1 ()
{ InitializeComponent (); } private void Form1_Load (remitente de objeto, EventArgs e) { // Inicialización del temporizador de enlace OPC OPCconnectTimer = new System.Windows.Forms.Timer (); OPCconnectTimer .Interval = 1000; OPCconnectTimer.Tick + = new EventHandler (OPCconnectTimer_Tick); OPCconnectTimer.Enabled = true; // Inicializar el temporizador de estado del enlace tim = new System.Windows.Forms.Timer (); // Definir una temporización 1S 器; tim.Interval = 1500;
tim.Tick + = new EventHandler (theout); // Ejecutar el evento de salida después de que se acabe el tiempo;
tim.Enabled = true ;; // Si ejecutar el evento System.Timers.Timer.Elapsed;
// (1) Crear opc objeto de servidor
objServer = new OPCServer ();
objChangeItem = new OPCItem [4];
}
/// <summary>
/// Evento de activación del temporizador de visualización de estado
/// </summary>
/// <param name = "source"> </ param>
/// <param name = "e"> </param>
private void theout (remitente del objeto, EventArgs e)
{ tim.Interval = 1500; // Estado del enlace OPC State = objServer.ServerState.ToString () ; SetOPCstate (Estado);
// OPC 与 PLC 链接 状态
opcQualityState = opcQualityJudge ();
changeLightStatus (opcQualityState);
}
#region OPC 链接 状态 显示
private void SetOPCstate (string text)
{ if (label3.InvokeRequired) { OPCtimer opcdelateTimer = new OPCtimer (InvokeMessage); this.Invoke (opcdelateTimer, texto); } else { this.label3.Text = text; } } private void InvokeMessage (texto de cadena) {
this.label3.Text = text;
}
#endregion
#region El indicador de estado de enlace de OPC y PLC muestra
el vacío privado changeLightStatus (int PLCstate)
{ if (label13.InvokeRequired) { OPCtoPlcState sl = new OPCtoPlcState (InvokeLight); this.Invoke (sl, PLCstate); } else { switch (PLCstate) { caso 1: this.label13.BackColor = Color.Green; this.label13.Text = "Connected"; break;
caso 0:
this.label13.BackColor = Color.Red;
this.label13.Text = "未 连接";
this.Data1.Text = "0";
this.Data2.Text = "0";
descanso;
}
}
}
private void InvokeLight (int light)
{ switch (light) { caso 1: this.label13.BackColor = Color.Green; this.label13.Text = "已 连接"; descanso; caso 0:
this.label13.BackColor = Color.Red;
this.label13.Text = "Unconnected" ; this.Data1.Text = "
0";
this.Data2.Text = "0";
break;
}
}
/// <resumen>
/// Juzgar el estado del enlace de OPC y PLC, el valor de retorno 1 significa enlace, el valor de retorno 0 significa desconexión.
/// Juzgar la información de calidad de cada ítem OPC a su vez, si hay una variable cuya calidad es 0, se considera desconectada.
/// </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 // Finaliza y desconecta el servidor opc private void button4_Click (object remitente, EventArgs e) { // Libera todos los recursos del grupo 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 (); } // Cerrar el proceso kepserver, esto no tiene nada que ver con la operación OPC / * foreach (Process oneProcess in Process.GetProcesses ()) { if (oneProcess.ProcessName == "ServerMain") oneProcess.Kill ();
}
* /
}
// Siempre que cambien los datos del artículo, use el método de suscripción
void KepGroup_DataChange (int TransactionID, int NumItems, ref Array ClientHandles, ref Array ItemValues, ref Array Qualities, ref Array TimeStamps)
{ // Para pruebas, así que agregué la salida de la consola para ver el número de ID de transacción //Console.WriteLine("*********"+TransactionID.ToString()+"********* "); para (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) ).Encadenar(); //this.label5.Text = Qualities.GetValue (i + 1) .ToString (); // int calidad; // calidad = 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). Encadenar(); } } if (Convert.ToInt32 (ClientHandles.GetValue (i + 1)) == 4) { if (ItemValues.GetValue (i + 1)! = null) { this.Data4.Text = ItemValues.GetValue (i + 1) ).Encadenar(); } }
if (Convert.ToInt32 (ClientHandles.GetValue (i + 1)) == 5)
{ if (ItemValues.GetValue (i + 1)! = null) { this.Data5.Text = ItemValues.GetValue (i + 1). Encadenar(); } } if (Convert.ToInt32 (ClientHandles.GetValue (i + 1)) == 6) { if (ItemValues.GetValue (i + 1)! = null) { this.Data6.Text = ItemValues.GetValue (i + 1) ).Encadenar(); } } } }
void AsyncReadComplete (int TransactionID, int NumItems, ref Array ClientHandles, ref Array ItemValues, ref Array Qualities, ref Array TimeStamps, ref Array Errores)
{ MessageBox.Show ("Read Complete"); label11.Text = "Connect on"; } // Enviar instrucciones de escritura de datos asincrónicos private void button3_Click (remitente de objeto, EventArgs e) { Array AsyncValue_Wt; Array SerHandles; object [] tmpWtData = new object [3]; // Los datos escritos deben ser del tipo de objeto, de lo contrario se producirá un error int [] tmpSerHdles = new int [3]; // Asignar los datos de entrada a la matriz, luego convertirlos al tipo de matriz y enviarlos a AsyncValue_Wt tmpWtData [1] = (objeto) textBox1.Text;
tmpWtData [2] = (object) textBox2.Text;
AsyncValue_Wt = (Array) tmpWtData;
// Asigne el identificador del servidor correspondiente al elemento enviado por los datos de entrada a la matriz, y luego conviértalo en un tipo de matriz y envíelo a SerHandles
tmpSerHdles [1] = Convertir .ToInt32 (lserverhandles.GetValue (1));
tmpSerHdles [2] = Convertir.ToInt32 (lserverhandles.GetValue (2));
SerHandles = (Array) tmpSerHdles;
objGrouples.AsyncW SerHdles , ref AsyncValue_Wt, out lErrors_Wt, lTransID_Wt, out lCancelID_Wt);
// Use objChangeItem [1] .Write para escribir datos con esta oración, pero no activa el evento de escritura.
objChangeItem [1] = objItems.GetOPCItem (Convert.ToInt32 (lserverhandles.GetValue (1)));
//objChangeItem[1].Write(102);
}
// Escritura asincrónica exitosa
private void AsyncWriteComplete (int TransactionID, int NumItems, ref Array ClientHandles, ref Array Errores)
{ MessageBox.Show ("¡Datos escritos correctamente!"); } /// <summary> /// Inicialización de OPC /// Cuándo cronometra Cuando el se activa el siguiente evento /// Después del arranque, el OPC se inicializará después de un retraso de 1 segundo. Después de 10 segundos, verifique la transición del enlace con el OPC. Si el enlace está desconectado, vuelva a conectar e inicialice el OPC /// </ resumen> /// <param name = "sender"> </param> /// <param name = "e"> </param> void OPCconnectTimer_Tick (objeto remitente, EventArgs e) { try { OPCconnectTimer.Interval = 10000; si ( objServer .ServerState! = 1)
{ Conectar el servidor opc objServer.Connect ("KEPware.KEPServerEx.V4", ""); // (2) Cree un conjunto de grupos opc objGroups = objServer.OPCGroups ; // (3) Cree un grupo opc objGroup = objGroups. Agregar (nulo); // El nombre del grupo es opcional // (4) Agregar la etiqueta opc objGroup.IsActive = true; // Establecer el grupo como activo. Cuando se conecta al PLC, es lo mismo que configurarlo como inactivo . objGroup.IsSubscriptions = true; // Configurar notificación asincrónica objGroup.UpdateRate = 250; objServer.OPCGroups.DefaultGroupDeadband = 0;
objGroup.DataChange + = nuevo DIOPCGroupEvent_DataChangeEventHandler (KepGroup_DataChange);
objGroup.AsyncReadComplete + = nuevo DIOPCGroupEvent_AsyncReadCompleteEventHandler (AsyncReadComplete);
objGroup.AsyncWriteComplete + = nuevo DIOPCGroupEvent_AsyncWriteCompleteEventHandler (AsyncWriteComplete);
objItems = objGroup.OPCItems; // 建立 opc 标签 集合
cadena [] tmpIDs = nueva cadena [7];
int [] tmpCHandles = new int [7];
para (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 型 , 否则 不能 调用 AddItems 方法
lClientHandles = (Array) tmpCHandles;
// 添加 opc 标签
objItems.AddItems (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))); } } } captura (Excepción ce)
{ objServer.Disconnect (); // ShowMessage sm = new ShowMessage (InsertAlarmMessage); //this.Invoke(sm, ce.Message); } } }
}