using System; using System.Collections; using System.Collections.Generic; using System.Globalization; using TMPro; using UnityEngine; using UnityEngine.Networking; public class AskForWEBInfomation : MonoBehaviour { [Serializable] public class IdentifierTextBinding { public string identifier; public TMP_Text targetText; } [Header("认证")] [TextArea(2, 4)] public string authorization = "tenantCode=DEMO&accessToken=225e1a7ffede96cb5adab3aa98775660f4c6a066"; [Header("编辑器测试地址")] public string editorFullUrl = "https://3d.gzckgc.cn/api.php/Device/deviceDetail"; [Header("设备SN列表")] public List deviceSnList = new List { //"ys_20260326", //"ys_2026020433", //"ys_2026020430", //"ys_2026020427", //"ys_2026020432", //"ys_2026020431", //"ys_2026020429", //"ys_2026020428", //"ys_2026020426", //"ys_2026040901" //"ys_2026020414","ys_2026020413","ys_2026020412","ys_2026020411","ys_2026020410","ys_2026020409" "ys_2026020442","ys_2026020443","ys_2026020444","ys_2026020445","ys_2026020446","ys_2026020447","ys_2026020448","ys_2026020449","ys_2026041501" }; [Header("手动拖拽绑定:identifier -> TMP_Text")] public List bindings = new List(); [Header("显示设置")] public string valueFormat = "0.##"; public bool includeUnit = true; private Dictionary textMap = new Dictionary(); public bool _isRunning = false;//这个东西只是用来防止手动连点 private void Awake() { BuildBindingMap(); } private void BuildBindingMap() { textMap.Clear(); foreach (var binding in bindings) { if (binding == null) continue; if (string.IsNullOrWhiteSpace(binding.identifier)) continue; if (binding.targetText == null) continue; textMap[binding.identifier] = binding.targetText; } } private void Start() { StartCoroutine(LoadAllDevices()); } //这个是和前端交互的时候按下的按钮 public void ManuallyLoadOneDevice(string SnWithDeviceName) { if (_isRunning) return; StartCoroutine(LoadOneDeviceManually(SnWithDeviceName)); } IEnumerator DelayPart() { yield return new WaitForSeconds(2.0f); // 等待2秒 // 这里写延迟执行的代码 Debug.Log("2秒后执行"); } private IEnumerator LoadAllDevices() { if (string.IsNullOrWhiteSpace(authorization) || authorization.Contains("替换")) { Debug.LogError("authorization 还没填。"); yield break; } foreach (string sn in deviceSnList) { yield return StartCoroutine(LoadOneDevice(sn)); } Debug.Log("全部设备文本更新完成"); } private IEnumerator LoadOneDevice(string deviceSn) { string url = GetRequestUrl(); WWWForm form = new WWWForm(); form.AddField("device_sn", deviceSn); using (UnityWebRequest req = UnityWebRequest.Post(url, form)) { req.SetRequestHeader("Accept", "application/json, text/plain, */*"); req.SetRequestHeader("Authorization", authorization); yield return req.SendWebRequest(); if (req.result != UnityWebRequest.Result.Success) { Debug.LogError($"请求失败 | SN={deviceSn} | {req.error}"); yield break; } string json = req.downloadHandler.text; DeviceDetailResponse resp = null; try { resp = JsonUtility.FromJson(json); } catch (Exception e) { Debug.LogError($"JSON解析失败 | SN={deviceSn} | {e.Message}"); yield break; } if (resp == null || resp.status == null) { Debug.LogError($"响应为空 | SN={deviceSn}"); yield break; } if (resp.status.code != 0) { Debug.LogError($"业务失败 | SN={deviceSn} | code={resp.status.code} | msg={resp.status.msg}"); yield break; } if (resp.result == null || resp.result.data_points == null || resp.result.data_points.timeseries == null) { Debug.LogWarning($"没有 timeseries 数据 | SN={deviceSn}"); yield break; } foreach (DevicePoint point in resp.result.data_points.timeseries) { if (point == null) continue; if (string.IsNullOrWhiteSpace(point.identifier)) continue; UpdateText(point.identifier, point.value, point.unitName, point.name); } } } private IEnumerator LoadOneDeviceManually(string deviceSnWithName)//狗日的unity多参数不能用inspector编辑,重载还不能名字相同,烦。。 { _isRunning = true; yield return null; float transitionDuration = Camera.main.transform.GetComponent().transitionDuration; yield return new WaitForSeconds(transitionDuration + 0.01f); // 等待2秒 // 这里写延迟执行的代码 Debug.Log("2秒后执行"); //为了手动点击传出sn和传感器名字,命名ys_2026020427_sb_wuxianqingjiaoji001,这样,用下划线找sn和名字 //我给这个方法重载了, //分别是手动点击时和自动跳转 //唯一不同就是最下面判断是不是被点击的设备 int first = deviceSnWithName.IndexOf("_"); int second = deviceSnWithName.IndexOf('_', first + 1); string deviceSn = deviceSnWithName.Substring(0, second); string iconName = GameObject.Find("WorldIcons").transform.Find(deviceSnWithName).transform.Find(deviceSnWithName.Substring(second + 1) + "Text").GetComponent().text; //传感器的名字。用这个 object 里面的 text。无法用 gameobject. find 直接找到子对象,先找它的父对象,然后用父对象找子对象。 string url = GetRequestUrl(); WWWForm form = new WWWForm(); form.AddField("device_sn", deviceSn); using (UnityWebRequest req = UnityWebRequest.Post(url, form)) { req.SetRequestHeader("Accept", "application/json, text/plain, */*"); req.SetRequestHeader("Authorization", authorization); yield return req.SendWebRequest(); if (req.result != UnityWebRequest.Result.Success) { Debug.LogError($"请求失败 | SN={deviceSn} | {req.error}"); yield break; } string json = req.downloadHandler.text; DeviceDetailResponse resp = null; try { resp = JsonUtility.FromJson(json); } catch (Exception e) { Debug.LogError($"JSON解析失败 | SN={deviceSn} | {e.Message}"); yield break; } if (resp == null || resp.status == null) { Debug.LogError($"响应为空 | SN={deviceSn}"); yield break; } //此部分为手动获取数据和自动获取数据的唯一区别。 SendData sendData = new SendData(); sendData.result = resp.result; sendData.iconName = iconName; string CoutJsonData = JsonUtility.ToJson(sendData, true); Application.ExternalCall("sendDataToVue", CoutJsonData); //Debug.Log(CoutJsonData); if (resp.status.code != 0) { Debug.LogError($"业务失败 | SN={deviceSn} | code={resp.status.code} | msg={resp.status.msg}"); yield break; } if (resp.result == null || resp.result.data_points == null || resp.result.data_points.timeseries == null) { Debug.LogWarning($"没有 timeseries 数据 | SN={deviceSn}"); yield break; } foreach (DevicePoint point in resp.result.data_points.timeseries) { if (point == null) continue; if (string.IsNullOrWhiteSpace(point.identifier)) continue; UpdateText(point.identifier, point.value, point.unitName, point.name); } } _isRunning = false;//协程运行完成自动解锁。 Debug.Log("单次查询完成"); } private void UpdateText(string identifier, string valueStr, string unitName, string itemName) { if (!textMap.TryGetValue(identifier, out TMP_Text target) || target == null) { Debug.LogWarning($"没有绑定 identifier: {identifier}"); return; } string finalText = valueStr; if (float.TryParse(valueStr, NumberStyles.Any, CultureInfo.InvariantCulture, out float value)) { finalText = value.ToString(valueFormat, CultureInfo.InvariantCulture); } if (includeUnit)//&& !string.IsNullOrWhiteSpace(unitName) { finalText += unitName; finalText = itemName + ": " + finalText; } target.text = finalText; } private string GetRequestUrl() { #if UNITY_WEBGL && !UNITY_EDITOR return "/api.php/Device/deviceDetail"; #else return editorFullUrl; #endif } [ContextMenu("重建绑定字典")] private void RebuildBindings() { BuildBindingMap(); Debug.Log("绑定字典已重建"); } [Serializable] public class DeviceDetailResponse { public ApiStatus status; public DeviceResult result; } [Serializable] public class ApiStatus { public int code; public string msg; } [Serializable] public class DeviceResult { public int device_id; public string device_name; public string device_sn; public string status; public string online_status; public string location; public string address; public string pic; public DataPoints data_points; } [Serializable] public class SendData { public string iconName; public DeviceResult result; } [Serializable] public class DataPoints { public DevicePoint[] control; public DevicePoint[] timeseries; } [Serializable] public class DevicePoint { public string point_id; public string name; public string alias; public string identifier; public string unitName; public string unitIdentifier; public string accessMode; public string dataType; public string value; public string callback_time; } }