Merge remote-tracking branch 'origin/sprint-731' into sprint-731

This commit is contained in:
huangxianguo 2024-08-23 14:14:13 +08:00
commit 6014885442
14 changed files with 236 additions and 71 deletions

View File

@ -21,4 +21,24 @@ public class Md5Util
return hashString.ToString(); return hashString.ToString();
} }
/// <summary>
/// 计算压缩包md5
/// </summary>
/// <param name="filePath"></param>
/// <returns></returns>
public static string Md5ForZipFile(string filePath)
{
using (var md5 = MD5.Create())
{
using (var stream = File.OpenRead(filePath))
{
// 计算文件流的哈希值
var hash = md5.ComputeHash(stream);
// 将哈希值转换为字符串格式
var hashString = BitConverter.ToString(hash).Replace("-", string.Empty).ToLowerInvariant();
return hashString;
}
}
}
} }

View File

@ -13,7 +13,7 @@ using System.Reflection;
[assembly: System.Reflection.AssemblyCompanyAttribute("MasstransferCommon")] [assembly: System.Reflection.AssemblyCompanyAttribute("MasstransferCommon")]
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+a303714a635d3146132582a2408fc8cf76a69947")] [assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+64cf3396835594f835ea904d6fccf95de4bc3e01")]
[assembly: System.Reflection.AssemblyProductAttribute("MasstransferCommon")] [assembly: System.Reflection.AssemblyProductAttribute("MasstransferCommon")]
[assembly: System.Reflection.AssemblyTitleAttribute("MasstransferCommon")] [assembly: System.Reflection.AssemblyTitleAttribute("MasstransferCommon")]
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]

View File

@ -1 +1 @@
04161de5d5b7e53625665da3c9aa9d1cc0c406c72bef7aeb16057254b572fd39 24bba642a13e6757b4f3f31fb043b50bb46d2cbfc99854439c2393c381e11be8

View File

@ -6,6 +6,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MasstransferInfrastructure"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MasstransferCommon", "MasstransferCommon\MasstransferCommon.csproj", "{66C6D73C-BADB-4E28-9C83-E701B019626D}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MasstransferCommon", "MasstransferCommon\MasstransferCommon.csproj", "{66C6D73C-BADB-4E28-9C83-E701B019626D}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestProject1", "TestProject1\TestProject1.csproj", "{D26C3A44-62AF-4ACC-B454-51E1098C2C86}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@ -24,5 +26,9 @@ Global
{66C6D73C-BADB-4E28-9C83-E701B019626D}.Debug|Any CPU.Build.0 = Debug|Any CPU {66C6D73C-BADB-4E28-9C83-E701B019626D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{66C6D73C-BADB-4E28-9C83-E701B019626D}.Release|Any CPU.ActiveCfg = Release|Any CPU {66C6D73C-BADB-4E28-9C83-E701B019626D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{66C6D73C-BADB-4E28-9C83-E701B019626D}.Release|Any CPU.Build.0 = Release|Any CPU {66C6D73C-BADB-4E28-9C83-E701B019626D}.Release|Any CPU.Build.0 = Release|Any CPU
{D26C3A44-62AF-4ACC-B454-51E1098C2C86}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D26C3A44-62AF-4ACC-B454-51E1098C2C86}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D26C3A44-62AF-4ACC-B454-51E1098C2C86}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D26C3A44-62AF-4ACC-B454-51E1098C2C86}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
EndGlobal EndGlobal

View File

