先添加更新程序用于更新IoTNode,完成后再在IoTNode中添加手动调用的更新"更新程序"的方法

更新"更新程序"时,确保IoTNode的版本和服务端上iotnode.xml里的版本号是一致的,这样可以避免冲突;开始检测更新时就关闭更新程序,更新结束后再启动


Former-commit-id: 67d6137cc0ac6b1a46f4b72201daf8b5e84e8c41
Former-commit-id: 7c752e3a9b1cd1775d43acd8e1dc17ee356b3afa
TSXN
wanggang 5 years ago
parent 6fb2dc5a6e
commit 3b7924d122

@ -1,5 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<app>
<version>1.0.0.20082401</version>
<checksum></checksum>
</app>

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8" ?>
<app>
<version>1.0.0.20082501</version>
<checksum>b67172948390b8594382cec333498b0905bbdf0fa70f32c3882d7dbc07d745ed899be55bf90f460d63caf12d3924d7384bb0722a264f7b2184e167b1b63397c0</checksum>
</app>

@ -1,43 +1,13 @@
using CookComputing.XmlRpc; using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc;
using System.Net;
using System.Net.Http;
using System.Reflection; using System.Reflection;
namespace IoTDameon.Controllers namespace IoTDameon.Controllers
{ {
public class HomeController : Controller public class HomeController : Controller
{ {
private IHttpClientFactory _httpClientFactory;
public HomeController(IHttpClientFactory httpClientFactory)
{
_httpClientFactory = httpClientFactory;
}
public IActionResult Index() public IActionResult Index()
{ {
this.Process(); return GetVersion();
return Content("");
}
private void Process(bool stop = false)
{
try
{
var proxy = XmlRpcProxyGen.Create<ISupervisorService>();
proxy.Url = "http://192.168.1.3:9001/RPC2";
proxy.Credentials = new NetworkCredential("usr", "pwd");
var result = stop ? proxy.stopProcess("iotnode") : proxy.startProcess("iotnode");
}
catch (XmlRpcFaultException ex)
{
//start:60 stop:70
if (ex.FaultCode != 60 && ex.FaultCode != 70)
{
throw ex;
}
}
} }
public IActionResult GetVersion() public IActionResult GetVersion()

@ -1,19 +0,0 @@
using CookComputing.XmlRpc;
namespace IoTDameon.Controllers
{
public interface ISupervisorService : IXmlRpcProxy
{
[XmlRpcMethod("supervisor.getAllProcessInfo")]
XmlRpcStruct getAllProcessInfo();
[XmlRpcMethod("supervisor.getProcessInfo")]//result["statename"]: "RUNNING" or "STOPPED"
XmlRpcStruct getProcessInfo(string name);
[XmlRpcMethod("supervisor.startProcess")]
bool startProcess(string name);
[XmlRpcMethod("supervisor.stopProcess")]
bool stopProcess(string name);
}
}

@ -1,6 +1,6 @@
using CookComputing.XmlRpc; using CookComputing.XmlRpc;
namespace IoTNode.Services namespace IoTDameon
{ {
public interface ISupervisorService : IXmlRpcProxy public interface ISupervisorService : IXmlRpcProxy
{ {

@ -25,7 +25,7 @@ namespace IoTDameon
builder.SetIsOriginAllowed(o => true).AllowAnyMethod().AllowAnyHeader().AllowCredentials(); builder.SetIsOriginAllowed(o => true).AllowAnyMethod().AllowAnyHeader().AllowCredentials();
}) })
); );
services.AddHostedService<UpdateIoTNodeService>();
services.AddHttpClient(); services.AddHttpClient();
services.AddControllersWithViews(); services.AddControllersWithViews();

@ -15,17 +15,18 @@ using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Xml; using System.Xml;
namespace IoTNode.Services namespace IoTDameon
{ {
public class UpdateDameonService : BackgroundService public class UpdateIoTNodeService : BackgroundService
{ {
private readonly ILogger<UpdateDameonService> _logger; private readonly ILogger<UpdateIoTNodeService> _logger;
private readonly IWebHostEnvironment _env; private readonly IWebHostEnvironment _env;
private readonly IConfiguration _cfg; private readonly IConfiguration _cfg;
private readonly IHttpClientFactory _httpClientFactory; private readonly IHttpClientFactory _httpClientFactory;
private bool _isUpdating;
public UpdateDameonService(ILogger<UpdateDameonService> logger, IWebHostEnvironment env, IConfiguration cfg, IHttpClientFactory httpClientFactory) public bool IsUpdating { get; set; }
public UpdateIoTNodeService(ILogger<UpdateIoTNodeService> logger, IWebHostEnvironment env, IConfiguration cfg, IHttpClientFactory httpClientFactory)
{ {
this._logger = logger; this._logger = logger;
this._env = env; this._env = env;
@ -47,13 +48,13 @@ namespace IoTNode.Services
private void Update() private void Update()
{ {
if (this._isUpdating) if (this.IsUpdating)
{ {
return; return;
} }
else else
{ {
this._isUpdating = true; this.IsUpdating = true;
} }
try try
{ {
@ -63,23 +64,26 @@ namespace IoTNode.Services
{ {
this._logger.LogError(ex, "update error"); this._logger.LogError(ex, "update error");
} }
this._isUpdating = false; this.IsUpdating = false;
} }
private void UpdateInternal() private void UpdateInternal()
{ {
var processName = "iotnode";
var appFolder = "IoTNode";
var port = 8002;
var proxyUrl = "http://localhost:9001/RPC2"; var proxyUrl = "http://localhost:9001/RPC2";
var processName = "iotdaemon";
var root = Directory.GetParent(_env.ContentRootPath).FullName; var root = Directory.GetParent(_env.ContentRootPath).FullName;
var appPath = Path.Combine(root, "IoTDameon"); var appPath = Path.Combine(root, appFolder);
var name = "dameon.zip"; var name = $"{appFolder}.zip";
var backupName = Path.Combine(root, "iotdameon.bk.zip"); var backupName = Path.Combine(root, $"{appFolder}.bk.zip");
var file = Path.Combine(root, name); var file = Path.Combine(root, name);
var currentCheckSum = string.Empty; var currentCheckSum = string.Empty;
//检查是否有更新 //检查是否有更新
this._logger.LogInformation("check dameon version"); this._logger.LogInformation("check version");
var currentVersion = this._httpClientFactory.CreateClient().GetAsync("http://localhost:8003/Home/GetVersion").Result.Content.ReadAsStringAsync().Result; var currentVersion = this._httpClientFactory.CreateClient().GetAsync($"http://localhost:{port}/Home/GetVersion").Result.Content.ReadAsStringAsync().Result;
var info = this._httpClientFactory.CreateClient().GetAsync($"{this._cfg["notify:host"]}/dameon.xml").Result.Content.ReadAsStringAsync().Result; var server = this._httpClientFactory.CreateClient().GetAsync($"http://localhost:{port}/Home/GetServer").Result.Content.ReadAsStringAsync().Result;
var info = this._httpClientFactory.CreateClient().GetAsync($"{server}/{processName}.xml").Result.Content.ReadAsStringAsync().Result;
var doc = new XmlDocument(); var doc = new XmlDocument();
doc.LoadXml(info); doc.LoadXml(info);
var lastVersion = doc.GetElementsByTagName("version")[0].InnerText.Trim(); var lastVersion = doc.GetElementsByTagName("version")[0].InnerText.Trim();
@ -131,15 +135,14 @@ namespace IoTNode.Services
try try
{ {
ZipFile.CreateFromDirectory(appPath, backupName); ZipFile.CreateFromDirectory(appPath, backupName);
Directory.Delete(appPath, true);
Directory.CreateDirectory(appPath);
} }
catch (Exception ex) catch (Exception ex)
{ {
this._logger.LogError(ex, ex.Message); this._logger.LogError(ex, ex.Message);
throw new Exception("备份程序失败", ex); throw new Exception("备份程序失败", ex);
} }
Directory.Delete(appPath, true);
Directory.CreateDirectory(appPath);
//更新程序 //更新程序
try try
{ {
@ -154,7 +157,9 @@ namespace IoTNode.Services
//设置权限 //设置权限
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{ {
Process.Start("/bin/bash", $"-c \"chmod 755 {Path.Combine(appPath, "IoTDameon")}\""); var updateScript = Path.Combine(appPath, "update.sh");
Process.Start("/bin/bash", $"-c \"chmod 755 {file}\"");
Process.Start(updateScript);
} }
//启动更新程序 //启动更新程序
proxy.startProcess(processName); proxy.startProcess(processName);

@ -1,24 +1,27 @@
using Application.Domain.Entities; using Application.Domain.Entities;
using Infrastructure.Application.Services.Settings;
using Infrastructure.Data; using Infrastructure.Data;
using Infrastructure.Web; using Infrastructure.Web;
using IoT.Shared.Services; using IoT.Shared.Services;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using System;
using System.Linq; using System.Linq;
using System.Reflection;
namespace IoTNode.Controllers namespace IoTNode.Controllers
{ {
//[Device] //[Device]
public class HomeController : BaseController public class HomeController : BaseController
{ {
private readonly ISettingService _settingService;
private readonly IRepository<Node> _nodeRepo; private readonly IRepository<Node> _nodeRepo;
private readonly IRepository<Scene> _sceneRepo; private readonly IRepository<Scene> _sceneRepo;
private readonly IoTNodeClient _ioTNodeClient; private readonly IoTNodeClient _ioTNodeClient;
public HomeController(IRepository<Node> nodeRepo, IRepository<Scene> sceneRepo,IoTNodeClient ioTNodeClient) public HomeController(ISettingService settingService, IRepository<Node> nodeRepo, IRepository<Scene> sceneRepo, IoTNodeClient ioTNodeClient)
{ {
this._settingService = settingService;
this._nodeRepo = nodeRepo; this._nodeRepo = nodeRepo;
this._sceneRepo = sceneRepo; this._sceneRepo = sceneRepo;
this._ioTNodeClient = ioTNodeClient; this._ioTNodeClient = ioTNodeClient;
@ -36,8 +39,8 @@ namespace IoTNode.Controllers
var model = this._sceneRepo.ReadOnlyTable() var model = this._sceneRepo.ReadOnlyTable()
.Include(o => o.SceneTimers) .Include(o => o.SceneTimers)
.Include(o => o.SceneTiggers) .Include(o => o.SceneTiggers)
.Include(o => o.SceneCommands).ThenInclude(o=>o.Command).ThenInclude(o=>o.Device) .Include(o => o.SceneCommands).ThenInclude(o => o.Command).ThenInclude(o => o.Device)
.Include(o=>o.SceneCommands).ThenInclude(o=>o.Command).ThenInclude(o=>o.Api) .Include(o => o.SceneCommands).ThenInclude(o => o.Command).ThenInclude(o => o.Api)
.ToList(); .ToList();
return View(model); return View(model);
} }
@ -47,5 +50,15 @@ namespace IoTNode.Controllers
this._ioTNodeClient.OnConnected(); this._ioTNodeClient.OnConnected();
return RedirectTo(); return RedirectTo();
} }
public IActionResult GetVersion()
{
return Content(Assembly.GetEntryAssembly().GetCustomAttribute<AssemblyInformationalVersionAttribute>().InformationalVersion);
}
public IActionResult GetServer()
{
return Content(this._settingService.GetSetting("notify:host").Value?.Trim());
}
} }
} }
Loading…
Cancel
Save