洁 任 2 months ago
commit e8d8b0dc18

@ -282,5 +282,60 @@ public class MinioService
return null;
}
}
public async Task<string> UploadStreamFile(Stream stream, string fileName, string bucketName, string prifix)
{
try
{
if (string.IsNullOrEmpty(bucketName))
{
bucketName = _bucketName;
}
// 判断桶是否存在
var beArgs = new BucketExistsArgs().WithBucket(bucketName);
bool found = await _minioClient.BucketExistsAsync(beArgs).ConfigureAwait(false);
if (!found)
{
var mbArgs = new MakeBucketArgs().WithBucket(bucketName);
await _minioClient.MakeBucketAsync(mbArgs).ConfigureAwait(false);
}
var suffix = Path.GetExtension(fileName);
string objectName;
if (string.IsNullOrEmpty(prifix))
{
objectName = $"{GenerateId.GenerateOrderNumber()}{suffix}";
}
else
{
objectName = $"{prifix}/{GenerateId.GenerateOrderNumber()}{suffix}";
}
// 计算 MD5
stream.Position = 0;
var md5 = Md5.CalculateStreamMd5(stream);
stream.Position = 0;
var putArgs = new PutObjectArgs()
.WithBucket(bucketName)
.WithObject(objectName)
.WithStreamData(stream)
.WithObjectSize(stream.Length)
.WithHeaders(new Dictionary<string, string>()
{
["X-Amz-Meta-Md5"] = md5
})
.WithContentType("application/octet-stream");
var result = await _minioClient.PutObjectAsync(putArgs);
Console.WriteLine("code :" + result.ResponseStatusCode);
return $"http://{endPoint}/{bucketName}/{objectName}";
}
catch (Exception ex)
{
throw new Exception($"上传文件失败: {ex.Message}");
}
}
}

@ -1,4 +1,7 @@
using Infrastructure;
using Infrastructure.CloudSdk.minio;
using Infrastructure.Extensions;
using Minio;
using Newtonsoft.Json;
using OpenAuth.App.BaseApp.Base;
using OpenAuth.App.Interface;
@ -9,7 +12,11 @@ using OpenAuth.Repository.Domain;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Linq;
using System.Net;
using System.Text;
using System.Text.Json.Nodes;
using System.Threading.Tasks;
@ -19,9 +26,11 @@ namespace OpenAuth.App.ServiceApp.Algo
public class DaHuaAiApp : SqlSugarBaseApp<LasaAlgorithmsRepository, SugarDbContext>
{
public DaHuaAiApp(ISugarUnitOfWork<SugarDbContext> unitWork,
public MinioService _minioService;
public DaHuaAiApp(ISugarUnitOfWork<SugarDbContext> unitWork, MinioService minioService,
ISimpleClient<LasaAlgorithmsRepository> repository, IAuth auth) : base(unitWork, repository, auth)
{
_minioService = minioService;
}
#region 大华算法
@ -101,12 +110,17 @@ namespace OpenAuth.App.ServiceApp.Algo
using (var db = UnitWork.CreateContext())
{
var data = JsonConvert.DeserializeObject<dynamic>(info);
LasaAiAchievement lasaAiAchievement = new LasaAiAchievement();
lasaAiAchievement.Id = Guid.NewGuid().ToString();
lasaAiAchievement.Title = "疑似耕地破坏";
lasaAiAchievement.CreateTime = DateTime.Now;
lasaAiAchievement.AiModel = "DaHuaAi";
string detectRegionJson = JsonConvert.SerializeObject(data.info.detectRegion);
var regionArray = JsonConvert.DeserializeObject<dynamic>(detectRegionJson);
LasaAiAchievement lasaAiAchievement = new LasaAiAchievement
{
Id = Guid.NewGuid().ToString(),
Title = "耕地破坏区域报警",
CreateTime = DateTime.Now,
AiModel = "DaHuaAi"
};
var imageList = data.imageInfoList;
int index = 0;
foreach (var item in imageList)
{
//插入详情
@ -114,14 +128,26 @@ namespace OpenAuth.App.ServiceApp.Algo
{
Id = Guid.NewGuid().ToString(),
Image = item.imgUrl,
AiAchievementId = lasaAiAchievement.Id
AiAchievementId = lasaAiAchievement.Id,
Lng = (double?)item.longitude ?? 0.0,
Lat = (double?)item.latitude ?? 0.0,
};
//// 如果是第二张图片 -> 画区域 + 上传
//var a = await DrawingImgAndUpload(item.imgUrl, regionArray);
//if (index == 1)
//{
// //DrawingImgAsync();
// Console.WriteLine(item.imgUrl);
// Console.WriteLine(regionArray);
// a = await DrawingImgAndUpload(item.imgUrl, regionArray);
// lasaAiAchievementDetail.Image = a;
//}
lasaAiAchievement.Lat = item.latitude;
lasaAiAchievement.Lng = item.longitude;
lasaAiAchievement.Cover = item.imgUrl;
await db.LasaAiAchievementDetail.InsertAsync(lasaAiAchievementDetail);
index++;
}
await db.LasaAiAchievement.InsertAsync(lasaAiAchievement);
if (db.Commit())
return new Response<bool>
@ -137,6 +163,97 @@ namespace OpenAuth.App.ServiceApp.Algo
};
}
}
public async Task<string> DrawingImgAndUpload(string url, dynamic regionArray)
{
//var regionArray = JsonConvert.DeserializeObject<int[][]>(detectRegionJson);
Console.WriteLine($"regionArray 是否为空: {regionArray == null}, 长度: {regionArray?.Length}");
if (regionArray == null || regionArray.Length == 0)
throw new ArgumentException("detectRegion 参数无效");
Point[] polygon = new Point[regionArray.Length];
for (int i = 0; i < regionArray.Length; i++)
{
polygon[i] = new Point(regionArray[i][0], regionArray[i][1]);
}
using (HttpClient client = new HttpClient())
{
var bytes = await client.GetByteArrayAsync(url);
using (var ms = new MemoryStream(bytes))
using (var image = Image.FromStream(ms))
using (var bmp = new Bitmap(image))
using (var g = Graphics.FromImage(bmp))
{
g.SmoothingMode = SmoothingMode.AntiAlias;
using (var pen = new Pen(Color.Red, 5))
using (var brush = new SolidBrush(Color.FromArgb(80, Color.Blue)))
{
g.FillPolygon(brush, polygon);
g.DrawPolygon(pen, polygon);
}
using (var outputStream = new MemoryStream())
{
bmp.Save(outputStream, ImageFormat.Png);
outputStream.Position = 0;
string fileName = Path.GetFileName(new Uri(url).AbsolutePath);
// 上传到 MinIO直接传 MemoryStream
string uploadedUrl = await _minioService.UploadStreamFile(outputStream, fileName, "test", Guid.NewGuid().ToString());
Console.WriteLine(uploadedUrl);
return uploadedUrl;
}
}
}
}
public async void DrawingImgAsync()
{
string url = "http://123.132.248.154:6015/DroneEnforcement/2025/20250514/lQLPJyIVimQWGKnNA4PNA6Gw1D3q5gbxUvQIiumcIx4vAA_929_899.png";
string savePath = "output.png";
// detectRegion JSON可以直接替换成你的接口返回数据
string detectRegionJson = "[[0, 0],[8063, 647],[8017, 7774],[552, 8033]]";
// 解析 JSON
var regionArray = JsonConvert.DeserializeObject<int[][]>(detectRegionJson);
if (regionArray == null)
{
Console.WriteLine("解析 detectRegion 失败");
return;
}
Point[] polygon = new Point[regionArray.Length];
for (int i = 0; i < regionArray.Length; i++)
{
polygon[i] = new Point(regionArray[i][0], regionArray[i][1]);
}
using (HttpClient client = new HttpClient())
{
var bytes = await client.GetByteArrayAsync(url);
using (var ms = new System.IO.MemoryStream(bytes))
using (var image = Image.FromStream(ms))
using (var bmp = new Bitmap(image))
using (var g = Graphics.FromImage(bmp))
{
g.SmoothingMode = SmoothingMode.AntiAlias;
using (var pen = new Pen(Color.Red, 5)) // 红色边框
using (var brush = new SolidBrush(Color.FromArgb(80, Color.Blue))) // 半透明填充
{
g.FillPolygon(brush, polygon);
g.DrawPolygon(pen, polygon);
}
bmp.Save(savePath, ImageFormat.Png);
}
}
Console.WriteLine("已保存图片: " + savePath);
}
#endregion
@ -175,18 +292,19 @@ namespace OpenAuth.App.ServiceApp.Algo
}
else
{
if (item.class_id == 1 || item.class_id == 2 || item.class_id == 3 || item.class_id == 5 || item.class_id == 6 || item.class_id == 7)
{
lasaAiAchievement.Title = "车辆识别";
}
else if (item.class_id == 0)
{
lasaAiAchievement.Title = "人员识别";
}
else
{
lasaAiAchievement.Title = "其他识别";
}
lasaAiAchievement.Title = "其他识别";
//if (item.class_id == 1 || item.class_id == 2 || item.class_id == 3 || item.class_id == 5 || item.class_id == 6 || item.class_id == 7)
//{
// lasaAiAchievement.Title = "车辆识别";
//}
//else if (item.class_id == 0)
//{
// lasaAiAchievement.Title = "人员识别";
//}
//else
//{
// lasaAiAchievement.Title = "其他识别";
//}
}

