Files
3d-bxqz/Assets/Scripts/DebugTools.cs
2026-05-06 17:36:41 +08:00

355 lines
11 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters
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.Globalization;
using TMPro;
using UnityEngine;
using UnityEngine.Networking;
public class DebugTools : 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<string> deviceSnList = new List<string>
{
"ys_20260326",
"ys_2026020433",
"ys_2026020430",
"ys_2026020427",
"ys_2026020432",
"ys_2026020431",
"ys_2026020429",
"ys_2026020428",
"ys_2026020426",
"ys_2026040901"
};
[Header("手动拖拽绑定identifier -> TMP_Text")]
public List<IdentifierTextBinding> bindings = new List<IdentifierTextBinding>();
[Header("显示设置")]
public string valueFormat = "0.##";
public bool includeUnit = true;
private Dictionary<string, TMP_Text> textMap = new Dictionary<string, TMP_Text>();
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<DeviceDetailResponse>(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<DoubleClickToFocus>().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("ICONS").transform.Find(deviceSnWithName).transform.Find(deviceSnWithName.Substring(second + 1) + "Text").GetComponent<TextMeshProUGUI>().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<DeviceDetailResponse>(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;
}
}