@ -1,45 +1,11 @@
using System.IO.Compression; using System.IO.Compression;
using MasstransferCommon.Model.Constant;
using MasstransferCommunicate.Mqtt;
using MasstransferCommon.Utils; using MasstransferCommon.Utils;
using MasstransferCommunicate.Mqtt.Client;
using MasstransferExporter.OTA.Model;
namespace MasstransferExporter.OTA.Client; namespace MasstransferExporter.OTA.Client;
public class OTAClient public class OTAClient
{ {
/// <summary>
/// 订阅OTA更新
/// </summary>
public static async Task ListenOTAUpdateEvent()
{
await MessageQueueHelper.Subscribe(Topics.IssuedOTAPackage, HandleUpdateOTAEvent);
}
/// <summary>
/// 查询OTA更新
/// </summary>
/// <param name="result"></param>
public static async Task QueryOTAUpdate(string result)
{
await MessageQueueHelper.Publish(Topics.QueryOTA, result);
}
/// <summary>
/// OTA更新反馈
/// </summary>
/// <param name="resutl"></param>
public static async Task OTALicenseUpdateEventFeedback(string resutl)
{
await MessageQueueHelper.Publish(Topics.OTAUpgradeFeedback, resutl);
}
private static async Task HandleUpdateOTAEvent(string topic, string license)
{
}
/// <summary> /// <summary>
/// 备份保存重要文件 /// 备份保存重要文件
/// </summary> /// </summary>
@ -47,7 +13,7 @@ public class OTAClient
/// <param name="destinationDir">目标地址</param> /// <param name="destinationDir">目标地址</param>
/// <param name="fileExtension">保存文件扩展名</param> /// <param name="fileExtension">保存文件扩展名</param>
/// <param name="logFileDir">保存文件日志</param> /// <param name="logFileDir">保存文件日志</param>
public void BackupEssentialFiles(string sourceDir, string destinationDir, string[] fileExtension, string logFileDir) public static void BackupEssentialFiles(string sourceDir, string destinationDir, string[] fileExtension, string logFileDir)
{ {
try try
{ {
@ -92,7 +58,7 @@ public class OTAClient
/// 恢复重要文件 /// 恢复重要文件
/// </summary> /// </summary>
/// <param name="logFileDir">重要文件备份日志</param> /// <param name="logFileDir">重要文件备份日志</param>
public void RecoverCriticalFiles(string logFileDir) public static void RecoverCriticalFiles(string logFileDir)
{ {
try try
{ {
@ -121,7 +87,7 @@ public class OTAClient
/// </summary> /// </summary>
/// <param name="sourceDir">源目录地址</param> /// <param name="sourceDir">源目录地址</param>
/// <param name="zipFilePath">压缩文件保存地址</param> /// <param name="zipFilePath">压缩文件保存地址</param>
public void CompressDirectory(string sourceDir, string zipFilePath) public static void CompressDirectory(string sourceDir, string zipFilePath)
{ {
try try
{ {
@ -148,7 +114,7 @@ public class OTAClient
/// </summary> /// </summary>
/// <param name="zipFilePath">压缩文件地址</param> /// <param name="zipFilePath">压缩文件地址</param>
/// <param name="extractPath">解压目录</param> /// <param name="extractPath">解压目录</param>
public void ExtractDirectory(string zipFilePath, string extractPath) public static void ExtractDirectory(string zipFilePath, string extractPath)
{ {
try try
{ {
@ -170,7 +136,7 @@ public class OTAClient
/// 删除目录 /// 删除目录
/// </summary> /// </summary>
/// <param name="sourceDir">删除目录地址</param> /// <param name="sourceDir">删除目录地址</param>
public void DeleteDirectory(string sourceDir) public static void DeleteDirectory(string sourceDir)
{ {
if (Directory.Exists(sourceDir)) if (Directory.Exists(sourceDir))
{ {
@ -183,11 +149,28 @@ public class OTAClient
/// 删除文件 /// 删除文件
/// </summary> /// </summary>
/// <param name="sourceDir">删除文件地址</param> /// <param name="sourceDir">删除文件地址</param>
public void DeleteFile(string sourceDir) public static void DeleteFile(string sourceDir)
{ {
if (File.Exists(sourceDir)) if (File.Exists(sourceDir))
{ {
File.Delete(sourceDir); File.Delete(sourceDir);
} }
} }
/// <summary>
/// 校验安装包
/// </summary>
/// <param name="md5"></param>
public static bool CheckMD5(string md5, string file_path)
{
var file_md5 = Md5Util.Md5ForZipFile(file_path);
if (file_md5.Equals(md5))
{
return true;
}
else
{
return false;
}
}
} }

View File

@ -0,0 +1,12 @@
namespace MasstransferExporter.OTA.Model;
public class OTAResultData
{
public byte Result { get; set; }
public string Msg { get; set; }
public string OtaSoftwareVersion { get; set; }
public string CurrentSoftwareVersion { get; set; }
}

View File

@ -0,0 +1,22 @@
using Org.BouncyCastle.Utilities;
namespace MasstransferExporter.OTA.Model;
public class OTAUpdateData
{
public byte Type { get; set; }
public string Url { get; set; }
public string Version { get; set; }
public string Module { get; set; }
public long Size { get; set; }
public string Checksum { get; set; }
public string Name { get; set; }
public string Description { get; set; }
}

View File

@ -1,8 +0,0 @@
namespace MasstransferExporter.OTA.Model;
public class UpdateInfo
{
public bool IsUpdateAvailable { get; set; }
public string Version { get; set; }
public string DownloadUrl { get; set; }
}

View File

@ -1,11 +1,13 @@
using MasstransferExporter.OTA.Client; using MasstransferCommon.Model.Constant;
using MasstransferCommon.Utils;
using MasstransferCommunicate.Mqtt.Client;
using MasstransferExporter.OTA.Client;
using MasstransferExporter.OTA.Model;
namespace MasstransferExporter.OTA.Service; namespace MasstransferExporter.OTA.Service;
public class OTAService public class OTAService
{ {
private readonly OTAClient _otaClient;
private readonly string _appDir; private readonly string _appDir;
private readonly string _criticalBackupDir; private readonly string _criticalBackupDir;
private readonly string _criticalSourceLogPath; private readonly string _criticalSourceLogPath;
@ -16,7 +18,6 @@ public class OTAService
public OTAService(string appDir, string criticalBackupDir, string criticalSourceLogPath, string[] criticalFileExtension, string previousBackupPath, string updatePackagePath) public OTAService(string appDir, string criticalBackupDir, string criticalSourceLogPath, string[] criticalFileExtension, string previousBackupPath, string updatePackagePath)
{ {
_otaClient = new OTAClient();
_appDir = appDir; _appDir = appDir;
_criticalBackupDir = criticalBackupDir; _criticalBackupDir = criticalBackupDir;
_criticalSourceLogPath = criticalSourceLogPath; _criticalSourceLogPath = criticalSourceLogPath;
@ -25,11 +26,73 @@ public class OTAService
_updatePackagePath = updatePackagePath; _updatePackagePath = updatePackagePath;
} }
/// <summary>
/// 订阅OTA更新
/// </summary>
public async Task ListenOTAUpdateEvent()
{
await MessageQueueHelper.Subscribe(Topics.IssuedOTAPackage, HandleUpdateOTAEvent);
}
/// <summary> /// <summary>
/// 更新压缩包 /// 查询OTA更新
/// </summary> /// </summary>
public void Update() /// <param name="request"></param>
public static async Task QueryOTAUpdate()
{
await MessageQueueHelper.Publish(Topics.QueryOTA, null);
}
/// <summary>
/// OTA更新反馈
/// </summary>
/// <param name="resutl"></param>
public async Task OTALicenseUpdateEventFeedback(OTAResultData resutl)
{
await MessageQueueHelper.Publish(Topics.OTAUpgradeFeedback, resutl);
}
/// <summary>
/// 处理OTA更新
/// </summary>
/// <param name="topic"></param>
/// <param name="otaUpdateData"></param>
private async Task HandleUpdateOTAEvent(string topic, OTAUpdateData otaUpdateData)
{
var type = otaUpdateData.Type;
var url = otaUpdateData.Url;
var version = otaUpdateData.Version;
var module = otaUpdateData.Module;
var size = otaUpdateData.Size;
var checksum = otaUpdateData.Checksum;
var name = otaUpdateData.Name;
var description = otaUpdateData.Description;
OTAResultData otaResultData = new OTAResultData();
//下载更新包
await ApiClient.DownloadFileAsync(url, _updatePackagePath);
//校验压缩包
if(!OTAClient.CheckMD5(checksum, _updatePackagePath)) return;
//kill masstransfer
//启动更新
otaResultData.Result = Install() ? (byte)1 : (byte)0;
//restart masstransfer
//更新反馈
otaResultData.OtaSoftwareVersion = version;
otaResultData.CurrentSoftwareVersion = version; //**需要修改为当前版本
await OTALicenseUpdateEventFeedback(otaResultData);
}
/// <summary>
/// 安装压缩包
/// </summary>
public bool Install()
{ {
try try
{ {
@ -37,33 +100,36 @@ public class OTAService
initDir(); initDir();
//备份重要文件 //备份重要文件
_otaClient.BackupEssentialFiles(_appDir, _criticalBackupDir, _criticalFileExtension, _criticalSourceLogPath); OTAClient.BackupEssentialFiles(_appDir, _criticalBackupDir, _criticalFileExtension, _criticalSourceLogPath);
//备份旧版本文件 //备份旧版本文件
_otaClient.CompressDirectory(_appDir, _previousBackupPath); OTAClient.CompressDirectory(_appDir, _previousBackupPath);
try try
{ {
//删除旧版本原文件 //删除旧版本原文件
_otaClient.DeleteDirectory(_appDir); OTAClient.DeleteDirectory(_appDir);
//解压更新包 //解压更新包
_otaClient.ExtractDirectory(_updatePackagePath, _appDir); OTAClient.ExtractDirectory(_updatePackagePath, _appDir);
//恢复重要文件 //恢复重要文件
_otaClient.RecoverCriticalFiles(_criticalSourceLogPath); OTAClient.RecoverCriticalFiles(_criticalSourceLogPath);
//删除旧版本备份文件 //删除旧版本备份文件
_otaClient.DeleteFile(_previousBackupPath); OTAClient.DeleteFile(_previousBackupPath);
//删除更新包 //删除更新包
_otaClient.DeleteFile(_updatePackagePath); OTAClient.DeleteFile(_updatePackagePath);
return true;
} }
catch (Exception ex) catch (Exception ex)
{ {
RollBack(); RollBack();
Console.WriteLine($"更新异常,已回滚: {ex.Message}"); Console.WriteLine($"更新异常,已回滚: {ex.Message}");
return false;
} }
} }
catch (Exception ex) catch (Exception ex)
@ -73,8 +139,10 @@ public class OTAService
//如果重要文件备份已经产生,则删除 //如果重要文件备份已经产生,则删除
if(Directory.Exists(_criticalBackupDir)) if(Directory.Exists(_criticalBackupDir))
{ {
_otaClient.DeleteDirectory(_criticalBackupDir); OTAClient.DeleteDirectory(_criticalBackupDir);
} }
return false;
} }
} }
@ -104,7 +172,7 @@ public class OTAService
{ {
if (Directory.Exists(directory)) if (Directory.Exists(directory))
{ {
_otaClient.DeleteDirectory(directory); OTAClient.DeleteDirectory(directory);
} }
} }
@ -112,15 +180,15 @@ public class OTAService
{ {
if (File.Exists(file)) if (File.Exists(file))
{ {
_otaClient.DeleteFile(file); OTAClient.DeleteFile(file);
} }
} }
//恢复旧版本文件 //恢复旧版本文件
_otaClient.ExtractDirectory(_previousBackupPath, _appDir); OTAClient.ExtractDirectory(_previousBackupPath, _appDir);
//删除旧版本备份 //删除旧版本备份
_otaClient.DeleteFile(_previousBackupPath); OTAClient.DeleteFile(_previousBackupPath);
} }
} }

View File

@ -13,7 +13,7 @@ using System.Reflection;
[assembly: System.Reflection.AssemblyCompanyAttribute("MasstransferExporter")] [assembly: System.Reflection.AssemblyCompanyAttribute("MasstransferExporter")]
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+a303714a635d3146132582a2408fc8cf76a69947")] [assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+64cf3396835594f835ea904d6fccf95de4bc3e01")]
[assembly: System.Reflection.AssemblyProductAttribute("MasstransferExporter")] [assembly: System.Reflection.AssemblyProductAttribute("MasstransferExporter")]
[assembly: System.Reflection.AssemblyTitleAttribute("MasstransferExporter")] [assembly: System.Reflection.AssemblyTitleAttribute("MasstransferExporter")]
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]

View File

@ -1 +1 @@
78895e0730c7e01dfba29760f86535377f37711dd2d831a492fe0a2d3f652707 afb45cd140781d3740c62e8429421ce27af7c578ce7ca503e1181871f13ddf71

View File

@ -68,6 +68,20 @@ public class ApiClient : IDisposable
return await response.Content.ReadFromJsonAsync<T>(); return await response.Content.ReadFromJsonAsync<T>();
} }
/// <summary>
/// 异步请求下载文件
/// </summary>
/// <param name="fileUrl"></param>
/// <param name="destinationFilePath"></param>
public static async Task DownloadFileAsync(string fileUrl, string destinationFilePath)
{
using var response = await Client.GetAsync(fileUrl);
response.EnsureSuccessStatusCode();
using var fileStream = new FileStream(destinationFilePath, FileMode.Create, FileAccess.Write, FileShare.None);
await response.Content.CopyToAsync(fileStream);
}
public void Dispose() public void Dispose()
{ {
Client.Dispose(); Client.Dispose();

View File

@ -0,0 +1,28 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="coverlet.collector" Version="6.0.0"/>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0"/>
<PackageReference Include="NUnit" Version="3.14.0"/>
<PackageReference Include="NUnit.Analyzers" Version="3.9.0"/>
<PackageReference Include="NUnit3TestAdapter" Version="4.5.0"/>
</ItemGroup>
<ItemGroup>
<Using Include="NUnit.Framework"/>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\MasstransferCommon\MasstransferCommon.csproj" />
</ItemGroup>
</Project>

20
TestProject1/UnitTest1.cs Normal file
View File

@ -0,0 +1,20 @@
using MasstransferCommon.Utils;
namespace TestProject1;
public class Tests
{
private string file_path = @"C:\Users\wangkaiyi\Downloads\JetBrains2023.1.zip";
private string b = "5181b067ead5386800c291b70b2c9456";
[SetUp]
public void Setup()
{
}
[Test]
public void Test1()
{
var a = Md5Util.Md5ForZipFile(file_path);
Console.WriteLine(a);
}
}