@ -53,26 +53,63 @@ namespace OpenAuth.App.ServiceApp
{
using (var db = UnitWork.CreateContext())
{
// 更新主表
await db.LasaAlgorithmsRepository.UpdateAsync(info);
await db.LasaModelLabel.DeleteAsync(r => r.PId == info.Id);
foreach (var item in info.ModelLabels)
var modelLabelsInDb = db.LasaModelLabel.AsQueryable()
.Where(r => r.PId == info.Id)
.ToList();
var newModelLabels = info.ModelLabels ?? new List<LasaModelLabel>();
var toDelete = modelLabelsInDb
.Where(dbItem => !newModelLabels.Any(newItem => newItem.Id == dbItem.Id))
.ToList();
if (toDelete.Any())
{
item.Id = Guid.NewGuid().ToString();
item.PId = info.Id;
await db.LasaModelLabel.DeleteAsync(toDelete);
}
await db.LasaModelLabel.InsertRangeAsync(info.ModelLabels);
var toAdd = new List<LasaModelLabel>();
var toUpdate = new List<LasaModelLabel>();
foreach (var newItem in newModelLabels)
{
newItem.PId = info.Id;
if (string.IsNullOrEmpty(newItem.Id) || !modelLabelsInDb.Any(dbItem => dbItem.Id == newItem.Id))
{
// 新增
newItem.Id = Guid.NewGuid().ToString();
toAdd.Add(newItem);
}
else
{
// 更新
toUpdate.Add(newItem);
}
}
if (toAdd.Any())
await db.LasaModelLabel.InsertRangeAsync(toAdd);
if (toUpdate.Any())
await db.LasaModelLabel.UpdateRangeAsync(toUpdate);
// 提交事务
if (db.Commit())
{
return new Response<bool>
{
Result = true,
Message = "修改成功"
};
}
else
{
return new Response<bool>
{
Result = false,
Message = "修改失败"
};
}
}
}
//删除算法库

