|
|
|
@ -1,12 +1,18 @@
|
|
|
|
|
using System.Drawing;
|
|
|
|
|
using System.Dynamic;
|
|
|
|
|
using System.Net;
|
|
|
|
|
using System.Text;
|
|
|
|
|
using Infrastructure;
|
|
|
|
|
using Infrastructure.CloudSdk;
|
|
|
|
|
using Infrastructure.CloudSdk.minio;
|
|
|
|
|
using Infrastructure.CloudSdk.wayline;
|
|
|
|
|
using Infrastructure.Extensions;
|
|
|
|
|
using Infrastructure.Helpers;
|
|
|
|
|
using MetadataExtractor;
|
|
|
|
|
using MetadataExtractor.Formats.Exif;
|
|
|
|
|
using Microsoft.AspNetCore.Http;
|
|
|
|
|
using Microsoft.IdentityModel.Tokens;
|
|
|
|
|
using Microsoft.Net.Http.Headers;
|
|
|
|
|
using Newtonsoft.Json;
|
|
|
|
|
using Newtonsoft.Json.Linq;
|
|
|
|
|
using OpenAuth.App.BaseApp.Base;
|
|
|
|
@ -22,6 +28,8 @@ using OpenAuth.Repository.Domain;
|
|
|
|
|
using OpenAuth.WebApi;
|
|
|
|
|
using OpenAuth.WebApi.CloudSdk;
|
|
|
|
|
using SqlSugar;
|
|
|
|
|
using Directory = System.IO.Directory;
|
|
|
|
|
using RangeHeaderValue = System.Net.Http.Headers.RangeHeaderValue;
|
|
|
|
|
|
|
|
|
|
namespace OpenAuth.App.ServiceApp
|
|
|
|
|
{
|
|
|
|
@ -969,7 +977,8 @@ namespace OpenAuth.App.ServiceApp
|
|
|
|
|
?.Value<int>(); // {"0":"无雨","1":"小雨","2":"中雨","3":"大雨"}
|
|
|
|
|
|
|
|
|
|
// 如果没有天气阻飞?
|
|
|
|
|
if (windSpeedThreshold <= windSpeed || rainThreshold <= rainfall || weatherWindSpeedThreshold <= weatherWindSpeed)
|
|
|
|
|
if (windSpeedThreshold <= windSpeed || rainThreshold <= rainfall ||
|
|
|
|
|
weatherWindSpeedThreshold <= weatherWindSpeed)
|
|
|
|
|
{
|
|
|
|
|
// 不让起飞
|
|
|
|
|
// 更新失败原因
|
|
|
|
@ -1871,5 +1880,283 @@ namespace OpenAuth.App.ServiceApp
|
|
|
|
|
Result = true
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public async Task<Response<bool>> Test1111(string msg)
|
|
|
|
|
{
|
|
|
|
|
var sn = "8UUXN5400A079H";
|
|
|
|
|
var result = JsonConvert.DeserializeObject<TopicServicesRequest<dynamic>>(msg);
|
|
|
|
|
var method = result.method;
|
|
|
|
|
var data = result.data;
|
|
|
|
|
int flightType = data.flight_task.flight_type;
|
|
|
|
|
string flightId = data.file.ext.flight_id;
|
|
|
|
|
var taskAssign = GetTaskAssignByFlightId(flightId);
|
|
|
|
|
var taskId = taskAssign.TaskId;
|
|
|
|
|
var executeTask = await Repository.AsSugarClient()
|
|
|
|
|
.Queryable<LasaTask>()
|
|
|
|
|
.SingleAsync(a => a.Id == taskId);
|
|
|
|
|
string objectKey = data.file.object_key;
|
|
|
|
|
var folderKey = ((string)data.file.object_key).Split("/");
|
|
|
|
|
var parentKey = folderKey[2];
|
|
|
|
|
var isExist = await Repository.AsSugarClient()
|
|
|
|
|
.Queryable<LasaMediaFile>()
|
|
|
|
|
.Where(x => x.Id.Equals(parentKey)).CountAsync();
|
|
|
|
|
if (isExist == 0)
|
|
|
|
|
{
|
|
|
|
|
var date = DateTime.Now;
|
|
|
|
|
var timeStr = date.ToString("yyyy-MM-dd HH:mm:ss");
|
|
|
|
|
var parent1 = new LasaMediaFile()
|
|
|
|
|
{
|
|
|
|
|
Id = folderKey[2],
|
|
|
|
|
FlightId = flightId,
|
|
|
|
|
TaskId = taskId,
|
|
|
|
|
ParentKey = "0",
|
|
|
|
|
Name = string.IsNullOrEmpty(executeTask.TaskName)
|
|
|
|
|
? timeStr
|
|
|
|
|
: $"{executeTask.TaskName} {timeStr}",
|
|
|
|
|
WorkspaceId = executeTask.WorkspaceId,
|
|
|
|
|
CreateTime = date,
|
|
|
|
|
};
|
|
|
|
|
await Repository.AsSugarClient().Insertable(parent1).ExecuteCommandAsync();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 重复检测
|
|
|
|
|
var mediaFile = await Repository.AsSugarClient()
|
|
|
|
|
.Queryable<LasaMediaFile>()
|
|
|
|
|
.Where(a => a.FlightId.Equals(flightId))
|
|
|
|
|
.Where(a => a.ObjectKey.Equals(objectKey)).SingleAsync();
|
|
|
|
|
if (mediaFile == null)
|
|
|
|
|
{
|
|
|
|
|
var type = 0;
|
|
|
|
|
var preSize = 5;
|
|
|
|
|
// todo 判断是不是图片
|
|
|
|
|
if (objectKey.EndsWith(".jpeg")) // todo 是否有其它类型的图片,待确定
|
|
|
|
|
{
|
|
|
|
|
preSize = 65535;
|
|
|
|
|
var fileName = Path.GetFileNameWithoutExtension(objectKey);
|
|
|
|
|
var fileNameParts = fileName.Split("_");
|
|
|
|
|
var suffix = fileNameParts[^1];
|
|
|
|
|
type = suffix switch
|
|
|
|
|
{
|
|
|
|
|
// 0 未知 1 可见光 2 红外 3 变焦 4.广角 5 视频
|
|
|
|
|
"V" => 1,
|
|
|
|
|
"T" => 2,
|
|
|
|
|
"Z" => 3, // 变焦
|
|
|
|
|
"W" => 4, // 广角
|
|
|
|
|
_ => type
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
else if (objectKey.EndsWith(".mp4"))
|
|
|
|
|
{
|
|
|
|
|
type = 5;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
string suoluokey = "";
|
|
|
|
|
long? fileSize = 0;
|
|
|
|
|
int width = 0, height = 0, focalLength = 0;
|
|
|
|
|
int offset = 0, length = 0;
|
|
|
|
|
string model = "";
|
|
|
|
|
|
|
|
|
|
var fileUrl = "http://" + _minioService.endPoint + "/" + _minioService._bucketName +
|
|
|
|
|
"/" + objectKey;
|
|
|
|
|
using (var httpClient = new HttpClient())
|
|
|
|
|
{
|
|
|
|
|
suoluokey = "minipic/" + data.file.name.ToString();
|
|
|
|
|
// 目前读取64KB
|
|
|
|
|
// 添加Range请求头
|
|
|
|
|
httpClient.DefaultRequestHeaders.Range =
|
|
|
|
|
new RangeHeaderValue(0, preSize);
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
var response = httpClient
|
|
|
|
|
.GetAsync(fileUrl, HttpCompletionOption.ResponseHeadersRead).Result;
|
|
|
|
|
if (response.StatusCode == HttpStatusCode.PartialContent)
|
|
|
|
|
{
|
|
|
|
|
//Focal Length 35: 24 mm
|
|
|
|
|
//Exif Image Width: 4032 pixels : Exif SubIFD
|
|
|
|
|
//Exif Image Height: 3024 pixels : Exif SubIFD
|
|
|
|
|
// 3.1 解析Content-Range头(格式:bytes start-end/total)
|
|
|
|
|
var contentRange = response.Content.Headers.ContentRange;
|
|
|
|
|
if (contentRange != null)
|
|
|
|
|
{
|
|
|
|
|
fileSize = contentRange.Length.Value;
|
|
|
|
|
Console.WriteLine(
|
|
|
|
|
$"获取范围:{contentRange.From}-{contentRange.To}/{contentRange.Length}");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (objectKey.ToLower().EndsWith("jpeg"))
|
|
|
|
|
{
|
|
|
|
|
// 成功获取部分内容
|
|
|
|
|
var y = response.Content.ReadAsByteArrayAsync().Result;
|
|
|
|
|
MemoryStream ms = new MemoryStream(y);
|
|
|
|
|
var directories = ImageMetadataReader.ReadMetadata(ms);
|
|
|
|
|
foreach (var directory in directories)
|
|
|
|
|
{
|
|
|
|
|
if (directory is ExifDirectoryBase)
|
|
|
|
|
{
|
|
|
|
|
if (directory.Name.Equals("Exif IFD0"))
|
|
|
|
|
{
|
|
|
|
|
foreach (var tag in directory.Tags)
|
|
|
|
|
{
|
|
|
|
|
if (tag.Name.Equals("Model"))
|
|
|
|
|
{
|
|
|
|
|
model = tag.Description;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (directory.Name.Equals("Exif SubIFD"))
|
|
|
|
|
{
|
|
|
|
|
foreach (var tag in directory.Tags)
|
|
|
|
|
{
|
|
|
|
|
if (tag.Name.Equals("Exif Image Width"))
|
|
|
|
|
{
|
|
|
|
|
width = int.Parse(tag.Description.Replace("pixels", "")
|
|
|
|
|
.Trim());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (tag.Name.Equals("Exif Image Height"))
|
|
|
|
|
{
|
|
|
|
|
height = int.Parse(tag.Description.Replace("pixels", "")
|
|
|
|
|
.Trim());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (tag.Name.Equals("Focal Length 35"))
|
|
|
|
|
{
|
|
|
|
|
focalLength = int.Parse(tag.Description
|
|
|
|
|
.Replace("mm", "")
|
|
|
|
|
.Trim());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//Console.WriteLine(directory.Name);
|
|
|
|
|
if (directory.Name.Equals("Exif Thumbnail"))
|
|
|
|
|
{
|
|
|
|
|
foreach (var tag in directory.Tags)
|
|
|
|
|
{
|
|
|
|
|
if (tag.Name.Equals("Thumbnail Offset"))
|
|
|
|
|
{
|
|
|
|
|
offset = int.Parse(tag.Description.Replace("bytes", "")
|
|
|
|
|
.Trim());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (tag.Name.Equals("Thumbnail Length"))
|
|
|
|
|
{
|
|
|
|
|
length = int.Parse(tag.Description.Replace("bytes", "")
|
|
|
|
|
.Trim());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ms.Seek(offset + 6, SeekOrigin.Begin);
|
|
|
|
|
byte[] buffer = new byte[length];
|
|
|
|
|
int bytesRead = ms.Read(buffer, 0, length);
|
|
|
|
|
// 上传缩略图到MinIO
|
|
|
|
|
await _minioService.PutObjectAsync("", data.file.name.ToString(), suoluokey,
|
|
|
|
|
new MemoryStream(buffer));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (response.StatusCode == HttpStatusCode.OK)
|
|
|
|
|
{
|
|
|
|
|
// 服务器不支持Range请求,返回完整内容
|
|
|
|
|
throw new InvalidOperationException("服务器不支持Range请求");
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
throw new HttpRequestException($"请求失败: {response.StatusCode}");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
throw new Exception($"执行错误: {ex.Message}", ex);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var createdTimeStr = (string)data.file.metadata.created_time;
|
|
|
|
|
var createTime = string.IsNullOrEmpty(createdTimeStr)
|
|
|
|
|
? DateTime.Now
|
|
|
|
|
: createdTimeStr.ToDateTime();
|
|
|
|
|
var fileUpload = new LasaMediaFile()
|
|
|
|
|
{
|
|
|
|
|
Id = Guid.NewGuid().ToString(),
|
|
|
|
|
FlightId = flightId, // 计划id
|
|
|
|
|
TaskId = taskAssign.TaskId, // 任务id
|
|
|
|
|
DroneModelKey = data.file.ext.drone_model_key, // 无人机型号
|
|
|
|
|
PayloadModelKey = data.file.ext.payload_model_key, //这应该可以标明是什么设置
|
|
|
|
|
IsOriginal = data.file.ext.is_original,
|
|
|
|
|
MediaIndex = data.file.ext.media_index,
|
|
|
|
|
AbsoluteAltitude = data.file.metadata.absolute_altitude, // 拍摄绝对高度
|
|
|
|
|
GimbalYawDegree = data.file.metadata.gimbal_yaw_degree, //云台偏航角度
|
|
|
|
|
RelativeAltitude = data.file.metadata.relative_altitude, // 拍摄相对高度
|
|
|
|
|
Lat = data.file.metadata.shoot_position.lat,
|
|
|
|
|
Lng = data.file.metadata.shoot_position.lng,
|
|
|
|
|
Name = data.file.name,
|
|
|
|
|
ObjectKey = data.file.object_key,
|
|
|
|
|
Path = data.file.path, // 目前这个好像没有值
|
|
|
|
|
CreateTime = createTime,
|
|
|
|
|
WorkspaceId = executeTask.WorkspaceId,
|
|
|
|
|
ParentKey = folderKey[2],
|
|
|
|
|
Tid = result.tid,
|
|
|
|
|
Bid = result.bid,
|
|
|
|
|
FlightType = flightType,
|
|
|
|
|
Width = width,
|
|
|
|
|
Height = height,
|
|
|
|
|
minipic = suoluokey,
|
|
|
|
|
Size = fileSize,
|
|
|
|
|
ShowOnMap = 1,
|
|
|
|
|
display = 1,
|
|
|
|
|
FocalLength = focalLength,
|
|
|
|
|
PayloadModelName = model,
|
|
|
|
|
Type = type
|
|
|
|
|
};
|
|
|
|
|
// todo 添加事务
|
|
|
|
|
await Repository.AsSugarClient().Insertable(fileUpload).ExecuteCommandAsync();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (result.need_reply.Equals(1))
|
|
|
|
|
{
|
|
|
|
|
var fileUploadCallbackEventReply = new FileUploadCallbackEventReply<object>()
|
|
|
|
|
{
|
|
|
|
|
bid = result.bid,
|
|
|
|
|
tid = result.tid,
|
|
|
|
|
method = "file_upload_callback",
|
|
|
|
|
gateway = sn,
|
|
|
|
|
data = new
|
|
|
|
|
{
|
|
|
|
|
result = 0
|
|
|
|
|
},
|
|
|
|
|
timestamp = DateTimeOffset.Now.ToUnixTimeMilliseconds(),
|
|
|
|
|
};
|
|
|
|
|
_ = _mqttClientManager.PublishAsync($"thing/product/{sn}/events_reply",
|
|
|
|
|
JsonConvert.SerializeObject(fileUploadCallbackEventReply));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var expectFileCount = data.flight_task.expected_file_count;
|
|
|
|
|
var uploadedFileCount = data.flight_task.uploaded_file_count;
|
|
|
|
|
|
|
|
|
|
var taskRecord = new LasaTask()
|
|
|
|
|
{
|
|
|
|
|
Id = taskId,
|
|
|
|
|
ExpectedFileCount = expectFileCount, // 期望文件数量
|
|
|
|
|
UploadedFileCount = uploadedFileCount // 已上传文件数量
|
|
|
|
|
};
|
|
|
|
|
// 当expectFileCount 等于uploadedFileCount时,则表示航线执行完成
|
|
|
|
|
/*
|
|
|
|
|
if (uploadedFileCount.Equals(expectFileCount))
|
|
|
|
|
{
|
|
|
|
|
taskRecord.Status = 5; // 成功状态
|
|
|
|
|
}
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
await Repository.AsSugarClient().Updateable(taskRecord)
|
|
|
|
|
.IgnoreNullColumns().ExecuteCommandAsync();
|
|
|
|
|
|
|
|
|
|
return new Response<bool>()
|
|
|
|
|
{
|
|
|
|
|
Result = true
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|