using System;
using System.Net.Sockets;
using System.Threading.Tasks;
using UnityEngine;
using System;
using System.Net.Sockets;
using System.Threading.Tasks;
using UnityEngine;
public class ModbusTcpClient
{
private TcpClient tcpClient;
private string serverIp = "127.0.0.1";
private int serverPort = 12315;
public ModbusTcpClient()
{
tcpClient = new TcpClient();
}
///
/// 接口为TCP/IP接口。
/// 协议为MODBUS/TCP,数据为十六进制数据。
/// 硬件设备为服务器端,IP地址192.168.0.100,端口12315,电脑为客户端。
///
public async Task ConnectToServer()
{
try
{
await tcpClient.ConnectAsync(serverIp, serverPort);
Debug.Log("已连接到Modbus服务器。");
await SendModbusRequest();
}
catch (Exception ex)
{
Debug.Log("连接Modbus服务器时出错: " + ex.Message);
}
}
///
/// 连接成功后,电脑主动发送(十六进制数据): 00 00 00 00 00 06 01 03 00 00 00 10
/// "00 00 00 00 00 06"为TCP报文头,06表示后面有六个字节。
/// "01"表示硬件设备编号
/// "03"表示读数据
/// "00 00" 表示读数据从0000开始
/// "00 10" 表示读16个数据
///
private async Task SendModbusRequest()
{
byte[] request = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00, 0x10 };
NetworkStream stream = tcpClient.GetStream();
if (stream.CanWrite)
{
await stream.WriteAsync(request, 0, request.Length);
Debug.Log("Modbus请求已发送。");
await ReadResponse(stream);
}
}
///
/// 设备回复: 00 00 00 00 00 24 01 03 20 00 01 00 02 00 03 00 04 00 05 00 06 00 07 00 08 00 09 00 0A 00 0B 00 0C 00 0D 00 0E 00 0F 00 10
/// "00 00 00 00 00 24" 为TCP报文头,24 表示后面有三十六个字节。
/// "01" 表示硬件设备编号。
/// "03" 表示读数据。
/// "20" 表示后面有三十二个字节数据,即16个数据。
/// 后续数据为硬件反馈回来的数据:
/// - "00 01" 为钥匙开关数据,0 熄火,1 通电,2 启动。
/// - "00 02"为方向盘数据,左打方向盘为负数,右打方向盘为正数,打方向盘幅度越大,绝对值越大。
/// - "00 03" 为方向盘上喇叭状态,01 为喇叭按下。
/// - "00 04"为刹车踏板数据, 0-100,踩到底为100
/// - "00 05" 为油门踏板数据。0-100,踩到底为100
/// - "00 06" 为离合踏板数据。0-100,踩到底为100
/// - "00 07" 为手刹数据,01 表示手刹有效。
/// - "00 08" 为挡位数据,00 空挡,1 前进档,2 倒挡,3 为 P 档。
/// - "00 09" 为雨刮数据,00 空档,1 手动一次雨刮,2 自动雨刮慢速,3 自动雨刮快速。
/// - "00 0A" 为灯光数据,00 未开灯,1 近光,2 远光。
/// - "00 0B" 为转向灯数据,00 未开转向灯,1 左转向灯,2 右转向灯。
/// - "00 0C"为点火钥匙数据,00是熄火,1是通电,2是点火
/// 后面为预留。
///
private async Task ReadResponse(NetworkStream stream)
{
byte[] response = new byte[256];
int bytesRead = await stream.ReadAsync(response, 0, response.Length);
Debug.Log("已接收到Modbus服务器的响应。");
if (bytesRead > 9) // 确保响应长度足够
{
int length = response[5];
byte deviceId = response[6];
byte functionCode = response[7];
Debug.Log($"设备ID: {deviceId}, 功能码: {functionCode}, 数据长度: {length}");
for (int i = 9; i < 9 + length; i += 2)
{
ushort dataValue = (ushort)(response[i] << 8 | response[i + 1]);
switch ((i - 9) / 2)
{
case 0:
Debug.Log($"钥匙开关数据: {dataValue}");
break;
case 1:
Debug.Log($"方向盘数据: {dataValue}");
break;
case 2:
Debug.Log($"方向盘上喇叭状态: {dataValue}");
break;
case 3:
Debug.Log($"刹车踏板数据: {dataValue}");
break;
case 4:
Debug.Log($"油门踏板数据: {dataValue}");
break;
case 5:
Debug.Log($"离合踏板数据: {dataValue}");
break;
case 6:
Debug.Log($"手刹数据: {dataValue}");
break;
case 7:
Debug.Log($"挡位数据: {dataValue}");
break;
case 8:
Debug.Log($"雨刮状态: {dataValue}");
break;
case 9:
Debug.Log($"灯光状态: {dataValue}");
break;
case 10:
Debug.Log($"转向灯状态: {dataValue}");
break;
case 11:
Debug.Log($"点火钥匙数据: {dataValue}");
break;
default:
Debug.Log($"预留数据 {i / 2 - 4}: {dataValue}");
break;
}
}
}
else
{
Debug.Log("响应长度无效。");
}
}
public void CloseConnection()
{
if (tcpClient != null)
{
if (tcpClient.Connected)
{
tcpClient.GetStream().Close();
tcpClient.Close();
Debug.Log("已关闭与Modbus服务器的连接。");
}
}
}
}