@ -823,7 +823,7 @@ namespace OpenAuth.App.ServiceApp.DroneDocking
public async Task<Response<bool>> ReportDroneStatus()
{
var droneList = await Repository
.ChangeRepository<SugarRepositiry<LasaUav>>()
.ChangeRepository<SugarRepositiry<LasaDronePort>>()
.AsQueryable()
.Where(it => it.IsDelete == false)
.ToListAsync();
@ -877,6 +877,7 @@ namespace OpenAuth.App.ServiceApp.DroneDocking
// 读取响应内容并反序列化
var responseBody = await response.Content.ReadAsStringAsync();
var result = JsonSerializer.Deserialize<ReciveData<string>>(responseBody);
Console.WriteLine($"无人机状态上报结果:{responseBody}");
//解密数据
byte[] resbytesx = Convert.FromBase64String(resxClScrete);
byte[] resdatabytes = Convert.FromBase64String(result?.data);

@ -392,7 +392,7 @@ namespace OpenAuth.App.ServiceApp
/// <param name="key"></param>
/// <returns></returns>
public async Task<Response<PageInfo<List<LasaTask>>>> GetTaskPageList(int page, int limit, string key,
int? status)
int? status,string airLineId)
{
RefAsync<int> totalCount = 0;
using (var db = UnitWork.CreateContext())
@ -400,6 +400,7 @@ namespace OpenAuth.App.ServiceApp
var list = await db.LasaTask.AsQueryable()
.WhereIF(!string.IsNullOrEmpty(key), a => a.TaskName.Contains(key))
.WhereIF(status != null, a => a.Status.Equals(status))
.WhereIF(!string.IsNullOrEmpty(airLineId), a => a.AirLineId == airLineId)
.OrderByDescending(a => a.CreateTime)
.ToPageListAsync(page, limit, totalCount);
return new Response<PageInfo<List<LasaTask>>>
@ -2437,6 +2438,7 @@ namespace OpenAuth.App.ServiceApp
}
else
{
// 计划任务
var aiInspection = await Repository
.ChangeRepository<SugarRepositiry<LasaAiInspection>>()
.AsQueryable().Where(x => x.TaskId == req.TaskId).FirstAsync();
@ -2499,7 +2501,7 @@ namespace OpenAuth.App.ServiceApp
}
json.tag = jsonTag;
Console.WriteLine(JsonConvert.SerializeObject(json));
_logger.LogDebug($"发送的json:{JsonConvert.SerializeObject(json)}");
var content = new StringContent(JsonConvert.SerializeObject(json), Encoding.UTF8, "application/json");
var url = config["AIModelApi:Url"];
using var httpClient = new HttpClient();

