初始化上传

This commit is contained in:
2025-08-26 08:37:44 +08:00
commit 31d81b91b6
448 changed files with 80981 additions and 0 deletions

View File

@@ -0,0 +1,234 @@
using McProtocol.Mitsubishi;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace .Utility.Network.Mitsubishi
{
internal class MC3EServer
{
public delegate void DataChanged(int address);
public delegate void LogChanged(string message);
public event DataChanged DataChangedEvent;
public event LogChanged LogChangedEvent;
private TcpListener _listener;
private bool _isRunning;
public static ushort[] _dataStorage = new ushort[65535]; // 初始化数据存储区; // 65535个地址数据类型为ushort
public MC3EServer(int port)
{
_listener = new TcpListener(IPAddress.Any, port);
}
public void Start()
{
new Thread(() =>
{
_isRunning = true;
_listener.Start();
LogChangedEvent?.Invoke("MC-3E Protocol Server started...");
while (_isRunning)
{
try
{
TcpClient client = _listener.AcceptTcpClient();
Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClient));
clientThread.Start(client);
}
catch (SocketException)
{
continue;
}
catch (ThreadInterruptedException)
{
break;
}
}
}).Start();
}
public void Stop()
{
_isRunning = false;
_listener.Stop();
}
private void HandleClient(object obj)
{
TcpClient client = (TcpClient)obj;
try
{
NetworkStream stream = client.GetStream();
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = stream.Read(buffer, 0, buffer.Length)) != 0)
{
LogChangedEvent?.Invoke($"Received {bytesRead} bytes from client.");
// 解析MC-3E协议请求
byte[] response = ProcessMc3ERequest(buffer, bytesRead, out bool write, out int address);
// 发送响应
stream.Write(response, 0, response.Length);
if (write) Task.Run(() => DataChangedEvent?.Invoke(address));
}
}
catch (Exception ex)
{
LogChangedEvent?.Invoke(ex.Message);
}
client.Close();
}
private byte[] ProcessMc3ERequest(byte[] request, int length, out bool write, out int address)
{
// MC-3E协议帧格式示例
// 子头 (2字节) + 网络编号 (1字节) + PLC编号 (1字节) + 请求目标模块IO编号 (2字节) + 请求目标模块站号 (1字节)
// + 请求数据长度 (2字节) + 请求数据 (N字节)
// 解析请求数据
if (length < 8)
{
LogChangedEvent?.Invoke($"Invalid request length.");
write = false;
address = 0;
return BuildErrorResponse();
}
McFrame mcFrame = new McFrame();
mcFrame.Frame = BitConverter.ToUInt16(request, 0); // 假设前两字节为帧类型 0x0050 80
mcFrame.NetworkNumber = request[2]; // 假设第3字节为网络编号
mcFrame.PcNumber = request[3]; // 假设第4字节为PLC编号
mcFrame.IoNumber = BitConverter.ToUInt16(request, 4); // 假设第5-6字节为模块IO编号
mcFrame.ChannelNumber = request[6]; // 假设第7字节为模块站号
int dataLength = BitConverter.ToUInt16(request, 7); // 假设第8-9字节为数据长度
mcFrame.CpuTimer = BitConverter.ToUInt16(request, 9); // 假设第10-11字节为CPU监视定时器
int mainCommand = BitConverter.ToUInt16(request, 11); // 假设第12-13字节为主命令
int subCommand = BitConverter.ToUInt16(request, 13); // 假设第14-15字节为子命令
mcFrame.Address = request[17] << 16 | request[16] << 8 | request[15];
mcFrame.Type = (PlcDeviceType)request[18];
mcFrame.Size = BitConverter.ToUInt16(request, 19);
byte[] data = new byte[mcFrame.Size * 2];
for (int i = 0; i < data.Length; i++)
{
data[i] = request[21 + i];
}
mcFrame.Data = data;
// 处理读请求
if (mainCommand == 0x0401) //读命令
{
LogChangedEvent?.Invoke($"Read request: Address={mcFrame.Address},Type={mcFrame.Type} Count={mcFrame.Size}");
write = false;
address = 0;
return HandleReadRequest(mcFrame);
}
// 处理写请求
else if (mainCommand == 0x1401) // 写命令
{
LogChangedEvent?.Invoke($"Write request: Address={mcFrame.Address},Type={mcFrame.Type} Count={mcFrame.Size}");
write = true;
address = mcFrame.Address;
return HandleWriteRequest(mcFrame); ;
}
else
{
LogChangedEvent?.Invoke("Unknown command.");
write = false;
address = 0;
return BuildErrorResponse();
}
}
class McFrame
{
public ushort Frame { get; set; } // 头部
public byte NetworkNumber { get; set; } // 网络号码
public byte PcNumber { get; set; } // 电脑号码
public ushort IoNumber { get; set; } // 请求单元 I/O 编号/O番号
public byte ChannelNumber { get; set; } // 请求单位站号
public ushort CpuTimer { get; set; } // 中央处理器监控计时器
public int Address { get; set; } // 地址
public PlcDeviceType Type { get; set; } // 类型
public uint Size { get; set; } // 大小
public byte[] Data { get; set; }
}
private byte[] HandleReadRequest(McFrame mcFrame)
{
// 读取数据
List<byte> responseData = new List<byte>(); // 每个ushort占2字节
for (int i = 0; i < mcFrame.Size; i++)
{
byte[] valueBytes = BitConverter.GetBytes(_dataStorage[mcFrame.Address + i]);
responseData.AddRange(valueBytes);
}
// 构建响应帧
return BuildSuccessResponse(mcFrame, responseData.ToArray());
}
private byte[] HandleWriteRequest(McFrame mcFrame)
{
for (int i = 0; i < mcFrame.Size; i++)
{
_dataStorage[mcFrame.Address + i] = BitConverter.ToUInt16(mcFrame.Data, i * 2);
}
LogChangedEvent?.Invoke($"Write successful: Address={mcFrame.Address}, Length={mcFrame.Size}");
return BuildSuccessResponse(mcFrame, new byte[0]); // 写入成功,返回空响应
}
private byte[] BuildSuccessResponse(McFrame mcFrame, byte[] responseData)
{
// 构建成功响应帧
List<byte> response = new List<byte>();
mcFrame.Frame = 0x00D0;
response.AddRange(BitConverter.GetBytes(mcFrame.Frame));//0 1
response.Add(mcFrame.NetworkNumber); //2
response.Add(mcFrame.PcNumber); //3
response.AddRange(BitConverter.GetBytes(mcFrame.IoNumber)); //4 5
response.Add(mcFrame.ChannelNumber);//6
//response.AddRange(BitConverter.GetBytes(mcFrame.CpuTimer));
//数据长度
response.AddRange(BitConverter.GetBytes((short)(responseData.Length + 2)));//7 8
response.AddRange(BitConverter.GetBytes((short)0));//9 10结束符号
response.AddRange(responseData);
return response.ToArray();
}
private byte[] BuildErrorResponse()
{
// 构建错误响应帧
byte[] response = new byte[8];
// 子头 (2字节)
response[0] = 0xD0;
response[1] = 0x00;
// 网络编号 (1字节)
response[2] = 0x00;
// PLC编号 (1字节)
response[3] = 0xFF;
// 模块IO编号 (2字节)
response[4] = 0x00;
response[5] = 0x00;
// 模块站号 (1字节)
response[6] = 0x00;
// 响应数据长度 (2字节)
response[7] = 0x00;
response[8] = 0x00;
return response;
}
}
}