You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

275 lines
11 KiB

  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Linq;
  5. using System.Net.Http;
  6. using System.Threading;
  7. using System.Threading.Tasks;
  8. using Lebai.SDK.Dtos;
  9. using Lebai.SDK.Exceptions;
  10. using TaskStatus = Lebai.SDK.Dtos.TaskStatus;
  11. #if NET5_0||NET6_0
  12. using System.Net.Http.Json;
  13. #endif
  14. namespace Lebai.SDK
  15. {
  16. public class EnumExtension
  17. {
  18. /// <summary>
  19. ///
  20. /// </summary>
  21. /// <param name="tField"></param>
  22. /// <typeparam name="T"></typeparam>
  23. /// <returns></returns>
  24. public static string GetEnumDescription<T>(T tField)
  25. {
  26. var description = string.Empty; //结果
  27. var inputType = tField.GetType(); //输入的类型
  28. var descType = typeof(DescriptionAttribute); //目标查找的描述类型
  29. var fieldStr = tField.ToString(); //输入的字段字符串
  30. var field = inputType.GetField(fieldStr); //目标字段
  31. var isDefined = field.IsDefined(descType, false); //判断描述是否在字段的特性
  32. if (isDefined)
  33. {
  34. var enumAttributes = (DescriptionAttribute[]) field //得到特性信息
  35. .GetCustomAttributes(descType, false);
  36. description = enumAttributes.FirstOrDefault()?.Description ?? string.Empty;
  37. }
  38. return description;
  39. }
  40. }
  41. public partial class LebaiRobotClient
  42. {
  43. public static Dictionary<int, string> CodeMessage = new()
  44. {
  45. [2001] = "系统异常",
  46. [2002] = "登录授权码错误",
  47. [2003] = "登录授权码已失效",
  48. [2004] = "机器人控制系统异常",
  49. [2005] = "404",
  50. [2006] = "参数错误",
  51. [2007] = "数据不存在",
  52. [2009] = "请登录",
  53. [2010] = "同一时间只能有一个用户登录",
  54. [2011] = "队列任务执行报错",
  55. [2012] = "机器人任务运行中不能运行其他任务",
  56. [2015] = "场景导入失败,导入文件格式错误",
  57. [2021] = "数据库异常",
  58. [2022] = "签名失败",
  59. [2023] = "任务队列恢复失败,手臂当前位置与即将运行轨迹的首个位置数据校验失败",
  60. [2024] = "无效机器人操作命令",
  61. [2025] = "机器人当前状态没有满足执行当前指令的预期(废弃)",
  62. [2026] = "请求超时",
  63. [2027] = "网络配置中,不能频繁进行操作",
  64. [2028] = "条件任务执行超时",
  65. [2029] = "机器人控制系统故障,请重启机器人后再试",
  66. [2030] = "机器人通信故障,请检查机器人是否已正确连接",
  67. [2031] = "机器人初始化中,请稍候再试",
  68. [2032] = "机器人更新中,请稍候再试",
  69. [2033] = "机器人启动中,请稍候再试",
  70. [2034] = "机器人停止中,请稍候再试",
  71. [2035] = "请结束示教操作后再试",
  72. [2036] = "请先停止任务历史中的当前任务后再执行相应操作",
  73. [2037] = "仿真模式暂不支持该功能"
  74. };
  75. /// <summary>
  76. /// 获取指定任务信息
  77. /// </summary>
  78. /// <param name="id"></param>
  79. /// <param name="cancellationToken"></param>
  80. /// <returns></returns>
  81. public virtual async ValueTask<TaskInfo> GetTask(int id, CancellationToken cancellationToken = default)
  82. {
  83. var response = await _httpClient.GetAsync($"/public/task?id={id}", cancellationToken);
  84. var r = await response.Content.ReadFromJsonAsync<LebaiHttpResult<OriginTaskInfo>>(
  85. cancellationToken: cancellationToken);
  86. HandleResult(r, $"场景Id:{id}");
  87. return r?.Data.ToTaskInfo();
  88. }
  89. /// <summary>
  90. /// 获取任务信息
  91. /// </summary>
  92. /// <param name="input"></param>
  93. /// <param name="cancellationToken"></param>
  94. /// <returns></returns>
  95. public virtual async ValueTask<TasksResult> GetTasks(GetTasksInput input,
  96. CancellationToken cancellationToken = default)
  97. {
  98. var response = _httpClient
  99. .GetAsync($"/public/tasks?pi={input.PageIndex}&ps={input.PageSize}", cancellationToken).Result;
  100. var r = await response.Content.ReadFromJsonAsync<LebaiHttpResult<OriginTasksResult>>(
  101. cancellationToken: cancellationToken);
  102. HandleResult(r);
  103. return r?.Data?.ToResult();
  104. }
  105. /// <summary>
  106. /// 检测是否能运行任务(机器人是否正在运行其他任务)
  107. /// </summary>
  108. /// <returns></returns>
  109. public virtual async ValueTask<bool> GetIsCanRunTask(CancellationToken cancellationToken = default)
  110. {
  111. var result = await GetTasks(new GetTasksInput {PageIndex = 1, PageSize = 1}, cancellationToken);
  112. var first = result?.Items?.FirstOrDefault();
  113. return first == null || first.Status != TaskStatus.Running && first.Status != TaskStatus.Pause;
  114. }
  115. /// <summary>
  116. ///
  117. /// </summary>
  118. /// <param name="cancellationToken"></param>
  119. /// <exception cref="Exception"></exception>
  120. protected virtual async ValueTask CheckRobotStatus(CancellationToken cancellationToken = default)
  121. {
  122. var result = await GetTasks(new GetTasksInput {PageIndex = 1, PageSize = 1}, cancellationToken);
  123. var first = result?.Items?.FirstOrDefault();
  124. var r= first == null || first.Status != TaskStatus.Running && first.Status != TaskStatus.Pause;
  125. if (!r) throw new Exception($"机器人正在执行其他任务!,任务数量:{result?.Items} 真正运行的其他任务: {first.Status}");
  126. }
  127. /// <summary>
  128. /// 运行任务
  129. /// </summary>
  130. /// <param name="id">任务Id</param>
  131. /// <param name="executeCount">执行次数</param>
  132. /// <param name="clear">是否强制停止正在运行的任务</param>
  133. /// <param name="cancellationToken"></param>
  134. /// <returns></returns>
  135. public virtual async Task<TaskExecuteResult> RunTask(int id, int executeCount = 1,
  136. bool clear = true, CancellationToken cancellationToken = default)
  137. {
  138. await CheckRobotStatus(cancellationToken);
  139. var response = _httpClient.PostAsJsonAsync("/public/task", new
  140. {
  141. execute_count = executeCount,
  142. clear = clear ? 1 : 0,
  143. task_id = id
  144. }, cancellationToken).Result;
  145. var r = await response.Content.ReadFromJsonAsync<LebaiHttpResult<TaskExecuteResult>>(
  146. cancellationToken: cancellationToken);
  147. HandleResult(r);
  148. return r?.Data;
  149. }
  150. /// <summary>
  151. /// 运行场景
  152. /// </summary>
  153. /// <param name="id">场景Id</param>
  154. /// <param name="executeCount">运行次数</param>
  155. /// <param name="clear">是否强制停止正在运行的场景</param>
  156. /// <param name="cancellationToken"></param>
  157. /// <returns></returns>
  158. public virtual async Task<TaskExecuteResult> RunScene(int id, int executeCount = 1,
  159. bool clear = false, CancellationToken cancellationToken = default)
  160. {
  161. await CheckRobotStatus(cancellationToken);
  162. var response = _httpClient.PostAsJsonAsync("/public/task", new
  163. {
  164. execute_count = executeCount,
  165. clear = clear ? 1 : 0,
  166. scene_id = id
  167. }, cancellationToken).Result;
  168. var r = await response.Content.ReadFromJsonAsync<LebaiHttpResult<TaskExecuteResult>>(
  169. cancellationToken: cancellationToken);
  170. HandleResult(r, $"场景Id:{id}");
  171. return r?.Data;
  172. }
  173. /// <summary>
  174. ///
  175. /// </summary>
  176. /// <param name="result"></param>
  177. /// <param name="message"></param>
  178. /// <typeparam name="T"></typeparam>
  179. /// <exception cref="HttpRequestException"></exception>
  180. protected void HandleResult<T>(LebaiHttpResult<T> result, string message = "")
  181. {
  182. if (result?.Code != 0)
  183. throw new HttpRequestException($"调用失败,{message},Code:{result.Code}" +
  184. (CodeMessage.ContainsKey(result.Code)
  185. ? $",{CodeMessage[result.Code]}"
  186. : ""));
  187. }
  188. /// <summary>
  189. /// 等待任务运行完成
  190. /// </summary>
  191. /// <param name="id">任务Id</param>
  192. /// <param name="cancellationToken"></param>
  193. /// <returns></returns>
  194. /// <exception cref="OperationCanceledException"></exception>
  195. /// <exception cref="RobotTaskException"></exception>
  196. public virtual async ValueTask<TaskInfo> WaitTaskRunCompleted(int id,
  197. CancellationToken cancellationToken = default)
  198. {
  199. TaskInfo taskInfo = await GetTask(id, cancellationToken);
  200. while (true)
  201. {
  202. if (cancellationToken.IsCancellationRequested) throw new OperationCanceledException();
  203. if (taskInfo?.Status is TaskStatus.Running or TaskStatus.Idea)
  204. {
  205. await Task.Delay(100, cancellationToken);
  206. taskInfo = await GetTask(id, cancellationToken);
  207. }
  208. else if (taskInfo?.Status is TaskStatus.RunSuccess)
  209. {
  210. break;
  211. }
  212. else
  213. {
  214. throw new RobotTaskException(taskInfo?.Status);
  215. }
  216. }
  217. return taskInfo;
  218. }
  219. /// <summary>
  220. /// 运行场景直到运行完成
  221. /// </summary>
  222. /// <param name="id">场景Id</param>
  223. /// <param name="executeCount">执行次数</param>
  224. /// <param name="clear">是否强制停止正在运行的场景</param>
  225. /// <param name="cancellationToken"></param>
  226. /// <returns></returns>
  227. public virtual async Task<TaskInfo> RunSceneUntilDone(int id, int executeCount = 1,
  228. bool clear = false, CancellationToken cancellationToken = default)
  229. {
  230. var r = await RunScene(id, executeCount, clear, cancellationToken);
  231. return await WaitTaskRunCompleted(r.Id, cancellationToken);
  232. }
  233. /// <summary>
  234. /// 执行Lua 代码
  235. /// </summary>
  236. /// <param name="luaCode"></param>
  237. /// <param name="cancellationToken"></param>
  238. /// <returns></returns>
  239. public virtual async Task<TaskExecuteResult> ExecuteLua(string luaCode,
  240. CancellationToken cancellationToken = default)
  241. {
  242. var response =
  243. await _httpClient.PostAsync("/public/executor/lua", new StringContent(luaCode), cancellationToken);
  244. var r = await response.Content.ReadFromJsonAsync<LebaiHttpResult<TaskExecuteResult>>(
  245. cancellationToken: cancellationToken);
  246. HandleResult(r);
  247. return r?.Data;
  248. }
  249. }
  250. }