您的位置:首页 > 房产 > 家装 > 河北石家庄疫情最新消息今天_外贸自建站有哪些_高清视频线和音频线的接口类型_如何优化

河北石家庄疫情最新消息今天_外贸自建站有哪些_高清视频线和音频线的接口类型_如何优化

2025/4/22 3:14:37 来源:https://blog.csdn.net/cherry_f_f/article/details/147137358  浏览:    关键词:河北石家庄疫情最新消息今天_外贸自建站有哪些_高清视频线和音频线的接口类型_如何优化
河北石家庄疫情最新消息今天_外贸自建站有哪些_高清视频线和音频线的接口类型_如何优化

一、本文介绍在web环境下unity与usb串口进行通信的代码

本篇使用本地服务器作为unity与串口的中介,unity发送数据到服务器,服务器发送给串口收到响应并解析返回给uinty。

使用websocket协议。

注:

1.我的硬件是检测磁阻液位,用到四字节十六进制浮点数,所以这里会直接转换到十进制。

2.我的硬件会返回9字节响应,所以我会限制响应长度,可以进行适当更改

重要:

1.再开始前一定要改为.NET 4.x,或者.NET Framework,因为.NET standard 2.0或者2.1不包括需要用到的using System.IO.Ports;更换路径为File/Build Setting/Player Settings.../Other Settings/Api Compatibility Level

二、准备文件:

1.使用c#写服务端,需要打开nuget包进行安装websocket,路径:工具/NuGet包管理器/管理解决方案的NuGet程序包/浏览

2.unity端:下载NativeWebSocket,地址:https://github.com/endel/NativeWebSocket

注意:下载了.unitypackage包后拖入到unity中,他会存放到与Assets同级的目录下,打开文件夹将他全部拖到Assets目录就可以了(我不知道不拖行不行,反正我这么做的可以正常使用)

三、服务端代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO.Ports;
using WebSocketSharp.Server;
using System.Threading;
using WebSocketSharp;namespace webforeverusb
{class Program{static void Main(string[] args){var wss = new WebSocketServer("ws://localhost:8080");wss.AddWebSocketService<SerialService>("/serial");wss.Start();Console.WriteLine("WebSocket 服务器正在运行...");Console.ReadLine(); // 保持控制台运行wss.Stop(); // 优雅关闭服务器}}class SerialService : WebSocketBehavior{private SerialPort sp = new SerialPort("COM3", 9600, Parity.None, 8, StopBits.One);private bool isRunning = false;protected override void OnOpen(){try{sp.Open();Console.WriteLine("串口已打开");// StartReading(); // 移除持续读取,仅通过命令触发}catch (Exception ex){Console.WriteLine($"串口打开失败: {ex.Message}");}Console.WriteLine("客户端已连接");}protected override void OnMessage(MessageEventArgs e){string command = e.Data;Console.WriteLine($"收到客户端命令: {command}");try{if (sp.IsOpen){// 将命令转换为字节数组并写入串口byte[] commandBytes = HexStringToBytes(command);sp.Write(commandBytes, 0, commandBytes.Length);Console.WriteLine("命令已写入串口");// 等待并读取串口响应(9 字节)byte[] response = new byte[9];int bytesRead = 0;int timeoutMs = 1000; // 超时时间 1 秒DateTime startTime = DateTime.Now;while (bytesRead < 9 && sp.IsOpen){if (sp.BytesToRead > 0){bytesRead += sp.Read(response, bytesRead, 9 - bytesRead);Console.WriteLine($"已读取 {bytesRead}/9 字节");}if ((DateTime.Now - startTime).TotalMilliseconds > timeoutMs){Console.WriteLine("读取响应超时");Send("错误: 读取响应超时");return;}Thread.Sleep(10);}// 验证响应格式string responseHex = BitConverter.ToString(response).Replace("-", " ");Console.WriteLine($"串口响应: {responseHex}");if (response.Length == 9 && response[0] == 0x01 && response[1] == 0x04){// 提取第 3 到第 6 字节(4 字节数据)byte[] floatBytes = new byte[4];Array.Copy(response, 3, floatBytes, 0, 4);// 转换为浮点数float floatValue = ConvertHexToFloat(floatBytes);Console.WriteLine($"解析得到的浮点数: {floatValue}");// 将浮点数值发送给客户端Send(floatValue.ToString());}else{Console.WriteLine("响应格式错误");Send("错误: 响应格式错误");}}else{Console.WriteLine("串口未打开");Send("错误: 串口未打开");}}catch (Exception ex){Console.WriteLine($"串口通信失败: {ex.Message}");Send($"错误: {ex.Message}");}}// 将十六进制字符串转换为字节数组private byte[] HexStringToBytes(string hexString){hexString = hexString.Replace(" ", "");byte[] bytes = new byte[hexString.Length / 2];for (int i = 0; i < bytes.Length; i++){bytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16);}return bytes;}// 将 4 个字节转换为 IEEE 754 单精度浮点数private float ConvertHexToFloat(byte[] bytes){if (BitConverter.IsLittleEndian){Array.Reverse(bytes); // 翻转字节顺序(大端转小端)}return BitConverter.ToSingle(bytes, 0);}protected override void OnClose(CloseEventArgs e){isRunning = false;if (sp != null && sp.IsOpen){sp.Close();sp.Dispose();Console.WriteLine("串口已关闭");}Console.WriteLine("客户端断开连接");}protected override void OnError(WebSocketSharp.ErrorEventArgs e){Console.WriteLine($"WebSocket 错误: {e.Message}");}}
}

四、unity端:

using UnityEngine;
using NativeWebSocket;
using System.Threading.Tasks;public class WebSocketClient : MonoBehaviour
{private WebSocket websocket;public float pavalue; // 存储解析后的浮点数值async void Start(){
#if UNITY_WEBGL && !UNITY_EDITORwebsocket = new WebSocket("ws://localhost:8080/serial");websocket.OnOpen += () =>{Debug.Log("连接成功,状态: " + websocket.State);SendCommand("01 04 00 02 00 02 D0 0B"); // 发送新命令};websocket.OnMessage += (bytes) =>{string message = System.Text.Encoding.UTF8.GetString(bytes);Debug.Log($"收到数据: {message}");// 尝试解析为浮点数if (float.TryParse(message, out float value)){pavalue = value;Debug.Log($"解析得到的浮点数: {pavalue}");}else{Debug.LogWarning("无法解析为浮点数: " + message);}};websocket.OnError += (e) =>{Debug.LogError($"错误: {e}");};websocket.OnClose += (e) =>{Debug.Log("连接关闭");};await websocket.Connect();
#elseDebug.LogWarning("WebSocket 仅在 WebGL 构建中运行");
#endif}public void SendCommand(string command){if (websocket != null && websocket.State == WebSocketState.Open){websocket.SendText(command);Debug.Log($"发送命令: {command}");}else{Debug.LogError("WebSocket 未连接,无法发送命令");}}float timer = 0f;void Update(){timer += Time.deltaTime;if (timer >= 1f){SendCommand("01 04 00 02 00 02 D0 0B");timer = 0f;}}async void OnDestroy(){
#if UNITY_WEBGL && !UNITY_EDITORif (websocket != null){await websocket.Close();}
#endif}
}

五、结尾:

有任何错误请指出,补充请评论,看到会第一时间回复,谢谢。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com