namespace RobotNet.Script; /// /// Client CC‑Link IE Basic (SLMP over TCP/UDP) dùng để kết nối PC ↔ PLC Mitsubishi qua Ethernet thường, /// hỗ trợ đọc/ghi device, polling chu kỳ và gửi lệnh SLMP thô. /// public interface ICcLinkIeBasicClient : IAsyncDisposable, IDisposable { /// /// Trạng thái đã kết nối phiên transport (TCP/UDP) tới PLC hay chưa. /// bool IsConnected { get; } /// /// Số lần thử gửi lại khi lỗi tạm thời/timeout. /// int RetryCount { get; set; } /// /// Ngắt kết nối transport và giải phóng tài nguyên liên quan. /// /// Token hủy bất đồng bộ. Task DisconnectAsync(CancellationToken ct = default); /// /// Đọc mảng bit (X/Y/M/L/S/B...) từ PLC. /// /// Loại device code. /// Địa chỉ bắt đầu. /// Số bit cần đọc. /// Token hủy. /// Mảng giá trị bit. Task ReadBitsAsync(DeviceCode device, int startAddress, int count, CancellationToken ct = default); /// /// Ghi mảng bit (X/Y/M/L/S/B...) vào PLC. /// /// Loại device code. /// Địa chỉ bắt đầu. /// Dãy giá trị bit cần ghi. /// Token hủy. Task WriteBitsAsync(DeviceCode device, int startAddress, ReadOnlyMemory values, CancellationToken ct = default); /// /// Đọc mảng word (D/W/R/ZR/B...) từ PLC. /// /// Loại device code. /// Địa chỉ bắt đầu (đơn vị word). /// Số word cần đọc. /// Token hủy. /// Mảng word (UInt16). Task ReadWordsAsync(DeviceCode device, int startAddress, int wordCount, CancellationToken ct = default); /// /// Ghi mảng word (D/W/R/ZR/B...) vào PLC. /// /// Loại device code. /// Địa chỉ bắt đầu (đơn vị word). /// Dãy word cần ghi. /// Token hủy. Task WriteWordsAsync(DeviceCode device, int startAddress, ReadOnlyMemory words, CancellationToken ct = default); /// /// Đọc mảng double‑word (UInt32) từ PLC (áp dụng cho vùng hỗ trợ dword). /// /// Loại device code. /// Địa chỉ bắt đầu (đơn vị dword). /// Số dword cần đọc. /// Token hủy. /// Mảng dword (UInt32). Task ReadDWordsAsync(DeviceCode device, int startAddress, int dwordCount, CancellationToken ct = default); /// /// Ghi mảng double‑word (UInt32) vào PLC (áp dụng cho vùng hỗ trợ dword). /// /// Loại device code. /// Địa chỉ bắt đầu (đơn vị dword). /// Dãy dword cần ghi. /// Token hủy. Task WriteDWordsAsync(DeviceCode device, int startAddress, ReadOnlyMemory dwords, CancellationToken ct = default); /// /// Đọc ngẫu nhiên nhiều điểm word rời rạc (mixed areas) trong một lần. /// /// Danh sách (device, address) cần đọc. /// Token hủy. /// Mảng word theo thứ tự điểm yêu cầu. Task ReadRandomWordsAsync((DeviceCode Device, int Address)[] points, CancellationToken ct = default); /// /// Ghi ngẫu nhiên nhiều điểm word rời rạc (mixed areas) trong một lần. /// /// Danh sách (device, address) cần ghi. /// Giá trị word theo thứ tự điểm. /// Token hủy. Task WriteRandomWordsAsync((DeviceCode Device, int Address)[] points, ReadOnlyMemory values, CancellationToken ct = default); /// /// Sự kiện bắn ra sau mỗi chu kỳ polling hoàn tất. /// event EventHandler? Polled; /// /// Bắt đầu polling chu kỳ một hoặc nhiều vùng device. /// /// Tùy chọn polling (chu kỳ, vùng, giới hạn kích thước). /// Token hủy. void StartPolling(PollOptions options, CancellationToken ct = default); /// /// Dừng polling chu kỳ. /// /// Token hủy. Task StopPollingAsync(CancellationToken ct = default); /// /// Lấy trạng thái liên kết/SLMP gần nhất (end code, thống kê thời gian phản hồi...). /// /// Token hủy. /// Thông tin trạng thái IE Basic. Task GetStatusAsync(CancellationToken ct = default); /// /// Kiểm tra liên lạc PLC (ví dụ node monitor) ở mức nhanh/gọn. /// /// Token hủy. /// true nếu phản hồi hợp lệ, ngược lại false. Task PingAsync(CancellationToken ct = default); /// /// Truy vấn thông tin nhận dạng module/CPU (nếu PLC cho phép). /// /// Token hủy. /// Thông tin định danh CPU/module. Task IdentifyAsync(CancellationToken ct = default); /// /// Gửi lệnh SLMP thô (mở rộng/đặc thù) và nhận phản hồi. /// /// Mã lệnh SLMP. /// Payload SLMP theo định dạng frame chọn (3E/4E). /// Token hủy. /// Phản hồi SLMP gồm end code và payload. Task SendSlmpAsync(SlmpCommand command, ReadOnlyMemory payload, CancellationToken ct = default); } /// /// Loại transport cho CC‑Link IE Basic (UDP hoặc TCP). /// public enum IeBasicTransport { /// Giao tiếp qua UDP (thường dùng cho IE Basic). Udp, /// Giao tiếp qua TCP. Tcp } /// /// Định dạng frame SLMP. /// public enum SlmpFrameFormat { /// Khung 3E (Format 3E). Format3E, /// Khung 4E (Format 4E). Format4E } /// /// Device code (vùng thiết bị) cấp ứng dụng. /// public enum DeviceCode { /// Input (bit). X, /// Output (bit). Y, /// Internal relay (bit). M, /// Latch relay (bit). L, /// Link relay (bit/word tùy CPU). B, /// Step relay (bit). S, /// Data register (word). D, /// Link register (word). W, /// File register (word). R, /// Extended file register (word). ZR } /// /// Tham số logic phía local (PC/sender) khi gửi SLMP. /// /// Số mạng logic. /// Địa chỉ I/O module logic (thường 0x03FF). /// Số đa điểm (nếu dùng). /// Số trạm logic. public readonly record struct IeBasicLocal( byte NetworkNo, ushort ModuleIoNo, byte MultidropNo, byte StationNo ); /// /// Cấu hình đầu xa: địa chỉ IP/Port và tham số logic đích cho SLMP. /// /// Địa chỉ IP hoặc hostname PLC/module. /// Cổng SLMP (ví dụ 5007). /// Số mạng logic đích. /// Địa chỉ I/O module logic đích. /// Số đa điểm (nếu dùng). /// Số trạm logic đích. public readonly record struct IeBasicRemote( string Host, int Port, byte NetworkNo, ushort ModuleIoNo, byte MultidropNo, byte StationNo ); /// /// Tùy chọn khởi tạo/kết nối IE Basic client. /// public sealed record IeBasicClientOptions( string Host, int Port, byte NetworkNo, ushort ModuleIoNo, byte MultidropNo, byte StationNo ) { /// Transport: UDP hoặc TCP. public IeBasicTransport Transport { get; init; } = IeBasicTransport.Udp; /// Định dạng frame SLMP (3E/4E). public SlmpFrameFormat FrameFormat { get; init; } = SlmpFrameFormat.Format3E; /// Tham số logic phía local. public IeBasicLocal Local { get; init; } = new IeBasicLocal(0, 0x03FF, 0, 0); /// Timeout cho mỗi yêu cầu. public TimeSpan Timeout { get; init; } = TimeSpan.FromMilliseconds(1000); /// Số lần retry khi lỗi tạm thời. public int RetryCount { get; init; } = 2; /// Tự động reconnect nếu mất liên kết. public bool AutoReconnect { get; init; } = true; /// /// Quy ước ghép cặp word trong DWord/Float (true: little‑endian word order). /// public bool LittleEndianWordOrder { get; init; } = true; } /// /// Tùy chọn cho polling chu kỳ các vùng device. /// public sealed record PollOptions { /// Khoảng thời gian giữa hai lần poll. public TimeSpan Interval { get; init; } = TimeSpan.FromMilliseconds(20); /// Danh sách vùng cần poll (device, địa chỉ bắt đầu, số lượng). public (DeviceCode Device, int Start, int Count)[] Areas { get; init; } = []; /// Giới hạn số word tối đa mỗi chu kỳ (để tránh gói quá lớn). public int MaxWordsPerCycle { get; init; } = 256; /// Gom vùng theo từng loại device để tối ưu số gói. public bool AlignAreasByDevice { get; init; } = true; } /// /// Dữ liệu trả về sau mỗi chu kỳ polling. /// public sealed class PollUpdatedEventArgs : EventArgs { /// Thời điểm khung dữ liệu được cập nhật. public DateTimeOffset Timestamp { get; init; } /// Mảng bit (nếu có vùng bit được cấu hình). public ReadOnlyMemory? Bits { get; init; } /// Mảng word (nếu có vùng word được cấu hình). public ReadOnlyMemory? Words { get; init; } /// Mảng dword (nếu có vùng dword được cấu hình). public ReadOnlyMemory? DWords { get; init; } } /// /// Trạng thái liên kết/SLMP để chẩn đoán và theo dõi. /// public sealed record IeBasicStatus { /// Liên kết hiện “đang lên” (có phản hồi) hay không. public bool LinkUp { get; init; } /// Số lỗi liên tiếp gần nhất. public int ConsecutiveErrors { get; init; } /// End code SLMP của lỗi gần nhất (nếu có). public SlmpEndCode? LastEndCode { get; init; } /// Mô tả lỗi gần nhất (nếu có). public string? LastErrorText { get; init; } /// Thời gian phản hồi trung bình ước tính. public TimeSpan? AvgRtt { get; init; } /// Thời gian phản hồi lớn nhất quan sát. public TimeSpan? MaxRtt { get; init; } } /// /// Thông tin nhận dạng CPU/module (nếu PLC cho phép truy vấn). /// public sealed record ModuleIdentity { /// Dòng CPU (ví dụ iQ‑R, iQ‑F). public string? CpuSeries { get; init; } /// Model cụ thể (ví dụ R04ENCPU). public string? CpuModel { get; init; } /// Phiên bản firmware. public string? Firmware { get; init; } /// Nhà sản xuất (thường là Mitsubishi Electric). public string? Vendor { get; init; } /// Thông tin bổ sung khác (nếu có). public string? AdditionalInfo { get; init; } } /// /// Mã lệnh SLMP rút gọn (có thể mở rộng khi hiện thực adapter). /// public enum SlmpCommand : ushort { /// Đọc device theo dải liên tục (bit/word). ReadDevice = 0x0401, /// Ghi device theo dải liên tục (bit/word). WriteDevice = 0x1401, /// Đọc ngẫu nhiên nhiều điểm. ReadRandom = 0x0403, /// Ghi ngẫu nhiên nhiều điểm. WriteRandom = 0x1402, /// Node monitor / kiểm tra liên lạc. NodeMonitor = 0x0619, /// Truy vấn thông tin thiết bị/PLC. DeviceInfo = 0x0601 } /// /// Mã end code SLMP (hoàn thành/thất bại), gồm cả mã nội bộ ánh xạ lỗi transport/timeout. /// public enum SlmpEndCode : ushort { /// Hoàn thành thành công. Completed = 0x0000, /// Lệnh không hợp lệ. InvalidCommand = 0xC059, /// Truy cập bị từ chối. AccessDenied = 0xC056, /// Lỗi phạm vi device. DeviceRangeError = 0xC051, /// Thiết bị bận. Busy = 0xCEE0, /// Quá thời gian chờ (gán nội bộ). Timeout = 0xFFFF, /// Lỗi transport/socket (gán nội bộ). TransportError = 0xFFFE, /// Lỗi không xác định (gán nội bộ). Unknown = 0xFFFD } /// /// Phản hồi SLMP thô trả về từ . /// public sealed record SlmpResponse { /// End code của phản hồi. public SlmpEndCode EndCode { get; init; } /// Payload nhị phân trả về (theo frame 3E/4E). public ReadOnlyMemory Payload { get; init; } /// Thời điểm nhận gói. public DateTimeOffset Timestamp { get; init; } }