GQ_Communicate/GQ_URP/GQ/Assets/Scripts/WJ/Robot/RobotDataManager.cs

640 lines
21 KiB
C#
Raw 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 Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Net.WebSockets;
using System.Text;
using System.Threading;
using UnityEngine;
using static InterfaceManager;
public class RobotDataManager : MonoBehaviour
{
[Header("响应成功码")]
public string rtCode = "0";
#region
/// <summary>
/// 是否初始化数据
/// </summary>
private bool init_data;
/// <summary>
/// 是否已获取【机器人列表】
/// </summary>
private bool get_robot_list_done;
/// <summary>
/// 是否已获取【机柜列表】
/// </summary>
private bool get_catrbin_list_done;
/// <summary>
/// 是否已获取【机器人地图数据】
/// </summary>
private bool get_robot_map_done;
/// <summary>
/// 是否已获取【定点任务-巡检点列表获取】、【机器人地图数据】
/// </summary>
private bool get_data_after_init_robot;
/// <summary>
/// 机器人信息接收次数
/// </summary>
private int get_info_times = 0;
#endregion
#region
/// <summary>
/// 【机器人列表】数据集合
/// </summary>
[Header("【机器人列表】数据集合")] public List<RobotClass> RobotList = new List<RobotClass>();
/// <summary>
/// 【机柜列表】数据集合
/// </summary>
[Header("【机柜列表】数据集合")] public List<CabinClass> CarbinList = new List<CabinClass>();
/// <summary>
/// 【定点任务-巡检点列表】数据集合
/// </summary>
[Header("【定点任务-巡检点列表】数据集合")] public List<RobotFixedPointins> RobotFixedPointsins = new List<RobotFixedPointins>();
/// <summary>
/// 【机器人地图】数据
/// </summary>
[Header("【机器人地图】数据")] public RobotMap RobotMap = new RobotMap();
/// <summary>
/// 【机器人任务队列】数据
/// </summary>
[Header("【机器人任务队列】数据")] public RobotTask RobotTask = new RobotTask();
/// <summary>
/// 【巡检报表数据】
/// </summary>
[Header("【巡检报表数据】")] public InsReport InsReport = new InsReport();
///// <summary>
///// 【机器人位置状态信息】数据队列
///// </summary>
//public Queue<RobotPos> RobotPosQueue = new Queue<RobotPos>();
/// <summary>
/// 【机器人信息】
/// </summary>
[Header("【机器人信息】")] public Queue<RobotInfo[]> RobotInfosQueue = new Queue<RobotInfo[]>();
#endregion
#region
/// <summary>
/// 机器人对象
/// </summary>
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);
}
}
/// <summary>
/// 需要Start中获取的数据在此执行
/// 等待Start完成本地文件读取后执行
/// </summary>
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<ResponseData>(_data);
Debug.Log(_response.rtMsg);
if (_response.rtCode.Equals(rtCode) && _response.rtData is JObject _jobject)
{
if (_jobject != null)
{
RobotList = _jobject["list"].ToObject<List<RobotClass>>();
//实例化实体机器人
RobotObject.RobotClass = RobotList[0];
}
}
get_robot_list_done = true;
}));
//获取机柜列表
StartCoroutine(GetRequest(http_ip_address + get_cabin_list, request_header, new Dictionary<string, string>() { { "isExport", "false" }, { "pageSize", "200" } }, (_error, _data) =>
{
if (_error != null)
{
Debug.Log("请求【机柜列表】错误:" + _error);
return;
}
var _response = JsonConvert.DeserializeObject<ResponseData>(_data);
Debug.Log(_response.rtMsg);
if (_response.rtCode.Equals(rtCode) && _response.rtData is JObject _jobject)
{
if (_jobject != null)
{
CarbinList = _jobject["list"].ToObject<List<CabinClass>>();
}
}
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<string, string>() { { "roomId", RobotList[0].roomId }, { "pageSize", "200" } }, (_error, _data) =>
{
if (_error != null)
{
Debug.Log("请求【定点任务-巡检点列表】错误:" + _error);
return;
}
var _response = JsonConvert.DeserializeObject<ResponseData>(_data);
Debug.Log(_response.rtMsg);
if (_response.rtCode.Equals(rtCode))
{
RobotFixedPointsins = JsonConvert.DeserializeObject<List<RobotFixedPointins>>(_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<string, string>() { { "robotId", RobotList[0].robot_id } }, (_error, _data) =>
{
if (_error != null)
{
Debug.Log("请求【机器人地图数据】错误:" + _error);
return;
}
var _response = JsonConvert.DeserializeObject<ResponseData>(_data);
Debug.Log(_response.rtMsg);
if (_response.rtCode.Equals(rtCode) && _response.rtData is JObject _jobject)
{
if (_jobject != null)
{
RobotMap = _jobject.ToObject<RobotMap>();
//实例化实体机器人的地图数据
RobotObject.RobotMap = RobotMap;
}
}
get_robot_map_done = true;
}));
//websocket
WSRobotPos();
//WSRobotInfo();
}
}
#region WebSocket数据接收
private ClientWebSocket ws_robot_pos;
/// <summary>
/// 【机器人位置状态信息】
/// </summary>
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<byte>(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<RobotPos>(_jobject["msg"].ToString());
RobotObject.RobotPosQueue.Enqueue(_robot_pos);
}
}
}
}
catch (Exception ex)
{
Debug.LogError(ex.ToString());
}
}
/// <summary>
/// 【机器人信息】
/// </summary>
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<byte>(result), new CancellationToken());
var str = Encoding.UTF8.GetString(result, 0, result.Length);
//处理数据
RobotInfo[] _robot_info = JsonConvert.DeserializeObject<RobotInfo[]>(str.ToString());
RobotInfosQueue.Enqueue(_robot_info);
get_info_times++;
}
}
#endregion
#region 2
/*
* 任务描述:
* 功能:点击机柜,下发巡检任务。
* 1.【获取机器人任务队列】先看机器人是否正在巡检(没有才下发)
* 2.【定点任务下发】“pointList“参数中”pointNo “为机柜巡检点,其他参数照抄不动
* 3.下发后看【获取机器人任务队列】是否巡检完成
* 4.巡检完成查看【查询巡检报表数据】将“pic“字段的值从” thermal “开始拆分把thermal后的截取出来发送到后台进行保存。
*/
/// <summary>
/// 功能点2调用示例
/// </summary>
/// <param name="_point_no">点位编号</param>
public void UsageExample(string _point_no)
{
//开始执行第一步:查询当前是否正在巡检
GetTaskQueue((_error, _no_task) =>
{
if (_error != null)
{
Debug.Log(_error);
return;
}
//判断当前是否正在巡检
if (!_no_task)
{
//如果准备下发巡检任务时正在巡检,则执行如下操作
Debug.Log("当前正在巡检中!请稍后再试!");
//ToDo
//...
SecondConfirmPanel.DeleteConform(null, "当前正在巡检中!请稍后再试!");
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<string, List<string>> _pics = new Dictionary<string, List<string>>();
for (int i = 0; i < InsReport.thermal.Count; i++)
{
var _ps = new List<string>();
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("图片路径处理完成!");
});
}));
});
});
}
/// <summary>
/// 获取机器人任务列队
/// </summary>
/// <param name="_callback">参数1异常信息参数2true->当前未在巡检</param>
public void GetTaskQueue(Action<string, bool> _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<ResponseData>(_data);
if (_response.rtCode.Equals(rtCode) && _response.rtData is JObject _jobject)
{
Debug.Log(_response.rtMsg);
if (_jobject != null)
{
RobotTask = _jobject.ToObject<RobotTask>();
//实例化实体机器人的任务数据注意机器人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);
}
}));
}
/// <summary>
/// 机器人任务下发
/// </summary>
public void PostRobotTask(string _point_no, Action<string, bool> _callback = null)
{
var p = new PointList();
p.pointList.Add(new PointNo("2"));
string _json_data = "{\r\n \"robotIp\": \"192.168.8.198\",\r\n \"pointList\": [" + p.pointList + " ]\r\n}";
//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<ResponseData>(_data);
Debug.Log(_response.rtMsg);
if (_response.rtCode.Equals(rtCode))//返回值匹配表示下发成功
{
//下发成功后循环执行获取机器人任务队列,直至任务队列为空后继续执行后续操作
_callback?.Invoke(null, true);
}
else
{
_callback?.Invoke(_response.rtMsg, false);
}
}));
}
/// <summary>
/// 执行循环查询等待操作
/// </summary>
/// <returns></returns>
public IEnumerator Cyclic_GetTaskQuery(Action<string> _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;
}
/// <summary>
/// 获取巡检报表数据
/// </summary>
public void GetInsReport(Action<string, bool> _callback)
{
//需补充请求参数机器人任务队列中的Ins_Id,根据业务筛选具体数据
StartCoroutine(GetRequest(http_ip_address + get_record_ins_report, request_header, new Dictionary<string, string>() { { "insId", RobotTask.data[0].Ins_Id } }, (_error, _data) =>
{
if (_error != null)
{
Debug.Log(_error);
_callback?.Invoke(_error, false);
return;
}
var _response = JsonConvert.DeserializeObject<ResponseData>(_data);
if (_response.rtCode.Equals(rtCode) && _response.rtData is JObject _jobject)
{
Debug.Log(_response.rtMsg);
if (_jobject != null)
{
InsReport = _jobject.ToObject<InsReport>();
_callback?.Invoke(null, true);
}
}
else
{
_callback?.Invoke(_response.rtMsg, false);
}
}));
}
#endregion
#region 3
public void ViewInspectionResults(Action<string, List<Sprite>> _callback)
{
//注意补充Token值
StartCoroutine(GetRequest(http_ip_ma_address + get_inspection, new Dictionary<string, string>() { { "X-Token", "" } }, null, (_error, _data) =>
{
if (_error != null)
{
Debug.Log(_error);
_callback?.Invoke(_error, null);
return;
}
ResponseData_ma response = JsonConvert.DeserializeObject<ResponseData_ma>(_data);
if (response.message.Equals("操作成功") && response.data is JObject jobject)
{
if (response.data != null)
{
var inspection_datas = jobject.ToObject<List<InspectionResult>>();
var sprites = new List<Sprite>();
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();
}
/// <summary>
/// 关闭ClientWebSocket。
/// </summary>
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();
}
}
}