using DocumentFormat.OpenXml.Wordprocessing; using Infrastructure; using Infrastructure.CloudSdk.minio; using Infrastructure.CloudSdk.wayline; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Configuration; using Newtonsoft.Json; using OpenAuth.App.BaseApp.Base; using OpenAuth.App.Interface; using OpenAuth.App.ServiceApp.Request; using OpenAuth.App.ServiceApp.Response; using OpenAuth.Repository; using OpenAuth.Repository.Domain; using OpenAuth.WebApi; using OpenAuth.WebApi.CloudSdk; using SqlSugar; namespace OpenAuth.App.ServiceApp { public class ManageApp : SqlSugarBaseApp { private readonly MqttClientManager _mqttClientManager; private readonly MinioService _minioService; public ManageApp(ISugarUnitOfWork unitWork, ISimpleClient repository, IAuth auth, MqttClientManager mqttClientManager, MinioService minioService) : base(unitWork, repository, auth) { _mqttClientManager = mqttClientManager; _minioService = minioService; } #region 机场管理 /// /// 分页获取所有数据 /// /// /// /// /// public async Task>>> GetPageList(int page, int limit, string key) { RefAsync totalCount = 0; using (var db = UnitWork.CreateContext()) { var list = await db.LasaDronePort.AsQueryable().Includes(a => a.UavList) .Where(a => a.IsDelete == false) .WhereIF(!string.IsNullOrEmpty(key), a => a.Name.Contains(key)) .ToPageListAsync(page, limit, totalCount); return new Response>> { Result = new PageInfo> { Items = list, Total = totalCount } }; } } /// /// 编辑机场信息 /// /// /// public async Task> EditDronePort(LasaDronePort info) { using (var db = UnitWork.CreateContext()) { var flag = await db.LasaDronePort.UpdateAsync(it => new LasaDronePort() { Name = info.Name, WorkSpaceId = info.WorkSpaceId, }, it => it.Id == info.Id); if (db.Commit()) return new Response { Result = true, Message = "编辑成功" }; else return new Response { Result = false, Message = "编辑失败" }; } } //删除机场信息 public async Task> DeleteDronePort(string id) { using (var db = UnitWork.CreateContext()) { await db.LasaDronePort.UpdateAsync(u => new LasaDronePort { IsDelete = true }, u => u.Id == id); if (db.Commit()) return new Response { Result = true, Message = "删除成功" }; else return new Response { Result = false, Message = "删除失败" }; } } #endregion /// /// 获取无人机列表 /// /// /// /// /// public async Task>>> GetUavPageList(int page, int limit, string key) { RefAsync totalCount = 0; using (var db = UnitWork.CreateContext()) { var list = await db.LasaUav.AsQueryable() .WhereIF(!string.IsNullOrEmpty(key), a => a.Name.Contains(key)) .ToPageListAsync(page, limit, totalCount); return new Response>> { Result = new PageInfo> { Items = list, Total = totalCount } }; } } /// /// 编辑无人机 /// /// /// public async Task> EditUav(LasaUav info) { using (var db = UnitWork.CreateContext()) { var flag = await db.LasaUav.UpdateAsync(it => new LasaUav() { Name = info.Name, }, it => it.Id == info.Id); if (db.Commit()) return new Response { Result = true, Message = "编辑成功" }; else return new Response { Result = false, Message = "编辑失败" }; } } //删除无人机 public async Task> DeleteUav(string id) { using (var db = UnitWork.CreateContext()) { await db.LasaUav.UpdateAsync(u => new LasaUav { IsDelete = true }, u => u.Id == id); if (db.Commit()) return new Response { Result = true, Message = "删除成功" }; else return new Response { Result = false, Message = "删除失败" }; } } /// /// 获取任务列表 /// /// /// /// /// public async Task>>> GetTaskPageList(int page, int limit, string key) { RefAsync totalCount = 0; using (var db = UnitWork.CreateContext()) { var list = await db.LasaTask.AsQueryable() .WhereIF(!string.IsNullOrEmpty(key), a => a.TaskName.Contains(key)) .ToPageListAsync(page, limit, totalCount); return new Response>> { Result = new PageInfo> { Items = list, Total = totalCount } }; } } //添加任务 public async Task> AddTask(LasaTask task) { using (var db = UnitWork.CreateContext()) { task.Id = Guid.NewGuid().ToString(); task.CreateId = _auth.GetCurrentUser().User.Id; task.CreateTime = DateTime.Now; var flag = await db.LasaTask.InsertAsync(task); if (db.Commit()) return new Response { Result = true, Message = "添加成功" }; else return new Response { Result = false, Message = "添加失败" }; } } //编辑任务 public async Task> EditTask(LasaTask task) { using (var db = UnitWork.CreateContext()) { var flag = await db.LasaTask.UpdateAsync(task); if (db.Commit()) return new Response { Result = true, Message = "编辑成功" }; else return new Response { Result = false, Message = "编辑失败" }; } } //删除任务 public async Task> DeleteTask(string id) { using (var db = UnitWork.CreateContext()) { var flag = await db.LasaTask.DeleteAsync(it => it.Id == id); if (db.Commit()) return new Response { Result = true, Message = "删除成功" }; else return new Response { Result = false, Message = "删除失败" }; } } #region 航线管理 /// /// 获取航线列表 /// /// /// /// /// public async Task>>> GetAirLinePageList(int page, int limit, string key) { RefAsync totalCount = 0; using (var db = UnitWork.CreateContext()) { var list = await db.LasaAirLine.AsQueryable() .WhereIF(!string.IsNullOrEmpty(key), a => a.AirLineName.Contains(key)) .ToPageListAsync(page, limit, totalCount); return new Response>> { Result = new PageInfo> { Items = list, Total = totalCount } }; } } //添加航线 public async Task> AddAirLine(LasaAirLine lasaAirLine) { using (var db = UnitWork.CreateContext()) { lasaAirLine.Id = Guid.NewGuid().ToString(); lasaAirLine.CreateId = _auth.GetCurrentUser().User.Id; lasaAirLine.CreateTime = DateTime.Now; var flag = await db.LasaAirLine.InsertAsync(lasaAirLine); if (db.Commit()) return new Response { Result = true, Message = "添加成功" }; else return new Response { Result = false, Message = "添加失败" }; } } //编辑航线 public async Task> EditAirLine(LasaAirLine lasaAirLine) { using (var db = UnitWork.CreateContext()) { var flag = await db.LasaAirLine.UpdateAsync(lasaAirLine); if (db.Commit()) return new Response { Result = true, Message = "编辑成功" }; else return new Response { Result = false, Message = "编辑失败" }; } } //删除航线 public async Task> DeleteAirLine(string id) { using (var db = UnitWork.CreateContext()) { var flag = await db.LasaAirLine.DeleteAsync(it => it.Id == id); if (db.Commit()) return new Response { Result = true, Message = "删除成功" }; else return new Response { Result = false, Message = "删除失败" }; } } //生成航线文件 #endregion #region 项目管理 /// /// 获取项目列表 /// /// /// public async Task>> GetWorkspaceList(int isjoin, string key, int state, string order = "\"CreateTime\" desc") { RefAsync totalCount = 0; using (var db = UnitWork.CreateContext()) { var userid = _auth.GetCurrentUser().User.Id; List ids = new List(); if (isjoin == 1) { ids = db.LasaSpaceUser.AsQueryable().Where(r => r.UserId == userid)?.Select(r => r.WorkSpaceId) .ToList(); } var list = await db.LasaWorkspace.AsQueryable() .WhereIF(!string.IsNullOrEmpty(key), a => a.WorkspaceName.Contains(key)) .WhereIF(state != 0, a => a.Sate == state) .WhereIF(isjoin == 1, a => ids.Contains(a.Id)) .WhereIF(isjoin == 2, a => !ids.Contains(a.Id)) .LeftJoin((a, u) => a.CreateId == u.Id) .Select((a, u) => new { a.Id, a.WorkspaceName, a.WorkspaceDesc, a.Sate, a.CreateTime, a.CreateId, u.Account, u.Name, UserNames = SqlFunc.Subqueryable().Where(r => r.WorkSpaceId == a.Id) .LeftJoin((r, s) => r.UserId == s.Id).SelectStringJoin((r, s) => s.Name, ",") }).MergeTable() .OrderBy(order) .ToListAsync(); return new Response> { Result = list }; } } //添加项目 public async Task> AddWorkspace(WorkSpace info) { using (var db = UnitWork.CreateContext()) { LasaWorkspace lasaWorkspace = info.LasaWorkspace; lasaWorkspace.Id = Guid.NewGuid().ToString(); lasaWorkspace.CreateId = _auth.GetCurrentUser().User.Id; lasaWorkspace.CreateTime = DateTime.Now; List devices = new List(); foreach (var item in info.DeviceIds) { LasaSpaceDevice sd = new LasaSpaceDevice(); sd.WorkSpaceId = lasaWorkspace.Id; sd.DeviceId = item; devices.Add(sd); } List users = new List(); foreach (var item in info.UserIds) { LasaSpaceUser sd = new LasaSpaceUser(); sd.WorkSpaceId = lasaWorkspace.Id; sd.UserId = item; users.Add(sd); } foreach (var item in info.Lockfly) { item.Id = Guid.NewGuid().ToString(); item.WorkSpaceId = lasaWorkspace.Id; await db.LasaSpaceLockFly.InsertAsync(item); } await db.LasaWorkspace.InsertAsync(lasaWorkspace); await db.LasaSpaceDevice.InsertRangeAsync(devices); await db.LasaSpaceUser.InsertRangeAsync(users); if (db.Commit()) return new Response { Result = true, Message = "添加成功" }; else return new Response { Result = false, Message = "添加失败" }; } } //编辑项目 public async Task> EditWorkspace(WorkSpace info) { using (var db = UnitWork.CreateContext()) { LasaWorkspace lasaWorkspace = info.LasaWorkspace; var flag = await db.LasaWorkspace.UpdateAsync(lasaWorkspace); List devices = new List(); foreach (var item in info.DeviceIds) { LasaSpaceDevice sd = new LasaSpaceDevice(); sd.WorkSpaceId = lasaWorkspace.Id; sd.DeviceId = item; devices.Add(sd); } List users = new List(); foreach (var item in info.UserIds) { LasaSpaceUser sd = new LasaSpaceUser(); sd.WorkSpaceId = lasaWorkspace.Id; sd.UserId = item; users.Add(sd); } foreach (var item in info.Lockfly) { if (!string.IsNullOrEmpty(item.Id)) { await db.LasaSpaceLockFly.UpdateAsync(item); } else { item.Id = Guid.NewGuid().ToString(); item.WorkSpaceId = lasaWorkspace.Id; await db.LasaSpaceLockFly.InsertAsync(item); } } await db.LasaSpaceDevice.DeleteAsync(r => r.WorkSpaceId == lasaWorkspace.Id); await db.LasaSpaceDevice.InsertRangeAsync(devices); await db.LasaSpaceUser.DeleteAsync(r => r.WorkSpaceId == lasaWorkspace.Id); await db.LasaSpaceUser.InsertRangeAsync(users); if (db.Commit()) return new Response { Result = true, Message = "编辑成功" }; else return new Response { Result = false, Message = "编辑失败" }; } } //获取无人机信息 public async Task>> GetUavList() { using (var db = UnitWork.CreateContext()) { var list = db.LasaSpaceDevice.AsQueryable()?.Select(r => r.DeviceId).ToList(); var uavlist = await db.LasaDronePort.AsQueryable() .Where(r => !list.Contains(r.Id)) .ToListAsync(); return new Response> { Result = uavlist }; } } /// /// 根据项目id获取项目信息 /// /// /// public async Task> GetWorkSpaceById(string id) { using (var db = UnitWork.CreateContext()) { WorkSpaceRes res = new WorkSpaceRes(); var workspace = await db.LasaWorkspace.AsQueryable().Where(r => r.Id == id).FirstAsync(); var sysuser = db.User.AsQueryable() .LeftJoin((r, a) => r.Id == a.UserId) .Where((r, a) => a.WorkSpaceId == id) .Select((r, a) => r).ToList(); var uav = db.LasaDronePort.AsQueryable() .LeftJoin((r, a) => r.Id == a.DeviceId) .Where((r, a) => a.WorkSpaceId == id) .Select((r, a) => r).ToList(); var lockfly = db.LasaSpaceLockFly.AsQueryable().Where(r => r.WorkSpaceId == id).ToList(); res.users = sysuser; res.LasaDronePort = uav; res.lasaSpaceLockFlies = lockfly; res.workspace = workspace; return new Response { Result = res }; } } //删除项目 public async Task> DeleteWorkspace(string id) { using (var db = UnitWork.CreateContext()) { await db.LasaWorkspace.UpdateAsync(u => new LasaWorkspace { IsDelete = true }, u => u.Id == id); if (db.Commit()) return new Response { Result = true, Message = "删除成功" }; else return new Response { Result = false, Message = "删除失败" }; } } //归档项目 public async Task> CompleteWorkspace(string id) { using (var db = UnitWork.CreateContext()) { await db.LasaWorkspace.UpdateAsync(u => new LasaWorkspace { Sate = 2 }, u => u.Id == id); if (db.Commit()) return new Response { Result = true, Message = "归档成功" }; else return new Response { Result = false, Message = "归档失败" }; } } #endregion public async Task ExecuteFlyTask(string taskId) { var task = await Repository.ChangeRepository>().GetByIdAsync(taskId); var airLine = await Repository.ChangeRepository>() .GetByIdAsync(task.AirLineId); var wpml = airLine.WPML; // todo 查询sn var dronePort = await Repository.ChangeRepository>() .GetByIdAsync(airLine.UavId); if (dronePort == null) { throw new Exception("指定机场不存在"); } var serialNo = dronePort.Sn; var topic = string.Format(GatewayManager.FlightTaskPrepare, serialNo); var request = new TopicServicesRequest() { method = "flighttask_prepare", tid = Guid.NewGuid().ToString(), bid = Guid.NewGuid().ToString(), timestamp = DateTime.Now.Ticks, }; var builder = new ConfigurationBuilder() .SetBasePath(Directory.GetCurrentDirectory()) .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) .AddJsonFile( $"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Development"}.json", optional: true) .AddEnvironmentVariables(); // 构建配置 var configuration = builder.Build(); var wpmlDir = configuration["WpmlDir"]; // 读取连接字符串 //var serverIp = configuration["MQTT:Server"]; var data = new { flight_id = Guid.NewGuid().ToString(), execute_time = DateTime.Now.Ticks, // 任务开始执行时间毫秒时间戳。可选字段。当 task_type 为 0 或 1 时必填,为 2 时非必填。 //立即任务和定时任务均由 execute_time 指定执行时间。条件任务支持 ready_conditions 字段指定任务就绪条件。任务可在指定时间段内满足一定条件后即可执行。立即任务媒体上传优先级最高,定时任务和条件任务媒体上传优先级相同。 //0":"立即任务","1":"定时任务","2":"条件任务 task_type = task.TaskType, file = new { url = wpml, // todo 拼接地址 fingerprint = "" // todo 计算md5 }, // 任务就绪条件 可选字段。条件任务(即 task_type 为2)时必填,其他类型任务会忽略该字段。下发条件任务后,设备会定频检查 ready_conditions 是否全部满足,若全部满足则会有 flighttask_ready 事件通知。且设备端接收 flighttask_execute 指令时,也会检查任务的 ready_conditions 是否已全部满足。 ready_conditions = new { // 可执行任务的飞行器电池电量百分比阈值,任务开始执行时的飞行器电量必须大于 // todo 去哪里取值 任务限制中是否存在 battery_capacity = 77, // 设备电量百分比,范围 0-100 // todo 设定时间 begin_time = DateTime.Now.Ticks, // 任务开始执行时间必须大于该值 // todo 设定结束时间 end_time = DateTime.Now.Ticks, // 任务结束时间必须 }, // 任务执行条件 executable_conditions = new { // 可执行任务的机场或飞行器最低存储容量,机场或飞行器存储容量不满足 storage_capacity 时,任务执行失败。 // todo 容量单位是什么? 一个图片多少兆,预计拍多少图片? storage_capacity = 1000 }, break_point = new { index = 1, // 断点序号 state = 1, // “0":"在航段上","1":"在航点上 progress = 1.0, // {"max":"1.0","min":"0"} wayline_id = "" // 航线id }, // 返航高度 {"max":1500,"min":20,"step":"","unit_name":"米 / m"} rth_altitude = 150, // todo 取自任务 // 返航高度模式 {"0":"智能高度","1":"设定高度"} // 智能返航模式下,飞行器将自动规划最佳返航高度。大疆机场当前不支持设置返航高度模式,只能选择'设定高度'模式。当环境,光线不满足视觉系统要求时(譬如傍晚阳光直射、夜间弱光无光),飞行器将使用您设定的返航高度进行直线返航 rth_mode = 1, // {"0":"返航","1":"悬停","2":"降落"} // 失控动作,当前固定传的值是 0,即返航。注意该枚举值定义跟飞控跟机场定义的不一致,机场端会进行转换。 out_of_control_action = 0, // 航线失控动作 保持跟 KMZ 文件一致 // {"0":"继续执行航线任务","1":"退出航线任务,执行遥控器失控动作"} exit_wayline_when_rc_lost = 0, // 航线精度类型 {"0":"GPS 任务","1":"高精度 RTK 任务"} // 高精度 RTK 任务:飞行器起飞后会在空中等待 RTK 收敛后再执行任务,等待 RTK 收敛的过程中无法暂停任务。默认场景建议使用该模式。GPS 任务:飞行器无需等待 RTK 收敛便可以直接开始执行。精度要求不高的任务或对起飞时效性要求较高的任务建议使用该模式。 wayline_precision_type = 1, // todo 值来自任务 // 是否在模拟器中执行任务 simulate_mission = new { //是否开启模拟器任务 //{"0":"不开启","1":"开启"} is_enable = 1, // 纬度 {"max":"90.0","min":"-90.0"} latitude = 35.0, // 经度 {"max":"180.0","min":"-180.0"} longitude = 120.0, // 高度 {"max":"9999.9","min":"-9999.9"unit_name":"米 / m"} altitude = 200.0 }, // 飞行安全预检查 // {"0":"关闭","1":"开启"} // 设置一键起飞和航线任务中的飞行安全是否预先检查。此字段为可选,默认为0,值为0表示关闭,1表示开启。飞行安全预先检查表示: 飞行器执行任务前,检查自身作业区文件是否与云端一致,如果不一致则拉取文件更新,如果一致则不处理 flight_safety_advance_check = 0 }; request.SetData(data); // 任务下发 await _mqttClientManager.PublishAsync(topic, JsonConvert.SerializeObject(request)); // todo 是否查询就绪任务 执行任务 await _mqttClientManager.PublishAsync(topic, JsonConvert.SerializeObject(request)); //thing/product/{gateway_sn}/services var flightTaskExecuteTopic = string.Format(GatewayManager.FlightTaskPrepare, serialNo); // todo var flightTaskExecuteRequest = new TopicServicesRequest { method = "flighttask_execute", tid = "tid", bid = "bid", timestamp = DateTime.Now.Ticks, data = new { flight_id = "" // todo } }; await _mqttClientManager.PublishAsync(flightTaskExecuteTopic, JsonConvert.SerializeObject(flightTaskExecuteRequest)); } public async Task PendingFlyTask(string taskId) { // todo // todo 查看任务状态(待执行,任务执行,已暂停,已挂起) 1. 待执行,任务执行,需要先取消任务 2. 已暂停,直接挂起任务 3. 已挂起,返回 throw new NotImplementedException(); } public Task UploadFile(IFormFile xmlFile) { return _minioService.UploadFile(xmlFile, ""); } } }