@ -35,6 +35,7 @@ public class ConfigSubscribe : IJob
private object _dockUploadFileLocker = new();
private readonly ILogger<ConfigSubscribe> _logger;
private readonly ConcurrentDictionary<string, DateTime> _processedMessages = new();
private readonly ConcurrentDictionary<string, string> liveInfo = new();
private readonly TimeSpan _deduplicationWindow = TimeSpan.FromMinutes(1);
public ConfigSubscribe(MqttClientManager mqttClientManager, ISqlSugarClient sqlSugarClient,
@ -104,6 +105,9 @@ public class ConfigSubscribe : IJob
var data = result.data;
//_logger.LogInformation($"主题:{topic}\n消息{message}");
long code = 0;
// rtmp://175.27.168.120:6019/live/
var rtmp = "rtmp://box.wisestcity.com:1935/live/7";
//var rtmp = "rtmp://175.27.168.120:6019/live/7";
switch (tempStr)
{
case "thing/product/*/requests":
@ -544,51 +548,22 @@ public class ConfigSubscribe : IJob
break;
case "flighttask_progress":
{
string flightId1 = (string)data.output.ext.flight_id;
var waylineMissionState = (int)data.output.ext.wayline_mission_state;
// current_step
// "0":"初始状态"
// "1":"启动前检查,飞行器是否在执行航线中"
// "2":"启动前检查,机场是否退出工作模式"
// "3":"启动前检查,航线执行中"
// "4":"启动前检查,返航中"
// "5":"航线执行进入准备状态,开始等待任务下发"
// "6":"机场进入工作状态"
// "7":"进入开机检查准备工作和开盖准备工作"
// "8":"图传远程对频"
// "9":"等待飞行系统准备就绪,推送连接建立"
// "10":"等待 RTK 源监听有值上报"
// "11":"检查 RTK 源是否是机场源,如果不是要重新设置"
// "12":"等待飞行控制权通知"
// "13":"机场无控制权,抢夺飞行器控制权"
// "14":"自定义飞行区一致性检查"
// "15":"离线地图一致性检查"
// "16":"获取最新 KMZ URL"
// "17":"下载 KMZ"
// "18":"KMZ 上传中"
// "19":"染色配置"
// "20":"飞行器起飞参数设置,备降点设置,起飞高度设置,染色设置"
// "21":"飞行器 flyto 起飞参数设置"
// "22":"起飞机场检查降落机场准备状态"
// "23":"Home 点设置"
// "24":"触发执行航线"
// "25":"航线执行中"
// "26":"进入返航的检查准备工作"
// "27":"飞行器降落机场"
// "28":"降落以后的关盖"
// "29":"机场退出工作模式"
// "30":"机场异常恢复","31":"机场上传飞行系统日志","32":"相机录像状态检查","33":"获取媒体文件数量","34":"机场起飞开盖的异常恢复","35":"通知任务结果","36":"日志列表拉取 - 飞行器列表","37":"日志列表拉取 - 拉取机场列表","38":"日志列表拉取 - 上传日志列表结果","39":"日志拉取-拉取飞行器日志","40":"日志拉取-拉取机场日志","41":"日志拉取-压缩飞行器日志","42":"日志拉取-压缩机场日志","43":"日志拉取-上传飞行器日志","44":"日志拉取-上传机场日志","45":"日志拉取-通知结果","46":"自定义飞行区文件更新准备中","47":"自定义飞行区更新中","48":"离线地图更新准备中","49":"离线地图更新中","65533":"结束后等待服务回包","65534":"无具体状态","65535":"UNKNOWN"}
var isHandle = IsDuplicate(Md5.Encrypt(message));
_logger.LogDebug($"md5: {isHandle} 重复否:{IsDuplicate(Md5.Encrypt(message))} 信息:{message} ");
var isHandle = IsDuplicate(Md5.Encrypt($"{result.bid}{flightId1}"));
_logger.LogDebug($"md5: {isHandle} 重复否:{IsDuplicate(Md5.Encrypt(message))}" +
$"主题:{topic} 信息:{message} ");
if (isHandle)
{
_logger.LogInformation("跳过处理");
break;
}
_logger.LogDebug("航线进度未跳过处理");
code = data.result; // result
var waylineMissionState = (int)data.output.ext.wayline_mission_state;
string flightId1 = (string)data.output.ext.flight_id;
var taskAssign1 = _manageApp.GetTaskAssignByFlightId(flightId1);
// 处理航线进度 ,也有可能是失败
if (code != 0)
@ -630,7 +605,7 @@ public class ConfigSubscribe : IJob
{
var step = (int)data.output.progress.current_step;
_logger.LogDebug($"航线进度:{waylineMissionState} {step} {message}");
if (step.Equals(25)) // 航线执行
if (step.Equals(25)) // todo 关于会接收到不同消息问题,如何处理
{
var task = await _sqlSugarClient.Queryable<LasaTask>()
.FirstAsync(y => y.Id == taskAssign1.TaskId);
@ -638,11 +613,13 @@ public class ConfigSubscribe : IJob
task.AIInspection.Equals("true") && string.IsNullOrEmpty(task.PushUrl))
{
_logger.LogDebug("执行AI 智能巡检。。。。。");
var rtmp = "rtmp://box.wisestcity.com:1935/live/7";
//var rtmp = "rtmp://box.wisestcity.com:1935/live/7";
var bid = Guid.NewGuid().ToString();
var tid = Guid.NewGuid().ToString();
var param = @$"{{
""bid"": ""{Guid.NewGuid().ToString()}"",
""bid"": ""{bid}"",
""method"": ""live_start_push"",
""tid"": ""{Guid.NewGuid().ToString()}"",
""tid"": ""{tid}"",
""timestamp"": {DateTimeOffset.Now.ToUnixTimeMilliseconds()},
""data"": {{
""url_type"": 1,
@ -655,9 +632,7 @@ public class ConfigSubscribe : IJob
var topicRequest = $"thing/product/{sn}/services";
// 开启直播
await _mqttClientManager.PublishAsync(topicRequest, param);
// todo 关于直播是否开启成功
var req = new CallAiModel { TaskId = taskAssign1.TaskId, RtmpUrl = rtmp };
await _manageApp.CallAiModel(req);
liveInfo[$"{tid}{bid}"] = taskAssign1.TaskId;
}
}
@ -666,7 +641,7 @@ public class ConfigSubscribe : IJob
{
var task = await _sqlSugarClient.Queryable<LasaTask>()
.FirstAsync(y => y.Id == taskAssign1.TaskId);
if (!string.IsNullOrEmpty(task.AIInspection) && task.AIInspection.Equals(true) &&
if (!string.IsNullOrEmpty(task.AIInspection) && task.AIInspection.Equals("true") &&
!string.IsNullOrEmpty(task.PushUrl))
{
// todo video_id 需要根据不同设备改变
@ -740,9 +715,15 @@ public class ConfigSubscribe : IJob
{
break;
}
// todo 已验证tid bid 是相同的
// todo 开启直播成功调用ai model
// 已验证tid bid 是相同的
// 开启直播成功调用ai model
_logger.LogDebug($"开启直播成功 {message}");
// 关于直播是否开启成功
// 取得taskid 然后从liveInfo中移除
var tempTaskId = liveInfo[$"{result.tid}{result.bid}"];
liveInfo.TryRemove($"{result.tid}{result.bid}", out _);
var req = new CallAiModel { TaskId = tempTaskId, RtmpUrl = rtmp };
await _manageApp.CallAiModel(req);
break;
case "live_stop_push":
_logger.LogDebug($"停止直播成功 {message}");

@ -1,4 +1,5 @@
using Infrastructure;
using DocumentFormat.OpenXml.Bibliography;
using Infrastructure;
using Infrastructure.Helpers;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
@ -234,6 +235,18 @@ namespace OpenAuth.WebApi.Controllers.ServiceControllers
}
}
/// <summary>
/// 测试大华
/// </summary>
/// <param name="info"></param>
/// <param name="detectRegionJson"></param>
[HttpPost]
[AllowAnonymous]
public async void DrawingImgAndUploadAsync(string info, int[][] detectRegionJson)
{
await _app.DrawingImgAndUpload(info, detectRegionJson);
}
/// <summary>
/// 测试插入数据
/// </summary>
/// <param name="info"></param>
@ -249,7 +262,7 @@ namespace OpenAuth.WebApi.Controllers.ServiceControllers
[AllowAnonymous]
public async Task<Response<bool>> AddImg([FromBody] AiImgReq request)
{
return await _app.AddImg(request.taskid, request.path, request.aiid,request.drone_info, request.tag);
return await _app.AddImg(request.taskid, request.path, request.aiid, request.drone_info, request.tag);
}
#endregion
}

@ -231,12 +231,12 @@ namespace OpenAuth.WebApi.Controllers.ServiceControllers
/// <returns></returns>
[HttpGet]
public async Task<Response<PageInfo<List<LasaTask>>>> GetTaskPageList(int page, int limit, string key,
int? status)
int? status,string airLineId)
{
var result = new Response<PageInfo<List<LasaTask>>>();
try
{
result = await _app.GetTaskPageList(page, limit, key, status);
result = await _app.GetTaskPageList(page, limit, key, status,airLineId);
}
catch (Exception ex)
{

@ -187,8 +187,8 @@ namespace OpenAuth.WebApi
services.AddHostedService<DelayedExecutionService>();
#region rabbitmq
//services.AddSingleton<RabbitMqListenerService>();
//services.AddHostedService(sp => sp.GetRequiredService<RabbitMqListenerService>());
services.AddSingleton<RabbitMqListenerService>();
services.AddHostedService(sp => sp.GetRequiredService<RabbitMqListenerService>());
#endregion
#region AppSetting

@ -23,7 +23,7 @@ public class DelayedExecutionService : BackgroundService
{
await PerformDelayedTask();
// 等待5秒
await Task.Delay(TimeSpan.FromSeconds(5), stoppingToken);
await Task.Delay(TimeSpan.FromMinutes(5), stoppingToken);
}
catch (OperationCanceledException)
{

@ -22,7 +22,7 @@
"UploadPath": "",
//
"RedisConf": {
"Conn": "123.132.248.154:9253,password=HopetryRedis1406",
"Conn": "192.168.10.163:6379,password=123456",
//"Conn": "127.0.0.1:6379,password=123456",
"Database": 7
},
@ -87,7 +87,7 @@
"DbFile": "D:/",
"JYMUrl": "E:/低空态势感知/资料/省对接/质检/LandCloud.CGDBPreCheckTool.exe"
},
"AIModelApi":{
"AIModelApi": {
"Url": "http://192.168.10.131:9025",
"PushUrl":"rtmp://192.168.3.17:1935/live/11"
}

Loading…
Cancel
Save