OpcGatewayStarter
Để project OpcGatewayStarter của bạn hoạt động giống hệt Kepware khi giao tiếp với phần mềm SCADA C# (sql_Connect)
Khi đó, phần mềm SCADA C# chỉ cần gọi lệnh quen thuộc:
OPCServer server = new OPCServer();
server.Connect("OpcGateway.Server.1", ""); // Thay vì "Kepware.KEPServerEX.V6"
Dưới đây là kiến trúc và code triển khai chi tiết từng bước bằng C#:
1. Kiến trúc tổng quan
[Modbus PLC / Slave]
│ (Modbus TCP)
▼
[OpcGatewayStarter (C#)]
├── Modbus Driver ──► Đọc dữ liệu từ PLC
├── TagDatabase ──► Lưu trữ giá trị Tag
└── OPC DA Engine ──► Đăng ký ProgID "OpcGateway.Server.1" vào Windows Registry
│
│ (COM Interop / OPCAutomation)
▼
[SCADA C# (sql_Connect)]
2. Các bước lập trình trong C#
Bước 1: Tạo Interface COM cho OPC DA Server (IOpcDaServer.cs)
Trong project OpcGateway.Server, tạo file IOpcDaServer.cs để định nghĩa các phương thức COM mà SCADA C# có thể gọi:
using System;
using System.Runtime.InteropServices;
namespace OpcGateway.Server
{
[Guid("8A4C62D2-3B4F-4C92-9C1D-8F2E1A908411")] // GUID cố định cho Interface
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
[ComVisible(true)]
public interface IOpcDaServerEvents
{
// Khai báo sự kiện thông báo khi Tag thay đổi giá trị (DataChange)
[DispId(1)]
void OnDataChange(string tagName, object value, short quality, DateTime timestamp);
}
[Guid("1D3E5F7A-9B2C-4D8E-A1B2-C3D4E5F67890")] // GUID cố định cho Server Class
[ComVisible(true)]
public interface IOpcDaServer
{
[DispId(1)]
void Connect(string serverName);
[DispId(2)]
object ReadTag(string tagName);
[DispId(3)]
bool WriteTag(string tagName, object value);
}
}
Bước 2: Lập trình Class COM Server (OpcDaComServer.cs)
Tạo file OpcDaComServer.cs làm nhiệm vụ lấy dữ liệu từ TagDatabase để trả về cho Client C#:
using System;
using System.Runtime.InteropServices;
using OpcGateway.Core; // Thư viện TagDatabase của bạn
namespace OpcGateway.Server
{
[Guid("1D3E5F7A-9B2C-4D8E-A1B2-C3D4E5F67890")]
[ProgId("OpcGateway.Server.1")] // Ten ProgID hien thi trong Windows / SCADA
[ClassInterface(ClassInterfaceType.None)]
[ComSourceInterfaces(typeof(IOpcDaServerEvents))]
[ComVisible(true)]
public class OpcDaComServer : IOpcDaServer
{
private static TagDatabase _tagDatabase;
// Hàm gán TagDatabase từ Main Program
public static void Initialize(TagDatabase tagDatabase)
{
_tagDatabase = tagDatabase;
}
public void Connect(string serverName)
{
Console.WriteLine($"[OPC DA COM] Client connected to ProgID: OpcGateway.Server.1");
}
public object ReadTag(string tagName)
{
if (_tagDatabase != null && _tagDatabase.TryGetTag(tagName, out var tagValue))
{
return tagValue.Value;
}
return null;
}
public bool WriteTag(string tagName, object value)
{
if (_tagDatabase != null)
{
// Gọi driver ghi dữ liệu xuống PLC
return _tagDatabase.WriteTagValue(tagName, value);
}
return false;
}
}
}
Bước 3: Đăng ký COM Server vào Windows Registry trong Program.cs
Mở file Program.cs của project OpcGateway.Server và đăng ký ProgID khi ứng dụng khởi chạy:
using System;
using System.Runtime.InteropServices;
using OpcGateway.Core;
namespace OpcGateway.Server
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("=== OPC Gateway Starter (Dual OPC UA & OPC DA) ===");
// 1. Khởi tạo TagDatabase & Modbus Driver
var tagDatabase = new TagDatabase();
// Đăng ký danh sách Tag
tagDatabase.AddTag(new TagDefinition("Line1.Temperature", "Modbus1", "holding:0", TagDataType.Int16, true));
tagDatabase.AddTag(new TagDefinition("Line1.Speed", "Modbus1", "holding:1", TagDataType.Int16, true));
// 2. Kích hoạt COM Server cho OPC DA (Giống Kepware)
OpcDaComServer.Initialize(tagDatabase);
try
{
// Đăng ký Class COM vào Windows Registry (Yêu cầu quyền Administrator ở lần đầu)
RegistrationServices regServices = new RegistrationServices();
regServices.RegisterTypeForComClients(typeof(OpcDaComServer), RegistrationFlags.SetCodeBase);
Console.WriteLine("[Thanh Cong] Da dang ky ProgID: 'OpcGateway.Server.1' vao Windows Registry.");
}
catch (Exception ex)
{
Console.WriteLine($"[Loi Registry] Can chay app voi quyen Administrator: {ex.Message}");
}
// 3. Khởi chạy vòng lặp Poll Tag từ Modbus Slave
// ... (Code poll Modbus hiện tại của bạn) ...
Console.WriteLine("\nGateway dang chay. Nhan Enter de dung...");
Console.ReadLine();
}
}
}
3. Cách sử dụng trên ứng dụng SCADA C# (sql_Connect)
Bây giờ, trong project SCADA C# (sql_Connect), thay vì kết nối tới Kepware, bạn gọi trực tiếp Gateway C# của mình:
// Đọc danh sách Tag từ file tags.txt như file class_KEPServerEX.cs của bạn
List<string> tagList = class_KEPServerEX.LoadTagList();
// Kết nối tới OpcGatewayStarter qua COM Interop
Type opcType = Type.GetTypeFromProgID("OpcGateway.Server.1");
dynamic opcServer = Activator.CreateInstance(opcType);
opcServer.Connect("OpcGateway.Server.1");
// Đọc giá trị Tag từ Gateway C#
object tempValue = opcServer.ReadTag("Line1.Temperature");
Console.WriteLine($"Gia tri Temperature tu Gateway: {tempValue}");

