using Netly; using Netly.Core; using Newtonsoft.Json; using System; using System.IO; using System.Text; using UnityEngine; using UnityEngine.XR; public class VR1 : MonoBehaviour { TcpClient client; bool isConnecting; int wearingState; DateTime connTime, dateTime; Register register = new Register(); VRInfo vrinfo = new VRInfo(); Logout logout = new Logout(); BackInfo backInfo = new BackInfo(); public UploadInfoToWeb uploadInfoToWeb; DateTime begin_at; string app; void Awake() { ShowLog(Application.persistentDataPath); CreateDirectory(); } void Start() { if (PlayerPrefs.GetInt("group") == 0) { PlayerPrefs.SetInt("group", 1); } Invoke("Init", 0.5f); } void Init() { ReadConfig(); connTime = DateTime.Now; dateTime = DateTime.Now.AddSeconds(-25); if (Application.isEditor) { Config.SN = "PA9410PGJ6170013H"; } else { Config.SN = PicoAPI._Instance.PicoSN(); } client = new TcpClient(framing: false); client.OnOpen(open); client.OnClose(close); client.OnError(error); client.OnEvent(msgEvent); client.OnData(msgData); } void ReadConfig() { if (File.Exists(Config.IpConfig)) { string[] str = File.ReadAllText(Config.IpConfig).Split('\n'); Config.TcpHost = str[0]; WebNet.webIp = str[1]; WebNet.assetsUrl = $"{WebNet.webIp}/api/dev/login"; WebNet.DownAssetsUrl = $"{WebNet.webIp}/storage/resource"; WebNet.UploadInfoUrl = $"{WebNet.webIp}/api/dev/uploadUsageInfo"; WebNet.getDeviceList = $"{WebNet.webIp}/api/tablet/getDeviceList"; WebNet.uploadEQ = $"{WebNet.webIp}/api/dev/uploadEQ"; } else { string str = $"{Config.TcpHost}\n{WebNet.webIp}"; File.WriteAllText(Config.IpConfig, str); } ShowLog($"webIp:{WebNet.webIp}"); } /// /// 创建目录 /// void CreateDirectory() { GameTools.CreateDirectory(Config.AppPath); GameTools.CreateDirectory(Config.AppIconPath); GameTools.CreateDirectory(Config.VideoPath); GameTools.CreateDirectory(Config.VideoIconPath); GameTools.CreateDirectory(Config.ImagePath); GameTools.CreateDirectory(Config.FilePath); GameTools.CreateDirectory(Config.MapPath); GameTools.CreateDirectory(Config.PCappPath); GameTools.CreateDirectory(Config.PCappIconPath); GameTools.CreateDirectory(Config.OtherPath); GameTools.CreateDirectory(Config.AssetsInfoPath); GameTools.CreateDirectory(Config.UseRecordPath); } private void OnApplicationFocus(bool focus) { if (focus && isConnecting) { sendLogout(); try { if (!string.IsNullOrEmpty(app)) { //uploadInfoToWeb.UploadPlayInfo(app, Config.SN, begin_at, 1); app = string.Empty; } } catch (Exception e) { ShowLog($"上传信息报错:{e.Message}"); } } } void Update() { //头盔变化 if (Application.platform == RuntimePlatform.Android) { if (InputDevices.GetDeviceAtXRNode(XRNode.Head).TryGetFeatureValue(CommonUsages.userPresence, out bool userPresence)) { if (userPresence) { wearingState = 1; } else { wearingState = 0; } } } //连接服务器 if (client != null) { if (!isConnecting) { if (DateTime.Now > connTime.AddSeconds(2)) { ShowLog("连接中。。。"); connTime = DateTime.Now; ReadConfig(); client.Open(new Host(Config.TcpHost, Config.TcpPort)); ShowLog($"连接的ip地址:{Config.TcpHost}"); Invoke("sendRegister", 1f); } } else { if (DateTime.Now > dateTime.AddSeconds(2)) { dateTime = DateTime.Now; sendvrInfo(Config.SN, "u", int.Parse(PicoAPI._Instance.PicoPower()), 1, wearingState); //sendvrInfo(Config.SN, "u", 100, 1, 1); ShowLog("发送设备信息。"); } } } if (InputDevices.GetDeviceAtXRNode(XRNode.RightHand).TryGetFeatureValue(CommonUsages.primaryButton, out bool ispri)) { if (ispri) { if (InputDevices.GetDeviceAtXRNode(XRNode.RightHand).TryGetFeatureValue(CommonUsages.triggerButton, out bool islogout)) { if (islogout) { ShowLog("注销"); sendLogout(); } } } } } #region 打印日志 public void ShowLog(string str) { Debug.Log(str); } #endregion #region 网络 void sendMessage(uint type, T msg) { try { // 序列化消息 string json = JsonConvert.SerializeObject(msg); Debug.Log($"发送的json: {json}"); byte[] msgBytes = Encoding.UTF8.GetBytes(json); // 计算总长度(消息类型 + 消息内容 + 结尾的0) int totalLength = sizeof(uint) + msgBytes.Length + 1; // 类型长度 + 消息长度 + 1(结尾的0) // 使用 MemoryStream 和 BinaryWriter 构建字节数组 using (var stream = new MemoryStream()) using (var writer = new BinaryWriter(stream)) { writer.Write(totalLength); // 写入总长度 writer.Write(type); // 写入消息类型 writer.Write(msgBytes); // 写入消息内容 writer.Write((byte)0); // 写入结尾的0 // 发送数据 client.ToData(stream.ToArray()); } } catch (Exception ex) { Debug.LogError("发送消息失败: " + ex.Message); } } // void open() { isConnecting = true; ShowLog("打开连接"); } void close() { isConnecting = false; ShowLog("关闭连接"); } void error(Exception e) { ShowLog($"连接错误:{e.Message}"); } void msgEvent(string name, byte[] bytes) { string msg = NE.GetString(bytes); } void msgData(byte[] bytes) { try { if (bytes == null || bytes.Length < 8) { Debug.LogError("无效数据包:长度不足"); return; } int length = BitConverter.ToInt32(bytes, 0); int type = BitConverter.ToInt32(bytes, 4); if (bytes.Length < length) { Debug.LogError($"数据不完整,预期长度: {length}, 实际长度: {bytes.Length}"); return; } if (bytes.Length > 9) { int msgLength = length - 4 - 1; // 最后一位是字节0 Memory msgMemory = new Memory(bytes, 8, msgLength); string msg = Encoding.UTF8.GetString(msgMemory.Span); Debug.LogError($"收到的消息:{msg}"); switch (type) { case 12: VRControl vrControl = JsonConvert.DeserializeObject(msg); if (string.Equals(vrControl.sn, Config.SN)) { switch (vrControl.com) { case 1: PicoAPI._Instance.ShutDown(); break; case 2: PicoAPI._Instance.Reboot(); break; case 3: PicoAPI._Instance.SetVolumeNum(vrControl.volume); break; case 4: float ipd = (float)vrControl.volume / 100; PicoAPI._Instance.SetIpd(ipd); break; } } break; case 3: Pad1GroupInfo pad1GroupInfo = JsonConvert.DeserializeObject(msg); foreach (var item in pad1GroupInfo.vrs) { if (string.Equals(item.sn, Config.SN)) { Config.Group = pad1GroupInfo.group; PlayerPrefs.SetInt("group", (int)Config.Group); try { if (uploadInfoToWeb) { app = pad1GroupInfo.app; begin_at = DateTime.Now; //uploadInfoToWeb.UploadPlayInfo(pad1GroupInfo.app, Config.SN, begin_at, 1); } } catch (Exception e) { ShowLog($"上传信息报错:{e.Message}"); } PicoAPI._Instance.OpenApp(pad1GroupInfo.apk); break; } } break; default: break; } } } catch (Exception ex) { Debug.LogError($"消息处理异常: {ex.Message}"); } } #endregion #region 消息 /// /// 注册 /// void sendRegister() { register.type = 1; register.user = "VR1"; register.sn = Config.SN; sendMessage(1, register); } /// /// 注销 /// void sendLogout() { logout.group = Config.Group = (uint)PlayerPrefs.GetInt("group"); logout.sn = Config.SN; sendMessage(6, logout); } /// /// 发送vr设备信息 /// void sendvrInfo(string sn, string name, int power, int status, int wear) { vrinfo.sn = sn; vrinfo.user = name; vrinfo.human = 0; vrinfo.power = power; vrinfo.status = status; vrinfo.wear = wear; sendMessage(2, vrinfo); } /// /// 回给平板消息 /// void sendBackInfo() { backInfo.sn = Config.SN; backInfo.url = PicoAPI._Instance.GetCastUrl(); sendMessage(14, backInfo); } #endregion }