H_SafeExperienceDrivingSystem/U3D_DrivingSystem/Assets/Script/ModbusTcpClient.cs

247 lines
11 KiB
C#
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Collections;
using System.Collections.Generic;
using System.Net.Sockets;
using System.Threading.Tasks;
using UnityEngine;
public class CarStatusData
{
public int IgnitionSwitch { get; set; } // 钥匙开关数据
public short SteeringWheelAngle { get; set; } // 方向盘数据
public int HornStatus { get; set; } // 方向盘上喇叭状态
public int BrakePedalPosition { get; set; } // 刹车踏板数据
public int AcceleratorPedalPosition { get; set; } // 油门踏板数据
public int ClutchPedalPosition { get; set; } // 离合踏板数据
public int HandbrakeStatus { get; set; } // 手刹数据
public int GearPosition { get; set; } // 挡位数据
public int WiperStatus { get; set; } // 雨刮状态
public int LightStatus { get; set; } // 灯光状态
public int TurnSignalStatus { get; set; } // 转向灯状态
public int KeyStatus { get; set; } // 点火钥匙数据
public int ButtonData { get; set; } // 按键数据
}
namespace ModbusManager
{
public class ModbusTcpClient:MonoBehaviour
{
private TcpClient tcpClient;
private string serverIp = "172.16.1.125";
private int serverPort = 12315;
public Queue<CarStatusData> modbusQueue;
public static ModbusTcpClient modbusTcpClient;
private void Awake()
{
modbusTcpClient = this;
tcpClient = new TcpClient();
modbusQueue = new Queue<CarStatusData>();
}
private void Start()
{
StartModbus();
}
async Task StartModbus()
{
await ConnectToServer();
while (true)
{
await SendModbusRequest();
// await SendModbusRequest12();
await Task.Delay(TimeSpan.FromSeconds(.1));
}
}
private void OnDestroy()
{
CloseConnection();
}
public ModbusTcpClient()
{
tcpClient = new TcpClient();
modbusQueue = new Queue<CarStatusData>();
}
/// <summary>
/// 接口为TCP/IP接口。
/// 协议为MODBUS/TCP,数据为十六进制数据。
/// 硬件设备为服务器端IP地址192.168.0.100,端口12315电脑为客户端。
/// </summary>
public async Task ConnectToServer()
{
try
{
await tcpClient.ConnectAsync(serverIp, serverPort);
Debug.Log("已连接到Modbus服务器。");
// await SendModbusRequest();
}
catch (Exception ex)
{
Debug.Log("连接Modbus服务器时出错: " + ex.Message);
}
}
/// <summary>
/// 连接成功后,电脑主动发送(十六进制数据): 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个数据
/// </summary>
public async Task SendModbusRequest()
{
byte[] request = new byte[] { 0x00, 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);
}
}
public async Task SendModbusRequest12()
{
byte[] request = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x01, 0x06, 0x00, 0x01, 0x00, 0x00 };
NetworkStream stream = tcpClient.GetStream();
if (stream.CanWrite)
{
await stream.WriteAsync(request, 0, request.Length);
// Debug.Log("Modbus请求已发送。");
await ReadResponse(stream);
}
}
/// <summary>
/// 设备回复: 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是点火
/// 后面为预留。
/// </summary>
private async Task ReadResponse(NetworkStream stream)
{
byte[] response = new byte[256];
int bytesRead = await stream.ReadAsync(response, 0, response.Length);
//Debug.LogLine("已接收到Modbus服务器的响应。");
if (bytesRead > 9) // 确保响应长度足够
{
int length = response[5];
byte deviceId = response[6];
byte functionCode = response[7];
//Debug.Log($"设备ID: {deviceId}, 功能码: {functionCode}, 数据长度: {length}");
CarStatusData carStatusData = new CarStatusData();
for (int i = 9; i < 9 + length; i += 2)
{
ushort dataValue = (ushort)(response[i] << 8 | response[i + 1]);
switch ((i - 9) / 2)
{
case 0://s0熄火1通电2启动
// Debug.Log($"钥匙开关数据: {dataValue}");
carStatusData.IgnitionSwitch = dataValue;
break;
case 1://左打方向盘为负数右打方向盘为正数打方向盘打死一圈半数值1500。
// Debug.Log($"方向盘数据: {(short)dataValue}");
carStatusData.SteeringWheelAngle = (short)dataValue;
break;
case 2://01为喇叭按下
// Debug.Log($"方向盘上喇叭状态: {dataValue}");
carStatusData.HornStatus = dataValue;
break;
case 3://0-100,踩到底为100
// Debug.Log($"刹车踏板数据: {dataValue}");
carStatusData.BrakePedalPosition = dataValue;
break;
case 4://0-100,踩到底为100
Debug.Log($"油门踏板数据: {dataValue}");
carStatusData.AcceleratorPedalPosition = dataValue;
break;
case 5://0-100,踩到底为100
// Debug.Log($"离合踏板数据: {dataValue}");
carStatusData.ClutchPedalPosition = dataValue;
break;
case 6://01表示手刹有效
// Debug.Log($"手刹数据: {dataValue}");
carStatusData.HandbrakeStatus = dataValue;
break;
case 7://00空挡1前进档2倒挡3为P档
// Debug.Log($"挡位数据: {dataValue}");
carStatusData.GearPosition = dataValue;
break;
case 8://00是空档1是手动一次雨刮2是自动雨刮慢速3是自动雨刮快速
// Debug.Log($"雨刮状态: {dataValue}");
carStatusData.WiperStatus = dataValue;
break;
case 9://00是未开灯1是示廓灯2是近光远光。。没有找到远光信号。
// Debug.Log($"灯光状态: {dataValue}");
carStatusData.LightStatus = dataValue;
break;
case 10://00是未开转向灯1是左转向灯2是右转向灯
// Debug.Log($"转向灯状态: {dataValue}");
carStatusData.TurnSignalStatus = dataValue;
break;
case 11://00是熄火1是通电2是点火
//Debug.Log($"点火钥匙数据: {dataValue}");
carStatusData.KeyStatus = dataValue;
break;
case 12://上1,右2,下3左4
// Debug.Log($"按键数据: {dataValue}");
carStatusData.ButtonData = dataValue;
break;
// default:
// Debug.Log($"预留数据 {i / 2 - 4}: {dataValue}");
// break;
}
}
modbusQueue.Enqueue(carStatusData);
// Debug.Log(modbusQueue.Count);
}
else
{
Debug.Log("响应长度无效。");
}
}
public void CloseConnection()
{
if (tcpClient != null)
{
if (tcpClient.Connected)
{
tcpClient.GetStream().Close();
tcpClient.Close();
Debug.Log("已关闭与Modbus服务器的连接。");
}
}
}
}
}