using Newtonsoft.Json; using Newtonsoft.Json.Linq; using System.Collections; using System.Collections.Generic; using System.IO; using UnityEngine; using System.Net.WebSockets; using static InterfaceManager; using System.Threading; using System; using System.Text; using Unity.VisualScripting; public class RobotDataManager : MonoBehaviour { [Header("响应成功码")] public string rtCode = "0"; #region 初始化属性 /// /// 是否初始化数据 /// private bool init_data; /// /// 是否已获取【机器人列表】 /// private bool get_robot_list_done; /// /// 是否已获取【机柜列表】 /// private bool get_catrbin_list_done; /// /// 是否已获取【机器人地图数据】 /// private bool get_robot_map_done; /// /// 是否已获取【定点任务-巡检点列表获取】、【机器人地图数据】 /// private bool get_data_after_init_robot; /// /// 机器人信息接收次数 /// private int get_info_times = 0; #endregion #region 初始化数据 /// /// 【机器人列表】数据集合 /// public List RobotList = new List(); /// /// 【机柜列表】数据集合 /// public List CarbinList = new List(); /// /// 【定点任务-巡检点列表】数据集合 /// public List RobotFixedPointsins = new List(); /// /// 【机器人地图】数据 /// public RobotMap RobotMap = new RobotMap(); /// /// 【机器人任务队列】数据 /// public RobotTask RobotTask = new RobotTask(); /// /// 【巡检报表数据】 /// public InsReport InsReport = new InsReport(); ///// ///// 【机器人位置状态信息】数据队列 ///// //public Queue RobotPosQueue = new Queue(); /// /// 【机器人信息】 /// public Queue RobotInfosQueue = new Queue(); #endregion #region 对象 /// /// 机器人对象 /// public RobotObject RobotObject; #endregion // Start is called before the first frame update void Start() { ///获取配置信息 StartCoroutine(GetRequest(Path.Combine(Application.streamingAssetsPath, "robot.txt"), null, null, (_error, _json) => { if (_error != null) { Debug.Log("请求【配置信息】错误:" + _error); return; } JObject _j = JObject.Parse(_json); http_ip_address = _j["http"].ToString(); ws_ip_address = _j["ws"].ToString(); http_ip_ma_address = _j["http_ma"].ToString(); isLive = true; })); } public string _pno; // Update is called once per frame void Update() { Init(); if (Input.GetKeyUp(KeyCode.Y)) { //UsageExample(_pno); for (int i = 0; i < RobotFixedPointsins.Count; i++) { Debug.Log(RobotFixedPointsins[i].pointNo); } } if (Input.GetKeyUp(KeyCode.J)) { UsageExample(_pno); } } /// /// 需要Start中获取的数据在此执行 /// 等待Start完成本地文件读取后执行 /// public void Init() { if (!init_data && isLive) { init_data = true; Debug.Log("初始化数据"); //获取机器人列表 StartCoroutine(GetRequest(http_ip_address + get_robot_list, request_header, null, (_error, _data) => { if (_error != null) { Debug.Log("请求【机器人列表】错误:" + _error); return; } var _response = JsonConvert.DeserializeObject(_data); Debug.Log(_response.rtMsg); if (_response.rtCode.Equals(rtCode) && _response.rtData is JObject _jobject) { if (_jobject != null) { RobotList = _jobject["list"].ToObject>(); //实例化实体机器人 RobotObject.RobotClass = RobotList[0]; } } get_robot_list_done = true; })); //获取机柜列表 StartCoroutine(GetRequest(http_ip_address + get_cabin_list, request_header, new Dictionary() { { "isExport", "false" }, { "pageSize", "200" } }, (_error, _data) => { if (_error != null) { Debug.Log("请求【机柜列表】错误:" + _error); return; } var _response = JsonConvert.DeserializeObject(_data); Debug.Log(_response.rtMsg); if (_response.rtCode.Equals(rtCode) && _response.rtData is JObject _jobject) { if (_jobject != null) { CarbinList = _jobject["list"].ToObject>(); } } get_catrbin_list_done = true; })); } if (get_robot_list_done && get_catrbin_list_done && !get_data_after_init_robot) { get_data_after_init_robot = true; if (RobotList.Count < 1) { Debug.Log("机器人列表小于1!"); return; } //获取定点任务-巡检点列表 StartCoroutine(GetRequest(http_ip_address + get_robot_fixed_pointins, request_header, new Dictionary() { { "roomId", RobotList[0].roomId }, { "pageSize", "200" } }, (_error, _data) => { if (_error != null) { Debug.Log("请求【定点任务-巡检点列表】错误:" + _error); return; } var _response = JsonConvert.DeserializeObject(_data); Debug.Log(_response.rtMsg); if (_response.rtCode.Equals(rtCode)) { RobotFixedPointsins = JsonConvert.DeserializeObject>(_response.rtData.ToString()); } get_catrbin_list_done = true; })); //获取机器人地图数据 StartCoroutine(GetRequest(http_ip_address + get_robot_map + RobotObject.RobotClass.robot_id + "/map", request_header, new Dictionary() { { "robotId", RobotList[0].robot_id } }, (_error, _data) => { if (_error != null) { Debug.Log("请求【机器人地图数据】错误:" + _error); return; } var _response = JsonConvert.DeserializeObject(_data); Debug.Log(_response.rtMsg); if (_response.rtCode.Equals(rtCode) && _response.rtData is JObject _jobject) { if (_jobject != null) { RobotMap = _jobject.ToObject(); //实例化实体机器人的地图数据 RobotObject.RobotMap = RobotMap; } } get_robot_map_done = true; })); //websocket WSRobotPos(); //WSRobotInfo(); } } #region WebSocket数据接收 private ClientWebSocket ws_robot_pos; /// /// 【机器人位置状态信息】 /// private async void WSRobotPos() { try { ws_robot_pos = new ClientWebSocket(); CancellationToken ct = new CancellationToken(); var url = ws_ip_address + ws_robot_html5 + RobotObject.RobotClass.id; Debug.Log(url); Uri uri = new Uri(url); await ws_robot_pos.ConnectAsync(uri, ct); while (true) { Debug.Log("111"); var result = new byte[1024]; await ws_robot_pos.ReceiveAsync(new ArraySegment(result), new CancellationToken()); var str = Encoding.UTF8.GetString(result, 0, result.Length); //处理数据 JObject _jobject = JObject.Parse(str); if (_jobject != null && _jobject["msg"] != null) { if (RobotObject != null) { RobotPos _robot_pos = JsonConvert.DeserializeObject(_jobject["msg"].ToString()); RobotObject.RobotPosQueue.Enqueue(_robot_pos); } } } } catch (Exception ex) { Debug.LogError(ex.ToString()); } } /// /// 【机器人信息】 /// private async void WSRobotInfo() { ClientWebSocket ws = new ClientWebSocket(); CancellationToken ct = new CancellationToken(); Uri uri = new Uri(ws_ip_address + ws_robot_info); await ws.ConnectAsync(uri, ct); while (true) { if (get_info_times == 0) continue; var result = new byte[1024]; await ws.ReceiveAsync(new ArraySegment(result), new CancellationToken()); var str = Encoding.UTF8.GetString(result, 0, result.Length); //处理数据 RobotInfo[] _robot_info = JsonConvert.DeserializeObject(str.ToString()); RobotInfosQueue.Enqueue(_robot_info); get_info_times++; } } #endregion #region 功能点2:下发巡检任务 /* * 任务描述: * 功能:点击机柜,下发巡检任务。 * 1.【获取机器人任务队列】先看机器人是否正在巡检(没有才下发) * 2.【定点任务下发】“pointList“参数中”pointNo “为机柜巡检点,其他参数照抄不动 * 3.下发后看【获取机器人任务队列】是否巡检完成 * 4.巡检完成查看【查询巡检报表数据】将“pic“字段的值从” thermal “开始拆分,把thermal后的截取出来,发送到后台进行保存。 */ /// /// 功能点2调用示例 /// /// 点位编号 public void UsageExample(string _point_no) { //开始执行第一步:查询当前是否正在巡检 GetTaskQueue((_error, _no_task) => { if (_error != null) { Debug.Log(_error); return; } //判断当前是否正在巡检 if (!_no_task) { //如果准备下发巡检任务时正在巡检,则执行如下操作 Debug.Log("当前正在巡检中!请稍后再试!"); //ToDo //... //return; } //若未在巡检,执行第二步:下发任务 PostRobotTask(_point_no, (_error, _post_success) => { //判断是否下发成功 if (_error != null) { Debug.Log(_error); return; } //下发成功后开始执行第三步:循环查询直至结束任务 StartCoroutine(Cyclic_GetTaskQuery((_error) => { if (_error != null) { Debug.Log(_error); return; } //任务结束后执行第四步:查看【查询巡检报表数据】将“pic“字段的值从” thermal “开始拆分,把thermal后的截取出来,发送到后台进行保存 GetInsReport((_error, _success) => { if (_error != null) { Debug.Log(_error); return; } Dictionary> _pics = new Dictionary>(); for (int i = 0; i < InsReport.thermal.Count; i++) { var _ps = new List(); var pic1 = InsReport.thermal[i].pic1.Split("thermal")[1]; var pic2 = InsReport.thermal[i].pic2.Split("thermal")[1]; var pic3 = InsReport.thermal[i].pic3.Split("thermal")[1]; var pic4 = InsReport.thermal[i].pic4.Split("thermal")[1]; var pic5 = InsReport.thermal[i].pic5.Split("thermal")[1]; var pic6 = InsReport.thermal[i].pic6.Split("thermal")[1]; var pic7 = InsReport.thermal[i].pic7.Split("thermal")[1]; _ps.Add(pic1); _ps.Add(pic2); _ps.Add(pic3); _ps.Add(pic4); _ps.Add(pic5); _ps.Add(pic6); _ps.Add(pic7); _pics.Add(InsReport.thermal[i].id, _ps); } //ToDo //将处理好的数据发送给后台 //... Debug.Log("图片路径处理完成!"); }); })); }); }); } /// /// 获取机器人任务列队 /// /// 参数1:异常信息;参数2:true->当前未在巡检 public void GetTaskQueue(Action _callback = null) { Debug.Log("查询当前巡检状态中..."); //注意接口地址中最后一个为机器人id,后期根据业务修改机器人id StartCoroutine(GetRequest(http_ip_address + get_task_queue + RobotObject.RobotClass.robot_id, request_header, null, (_error, _data) => { if (_error != null) { _callback?.Invoke(_error, false); return; } var _response = JsonConvert.DeserializeObject(_data); if (_response.rtCode.Equals(rtCode) && _response.rtData is JObject _jobject) { Debug.Log(_response.rtMsg); if (_jobject != null) { RobotTask = _jobject.ToObject(); //实例化实体机器人的任务数据,注意机器人id是否匹配 RobotObject.RobotTask = RobotTask; //判断每条 RobotTask.data[].Task_type是否为fixed //...如果没有返回True,表示未在巡检,否则返回False _callback?.Invoke(null, RobotTask.data == null || RobotTask.data.Count == 0); } } else { _callback?.Invoke(_response.rtMsg, false); } })); } /// /// 机器人任务下发 /// public void PostRobotTask(string _point_no, Action _callback = null) { string _json_data = "{\r\n \"robotIp\": \"192.168.8.198\",\r\n \"pointList\": [\r\n {\r\n \"pointNo\": \"" + _point_no + "\",\r\n \"04\": \"0\",\r\n \"06\": \"0\",\r\n \"01\": \"1\",\r\n \"cabinType\": \"1\",\r\n \"03\": \"0\",\r\n \"05\": \"0\"\r\n }\r\n ]\r\n}"; StartCoroutine(PostRequest(http_ip_address + post_robot_fixed_point, _json_data, request_header, (_error, _data) => { if (_error != null) { Debug.Log(_error); _callback?.Invoke(_error, false); return; } var _response = JsonConvert.DeserializeObject(_data); Debug.Log(_response.rtMsg); if (_response.rtCode.Equals(rtCode))//返回值匹配表示下发成功 { //下发成功后循环执行获取机器人任务队列,直至任务队列为空后继续执行后续操作 _callback?.Invoke(null, true); } else { _callback?.Invoke(_response.rtMsg, false); } })); } /// /// 执行循环查询等待操作 /// /// public IEnumerator Cyclic_GetTaskQuery(Action _callback = null) { int _call_time = 0;//调用次数 int _response_time = 0;//返回次数 bool _finish = false;//结束循环操作 int _error_time = 0; while (true) { if (_finish) break; //循环查询异常次数超过一定值,结束查询并跳出循环,避免过多不必要的开销 if (_error_time > 3) { _callback?.Invoke("查询异常!"); break; } yield return new WaitForSeconds(3); if (_call_time != _response_time) continue; #region 测试 if (_response_time == 3) { Debug.Log("测试:等待次数过多"); _callback?.Invoke(null); break; } #endregion _call_time++; Debug.Log("执行第" + _call_time + "次循环"); GetTaskQueue((_error, _no_task) => { if (_error != null) { _error_time++; _response_time++; Debug.Log("请求返回第" + _response_time + "次"); return; } if (_no_task) { //当前无任务,结束循环操作 _finish = true; _callback?.Invoke(null); } else { //当前任务尚未结束,继续执行循环操作等待任务结束 _response_time++; Debug.Log("请求返回第" + _response_time + "次"); } }); } yield return null; } /// /// 获取巡检报表数据 /// public void GetInsReport(Action _callback) { //需补充请求参数,机器人任务队列中的Ins_Id,根据业务筛选具体数据 StartCoroutine(GetRequest(http_ip_address + get_record_ins_report, request_header, new Dictionary() { { "insId", RobotTask.data[0].Ins_Id } }, (_error, _data) => { if (_error != null) { Debug.Log(_error); _callback?.Invoke(_error, false); return; } var _response = JsonConvert.DeserializeObject(_data); if (_response.rtCode.Equals(rtCode) && _response.rtData is JObject _jobject) { Debug.Log(_response.rtMsg); if (_jobject != null) { InsReport = _jobject.ToObject(); _callback?.Invoke(null, true); } } else { _callback?.Invoke(_response.rtMsg, false); } })); } #endregion #region 功能点3:巡检结果查看 public void ViewInspectionResults(Action> _callback) { //注意补充Token值 StartCoroutine(GetRequest(http_ip_ma_address + get_inspection, new Dictionary() { { "X-Token", "" } }, null, (_error, _data) => { if (_error != null) { Debug.Log(_error); _callback?.Invoke(_error, null); return; } ResponseData_ma response = JsonConvert.DeserializeObject(_data); if (response.message.Equals("操作成功") && response.data is JObject jobject) { if (response.data != null) { var inspection_datas = jobject.ToObject>(); var sprites = new List(); for (int i = 0; i < inspection_datas.Count; i++) { //base64转图片 byte[] bytes = Convert.FromBase64String(_data); Texture2D text2D = new Texture2D(100, 100); text2D.LoadImage(bytes); Sprite sprite = Sprite.Create(text2D, new Rect(0, 0, text2D.width, text2D.height), new Vector2(0.5f, 0.5f)); sprites.Add(sprite); } _callback?.Invoke(null, sprites); } } })); } #endregion private void OnDestroy() { CloseClientWebSocket(); } /// /// 关闭ClientWebSocket。 /// public void CloseClientWebSocket() { //关闭Socket if (ws_robot_pos != null && ws_robot_pos.State == WebSocketState.Open) { var task = ws_robot_pos.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None); task.Wait(); } } }