Compare commits
2 Commits
fd52e9c843
...
7ef948ae48
Author | SHA1 | Date |
---|---|---|
wangkaiyi | 7ef948ae48 | |
wangkaiyi | b692f8e41c |
|
@ -120,4 +120,9 @@ public static class Topics
|
||||||
/// 上行系统状态信息
|
/// 上行系统状态信息
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const string ReportSystemStat = $"up/{SN}/601/{Version}";
|
public const string ReportSystemStat = $"up/{SN}/601/{Version}";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 上行系统版本信息
|
||||||
|
/// </summary>
|
||||||
|
public const string ReportSystemVersion = $"up/{SN}/602/{Version}";
|
||||||
}
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
using System.ComponentModel;
|
||||||
|
using SQLite;
|
||||||
|
|
||||||
|
namespace MasstransferCommon.Model.Entity;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 路径参数
|
||||||
|
/// </summary>
|
||||||
|
[Table("path_params"), Description("文件路径参数")]
|
||||||
|
public class PathParams : Entity
|
||||||
|
{
|
||||||
|
[Column("AppDir"), Description("应用程序路径")]
|
||||||
|
public string AppDir { get; set; }
|
||||||
|
|
||||||
|
[Column("AssemblyPath"), Description("程序集路径")]
|
||||||
|
public string AssemblyPath { get; set; }
|
||||||
|
|
||||||
|
[Column("CriticalBackupDir"), Description("重要文件备份目录地址")]
|
||||||
|
public string CriticalBackupDir { get; set; }
|
||||||
|
|
||||||
|
[Column("CriticalFileExtension"), Description("重要文件后缀")]
|
||||||
|
public string[] CriticalFileExtension { get; set; }
|
||||||
|
|
||||||
|
[Column("CriticalSourceLogPath"), Description("重要文件备份记录文件地址")]
|
||||||
|
public string CriticalSourceLogPath { get; set; }
|
||||||
|
|
||||||
|
[Column("PreviousBackupPath"), Description("原应用程序备份目录地址")]
|
||||||
|
public string PreviousBackupPath { get; set; }
|
||||||
|
|
||||||
|
[Column("UpdatePackagePath"), Description("更新包下载地址")]
|
||||||
|
public string UpdatePackagePath { get; set; }
|
||||||
|
}
|
|
@ -1,4 +1,5 @@
|
||||||
using System.IO.Compression;
|
using System.Diagnostics;
|
||||||
|
using System.IO.Compression;
|
||||||
using MasstransferCommon.Utils;
|
using MasstransferCommon.Utils;
|
||||||
|
|
||||||
|
|
||||||
|
@ -6,6 +7,10 @@ namespace MasstransferExporter.OTA.Client;
|
||||||
|
|
||||||
public class OTAClient
|
public class OTAClient
|
||||||
{
|
{
|
||||||
|
private const string ProcessName = "Masstransfer";
|
||||||
|
|
||||||
|
private const string KeyPath = @""; //待指定
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 备份保存重要文件
|
/// 备份保存重要文件
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -168,9 +173,69 @@ public class OTAClient
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
return false;
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
public static bool ExecuteSetup(string packagePath, string appDir)
|
||||||
|
{
|
||||||
|
ProcessStartInfo startInfo = new ProcessStartInfo
|
||||||
|
{
|
||||||
|
FileName = packagePath,
|
||||||
|
Arguments = "/quiet", // 根据需要添加安装程序的命令行参数
|
||||||
|
UseShellExecute = false,
|
||||||
|
RedirectStandardOutput = true,
|
||||||
|
RedirectStandardError = true,
|
||||||
|
CreateNoWindow = true // 如果不想显示安装过程窗口
|
||||||
|
};
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 启动安装程序
|
||||||
|
using (Process process = Process.Start(startInfo))
|
||||||
|
{
|
||||||
|
if (process != null)
|
||||||
|
{
|
||||||
|
// 等待安装程序执行完成
|
||||||
|
process.WaitForExit();
|
||||||
|
|
||||||
|
// 检查返回值,通常0表示成功
|
||||||
|
if (process.ExitCode == 0)
|
||||||
|
{
|
||||||
|
Console.WriteLine("安装成功!");
|
||||||
|
// 在安装成功后执行后续操作
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.WriteLine($"安装失败,退出代码: {process.ExitCode}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"执行安装时发生错误: {ex.Message}");
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void startMasstransfer()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
//从注册表获取进程路径
|
||||||
|
if (RegistryHelper.ReadValue(KeyPath, "ExporterPath") is string path)
|
||||||
|
{
|
||||||
|
Process.Start(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Console.WriteLine(e);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -2,11 +2,11 @@
|
||||||
|
|
||||||
public class OTAResultData
|
public class OTAResultData
|
||||||
{
|
{
|
||||||
public byte Result { get; set; }
|
public byte result { get; set; }
|
||||||
|
|
||||||
public string Msg { get; set; }
|
public string msg { get; set; }
|
||||||
|
|
||||||
public string OtaSoftwareVersion { get; set; }
|
public string otaSoftwareVersion { get; set; }
|
||||||
|
|
||||||
public string CurrentSoftwareVersion { get; set; }
|
public string currentSoftwareVersion { get; set; }
|
||||||
}
|
}
|
|
@ -1,16 +0,0 @@
|
||||||
namespace MasstransferExporter.OTA.Model;
|
|
||||||
|
|
||||||
public class OTAUpdateFileManager
|
|
||||||
{
|
|
||||||
public string UpdatePackagePath;
|
|
||||||
|
|
||||||
public string AppDir;
|
|
||||||
|
|
||||||
public string CriticalBackupDir;
|
|
||||||
|
|
||||||
public string[] CriticalFileExtension;
|
|
||||||
|
|
||||||
public string CriticalSourceLogPath;
|
|
||||||
|
|
||||||
public string PreviousBackupPath;
|
|
||||||
}
|
|
|
@ -1,26 +1,43 @@
|
||||||
using MasstransferCommon.Atrributes;
|
using MasstransferCommon.Atrributes;
|
||||||
using MasstransferCommon.Events;
|
using MasstransferCommon.Events;
|
||||||
using MasstransferCommon.Model.Constant;
|
using MasstransferCommon.Model.Constant;
|
||||||
using MasstransferCommon.Utils;
|
using MasstransferCommon.Model.Entity;
|
||||||
|
using MasstransferCommunicate.Minio;
|
||||||
using MasstransferCommunicate.Mqtt.Client;
|
using MasstransferCommunicate.Mqtt.Client;
|
||||||
using MasstransferCommunicate.Process.Client;
|
using MasstransferCommunicate.Process.Client;
|
||||||
using MasstransferExporter.OTA.Client;
|
using MasstransferExporter.OTA.Client;
|
||||||
using MasstransferExporter.OTA.Model;
|
using MasstransferExporter.OTA.Model;
|
||||||
|
using MasstransferExporter.StatExporter;
|
||||||
using MasstransferInfrastructure.Database.Sqlite;
|
using MasstransferInfrastructure.Database.Sqlite;
|
||||||
|
|
||||||
namespace MasstransferExporter.OTA.Service;
|
namespace MasstransferExporter.OTA.Service;
|
||||||
|
|
||||||
public class OTAService : Instant
|
public class OTAService : Instant
|
||||||
{
|
{
|
||||||
private static readonly SqliteHelper Db = SqliteHelper.GetInstance();
|
private static readonly SqliteHelper _sqliteHelper = SqliteHelper.GetInstance();
|
||||||
private static OTAUpdateFileManager _otaUpdateFileManager;
|
private static readonly MinioHelper Minio = MinioHelper.GetInstance();
|
||||||
|
|
||||||
|
private static PathParams _filePath;
|
||||||
|
public static PathParams FilePath
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_filePath == null)
|
||||||
|
{
|
||||||
|
_filePath = _sqliteHelper.Query<PathParams>("select * from path_params limit 1").FirstOrDefault();
|
||||||
|
if (_filePath == null)
|
||||||
|
{
|
||||||
|
throw new Exception("无法从数据库中获取路径参数");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return _filePath;
|
||||||
|
}
|
||||||
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 启动OTA服务
|
/// 启动OTA服务
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private static async Task StartOTAService(EventType type, bool start)
|
private static async Task StartOTAService(EventType type, bool start)
|
||||||
{
|
{
|
||||||
_otaUpdateFileManager = GetOTAUpdateFileManager();
|
|
||||||
|
|
||||||
//订阅云端发包
|
//订阅云端发包
|
||||||
await MessageQueueHelper.Subscribe(Topics.IssuedOTAPackage, HandleIssuedOTAPackage);
|
await MessageQueueHelper.Subscribe(Topics.IssuedOTAPackage, HandleIssuedOTAPackage);
|
||||||
|
@ -36,22 +53,17 @@ public class OTAService : Instant
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 从数据库读取文件操作地址、关键文件后缀
|
/// 处理云端响应OTA请求事件,通知Masstransfer
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <param name="topic"></param>
|
||||||
private static OTAUpdateFileManager? GetOTAUpdateFileManager()
|
/// <param name="otaUpdateData"></param>
|
||||||
{
|
|
||||||
return Db.Query<OTAUpdateFileManager>("").FirstOrDefault();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void HandleIssuedOTAPackage(string topic, OTAUpdateData otaUpdateData)
|
private static void HandleIssuedOTAPackage(string topic, OTAUpdateData otaUpdateData)
|
||||||
{
|
{
|
||||||
ProcessHelper.Send(ProcessTopics.OTAQueryEventFeedback, otaUpdateData);
|
ProcessHelper.Send(ProcessTopics.OTAQueryEventFeedback, otaUpdateData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Masstransfer 请求OTA事件响应,向云端发送请求信息
|
/// 处理Masstransfer请求OTA事件,向云端发送请求信息
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="topic"></param>
|
/// <param name="topic"></param>
|
||||||
/// <param name="mess"></param>
|
/// <param name="mess"></param>
|
||||||
|
@ -60,43 +72,51 @@ public class OTAService : Instant
|
||||||
await MessageQueueHelper.Publish(Topics.QueryOTA, new object());
|
await MessageQueueHelper.Publish(Topics.QueryOTA, new object());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 处理Masstransfer下载安装包事件,从云端下载安装包
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="topic"></param>
|
||||||
|
/// <param name="data"></param>
|
||||||
public static async Task HandleDownloadUpdatePackageEvent(string topic, (string Url, string Checksum) data)
|
public static async Task HandleDownloadUpdatePackageEvent(string topic, (string Url, string Checksum) data)
|
||||||
{
|
{
|
||||||
var updatePackagePath = _otaUpdateFileManager.UpdatePackagePath;
|
var updatePackagePath = FilePath.UpdatePackagePath;
|
||||||
string url = data.Url;
|
|
||||||
string checksum = data.Checksum;
|
string checksum = data.Checksum;
|
||||||
bool result = false;
|
bool result = false;
|
||||||
|
var filePath = Path.Combine(updatePackagePath, data.Url.Split("/")[1]);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await ApiClient.DownloadFileAsync(url, updatePackagePath);
|
await Minio.DownloadFileAsync("cloud", data.Url, filePath);
|
||||||
if (!OTAClient.CheckMD5(checksum, updatePackagePath)) throw new Exception("MD5 check failed.");
|
if (OTAClient.CheckMD5(checksum, filePath))
|
||||||
result = true;
|
{
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Console.WriteLine(e);
|
Console.WriteLine(e);
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
|
||||||
ProcessHelper.Send(ProcessTopics.DownloadUpdatePackageEventFeedback, result);
|
ProcessHelper.Send(ProcessTopics.DownloadUpdatePackageEventFeedback, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Masstransfer 通知-启动更新
|
/// <summary>
|
||||||
private static async Task HandleOTAUpdateEvent(string topic, OTAUpdateData otaUpdateData)
|
/// 处理Masstransfer启动更新事件
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="topic"></param>
|
||||||
|
/// <param name="mess"></param>
|
||||||
|
private static async Task HandleOTAUpdateEvent(string topic, string mess)
|
||||||
{
|
{
|
||||||
var version = "";
|
|
||||||
|
|
||||||
var otaResultData = new OTAResultData
|
var otaResultData = new OTAResultData
|
||||||
{
|
{
|
||||||
//启动更新
|
//启动更新
|
||||||
Result = Install() ? (byte)1 : (byte)0,
|
result = Install() ? (byte)1 : (byte)0,
|
||||||
//restart masstransfer
|
otaSoftwareVersion = mess,
|
||||||
//更新反馈
|
currentSoftwareVersion = SystemVersionExporter.GetSoftwreVersion()
|
||||||
OtaSoftwareVersion = version,
|
|
||||||
CurrentSoftwareVersion = version //**需要修改为当前版本
|
|
||||||
};
|
};
|
||||||
|
|
||||||
await MessageQueueHelper.Publish(Topics.OTAUpgradeFeedback, otaResultData);
|
await MessageQueueHelper.Publish(Topics.OTAUpgradeFeedback, otaResultData);
|
||||||
|
|
||||||
|
//启动masstransfer
|
||||||
|
OTAClient.startMasstransfer();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -104,12 +124,13 @@ public class OTAService : Instant
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private static bool Install()
|
private static bool Install()
|
||||||
{
|
{
|
||||||
var appDir = _otaUpdateFileManager.AppDir;
|
var appDir = FilePath.AppDir;
|
||||||
var criticalBackupDir = _otaUpdateFileManager.CriticalBackupDir;
|
var criticalBackupDir = FilePath.CriticalBackupDir;
|
||||||
var criticalFileExtension = _otaUpdateFileManager.CriticalFileExtension;
|
var criticalFileExtension = FilePath.CriticalFileExtension;
|
||||||
var criticalSourceLogPath = _otaUpdateFileManager.CriticalSourceLogPath;
|
var criticalSourceLogPath = FilePath.CriticalSourceLogPath;
|
||||||
var previousBackupPath = _otaUpdateFileManager.PreviousBackupPath;
|
var previousBackupPath = FilePath.PreviousBackupPath;
|
||||||
var updatePackagePath = _otaUpdateFileManager.UpdatePackagePath;
|
var updatePackagePath = FilePath.UpdatePackagePath;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
//初始化
|
//初始化
|
||||||
|
@ -126,8 +147,8 @@ public class OTAService : Instant
|
||||||
//删除旧版本原文件
|
//删除旧版本原文件
|
||||||
OTAClient.DeleteDirectory(appDir);
|
OTAClient.DeleteDirectory(appDir);
|
||||||
|
|
||||||
//解压更新包
|
//安装更新包
|
||||||
OTAClient.ExtractDirectory(updatePackagePath, appDir);
|
OTAClient.ExecuteSetup(updatePackagePath, appDir);
|
||||||
|
|
||||||
//恢复重要文件
|
//恢复重要文件
|
||||||
OTAClient.RecoverCriticalFiles(criticalSourceLogPath);
|
OTAClient.RecoverCriticalFiles(criticalSourceLogPath);
|
||||||
|
@ -170,7 +191,6 @@ public class OTAService : Instant
|
||||||
{
|
{
|
||||||
Directory.Delete(criticalBackupDir, true);
|
Directory.Delete(criticalBackupDir, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
Directory.CreateDirectory(criticalBackupDir);
|
Directory.CreateDirectory(criticalBackupDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -205,6 +225,9 @@ public class OTAService : Instant
|
||||||
|
|
||||||
//删除旧版本备份
|
//删除旧版本备份
|
||||||
OTAClient.DeleteFile(previousBackupPath);
|
OTAClient.DeleteFile(previousBackupPath);
|
||||||
|
|
||||||
|
//启动masstransfer
|
||||||
|
OTAClient.startMasstransfer();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Initialized()
|
public void Initialized()
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
using MasstransferCommon.Events;
|
using MasstransferCommon.Events;
|
||||||
using MasstransferCommon.Scheduler;
|
using MasstransferCommon.Scheduler;
|
||||||
using MasstransferCommunicate.Mqtt.Client;
|
using MasstransferCommunicate.Mqtt.Client;
|
||||||
|
using MasstransferCommunicate.Process.Client;
|
||||||
using MasstransferExporter.DataExporter;
|
using MasstransferExporter.DataExporter;
|
||||||
using MasstransferExporter.Init;
|
using MasstransferExporter.Init;
|
||||||
using MasstransferExporter.StatExporter;
|
using MasstransferExporter.StatExporter;
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
namespace MasstransferExporter.StatExporter.Model;
|
||||||
|
|
||||||
|
public class SystemVersion
|
||||||
|
{
|
||||||
|
public string softwareVersion { get; set; }
|
||||||
|
|
||||||
|
public string hardwareVersion { get; set; }
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
using System.Runtime.Loader;
|
||||||
|
using MasstransferCommon.Model.Constant;
|
||||||
|
using MasstransferCommon.Model.Entity;
|
||||||
|
using MasstransferCommunicate.Mqtt.Client;
|
||||||
|
using MasstransferExporter.StatExporter.Model;
|
||||||
|
using MasstransferInfrastructure.Database.Sqlite;
|
||||||
|
|
||||||
|
|
||||||
|
namespace MasstransferExporter.StatExporter;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 系统版本统计信息
|
||||||
|
/// 定时触发,1d 一次
|
||||||
|
/// </summary>
|
||||||
|
public class SystemVersionExporter
|
||||||
|
{
|
||||||
|
private static SqliteHelper _sqliteHelper = SqliteHelper.GetInstance();
|
||||||
|
public static async Task StartVersionExport()
|
||||||
|
{
|
||||||
|
var version = new SystemVersion
|
||||||
|
{
|
||||||
|
softwareVersion = GetSoftwreVersion(),
|
||||||
|
hardwareVersion = "1.0.0",
|
||||||
|
};
|
||||||
|
await MessageQueueHelper.Publish(Topics.ReportSystemVersion, version);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GetSoftwreVersion()
|
||||||
|
{
|
||||||
|
var filePath = _sqliteHelper.Query<PathParams>("select * from path_params limit 1").FirstOrDefault();
|
||||||
|
// 使用 AssemblyLoadContext 动态加载程序集
|
||||||
|
var assembly = AssemblyLoadContext.Default.LoadFromAssemblyPath(filePath.AssemblyPath);
|
||||||
|
|
||||||
|
// 获取程序集的 AssemblyName 对象
|
||||||
|
var assemblyName = assembly.GetName();
|
||||||
|
return assemblyName.Version.ToString();
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue