IoTCenter 1.0.0.3

合并JobServer到IoTCenter


Former-commit-id: d6188984c1259527232d064e87ee9e9cd72557b1
Former-commit-id: 8af62e24c99b6625b3acbcedc83eed6af1aef870
TSXN
wanggang 5 years ago
parent 3b71fa0607
commit 8114c4a9f2

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
https://go.microsoft.com/fwlink/?LinkID=208121.
-->
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration>Release</Configuration>
<Platform>Any CPU</Platform>
<PublishDir>bin\Release\net5.0\publish\</PublishDir>
<PublishProtocol>FileSystem</PublishProtocol>
<TargetFramework>net5.0</TargetFramework>
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
<SelfContained>true</SelfContained>
<PublishSingleFile>True</PublishSingleFile>
<PublishReadyToRun>False</PublishReadyToRun>
<PublishTrimmed>False</PublishTrimmed>
</PropertyGroup>
</Project>

@ -48,27 +48,6 @@ namespace IoT.Shared
modelBuilder.Entity<SceneTimer>().HasOne(o => o.Scene).WithMany(o => o.SceneTimers).HasForeignKey(o => o.SceneId);
modelBuilder.Entity<SceneTigger>().HasOne(o => o.Scene).WithMany(o => o.SceneTiggers).HasForeignKey(o => o.SceneId);
modelBuilder.Entity<SceneTigger>().HasOne(o => o.Data).WithMany(o => o.Tiggers).HasForeignKey(o => o.DataId);
//
modelBuilder.Ignore<NodeCategory>();
modelBuilder.Ignore<NodeCategoryNode>();
modelBuilder.Ignore<NodeCategoryNode>();
modelBuilder.Ignore<NodeCategoryNode>();
modelBuilder.Ignore<Organ>();
modelBuilder.Ignore<Organ>();
modelBuilder.Ignore<OrganUser>();
modelBuilder.Ignore<OrganUser>();
modelBuilder.Ignore<OrganUser>();
modelBuilder.Ignore<OrganNode>();
modelBuilder.Ignore<OrganNode>();
modelBuilder.Ignore<OrganNode>();
modelBuilder.Ignore<OrganNode>();
;
modelBuilder.Ignore<OrganScene>();
modelBuilder.Ignore<OrganSceneCommand>();
modelBuilder.Ignore<OrganSceneCommand>();
modelBuilder.Ignore<OrganSceneTimer>();
modelBuilder.Ignore<OrganSceneTigger>();
modelBuilder.Ignore<OrganSceneTigger>();
}
public static void Seed(DbContext db)

@ -1,11 +1,15 @@
using Application.Domain.Entities;
using Application.Models;
using Hangfire;
using Hangfire.Storage;
using Infrastructure.Application.Services.Settings;
using Infrastructure.Data;
using Infrastructure.Extensions;
using IoTCenter.Services;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.SignalR;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using System;
using System.ComponentModel.DataAnnotations;
@ -19,18 +23,19 @@ namespace IoTCenter.Api.Controllers
[ApiController]
public class ApiController : ControllerBase
{
private readonly IConfiguration _cfg;
private readonly ISettingService _settingService;
private readonly ILogger<ApiController> _logger;
private readonly IRepository<Scene> _sceneRepo;
private readonly IRepository<SceneCommand> _sceneCommandRepo;
private readonly IRepository<OrganScene> _organSceneRepo;
private readonly IRepository<OrganSceneCommand> _organSceneCommandRepo;
private readonly IRepository<OrganSceneTimer> _sceneTimerRepo;
private readonly IRepository<OrganSceneTimer> _organSceneTimerRepo;
private readonly IRepository<Command> _commandRepo;
private readonly IRepository<Device> _deviceRepo;
private readonly IHubContext<IoTCenterHub> _hub;
public ApiController(
public ApiController(IConfiguration cfg,
ISettingService settingService,
ILogger<ApiController> logger,
IRepository<Scene> sceneRepo,
@ -42,12 +47,13 @@ namespace IoTCenter.Api.Controllers
IRepository<Device> deviceRepo,
IHubContext<IoTCenterHub> hub)
{
this._cfg = cfg;
this._settingService = settingService;
this._logger = logger;
this._sceneRepo = sceneRepo;
this._organSceneRepo = organSceneRepo;
this._organSceneCommandRepo = organSceneCommandRepo;
this._sceneTimerRepo = sceneTimerRepo;
this._organSceneTimerRepo = sceneTimerRepo;
this._sceneCommandRepo = sceneCommandRepo;
this._commandRepo = commandRepo;
this._deviceRepo = deviceRepo;
@ -162,47 +168,35 @@ namespace IoTCenter.Api.Controllers
}
}
/// <summary>
/// job server call back
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
[HttpPost]
[Route("{id}")]
public ActionResult ExecTimer([Required(ErrorMessage = nameof(RequiredAttribute))] Guid id)
public IActionResult UpdateTimer()
{
try
using var conn = JobStorage.Current.GetConnection();
var jobs = conn.GetRecurringJobs();
foreach (var job in jobs)
{
RecurringJob.RemoveIfExists(job.Id);
}
var timers = this._organSceneTimerRepo.ReadOnlyTable().ToList();
foreach (var timer in timers)
{
this._logger.LogDebug($"global timer exec:{id}");
var timer = this._sceneTimerRepo.ReadOnlyTable()
.Include(o => o.OrganScene).ThenInclude(o => o.OrganSceneCommands).ThenInclude(o => o.Command).ThenInclude(o => o.Device).ThenInclude(o => o.Node)
.FirstOrDefault(o => o.Id == id);
if (timer != null)
try
{
foreach (var sceneCommand in timer.OrganScene.OrganSceneCommands.OrderBy(o => o.Command.DisplayOrder))
{
try
{
this._hub.ServerToClient(Methods.ExecCommand, sceneCommand.CommandId, sceneCommand.Command.Device.Node.Number, null);
Delay(sceneCommand.Command.Delay);
}
catch (Exception ex)
{
this._logger.LogError(ex.ToString());
}
}
RecurringJob.AddOrUpdate(timer.Id.ToString(), () => Handle(timer.Id), timer.Cron, TimeZoneInfo.Local);
}
else
catch (Exception ex)
{
this._logger.LogError($"timer {id} does not exist");
ex.PrintStack();
this._logger.LogError(ex.ToString());
}
return Ok();
}
catch (Exception ex)
{
this._logger.LogError(ex.ToString());
return Problem(ex.Message);
}
return Ok();
}
[ApiExplorerSettings(IgnoreApi = true)]
public void Handle(Guid id)
{
IoTCenterEventHandler.GlobalTimerExec(_logger, _settingService, _organSceneTimerRepo, _hub, id);
}
private void CallApi(string connectionId, string number, string method, string query)

@ -43,6 +43,7 @@ namespace IoTCenter.Api.Controllers
o.Product.Id,
o.Product.Name,
o.Product.Number,
o.Product.Image,
o.Product.DisplayOrder
})
.Select(o => new
@ -50,6 +51,7 @@ namespace IoTCenter.Api.Controllers
o.Key.Id,
o.Key.Name,
o.Key.Number,
o.Key.Image,
o.Key.DisplayOrder,
Count = o.Count()
})

@ -1,18 +1,14 @@
using Application.Domain.Entities;
using Hangfire;
using Hangfire.Storage;
using Infrastructure.Application.Services.Settings;
using Infrastructure.Data;
using Infrastructure.Extensions;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text;
namespace IoTCenter.Api.Controllers
{
@ -85,50 +81,5 @@ namespace IoTCenter.Api.Controllers
return Problem(ex.Message);
}
}
[HttpPost]
public IActionResult UpdateTimer()
{
using var conn = JobStorage.Current.GetConnection();
var jobs = conn.GetRecurringJobs();
foreach (var job in jobs)
{
RecurringJob.RemoveIfExists(job.Id);
}
var timers = this._organSceneTimerRepo.ReadOnlyTable().ToList();
foreach (var timer in timers)
{
var url = _cfg.GetConnectionString("JobServer") + $"/RecurringJob/AddOrUpdate";
var data = new
{
timer.Id,
url = $"{_cfg.GetConnectionString("JobCallBack")}/{timer.Id}",
cron = timer.Cron
};
try
{
this._logger.LogDebug($"update job server");
var client = _httpClientFactory.CreateClient();
using var content = new StringContent(JsonConvert.SerializeObject(data), Encoding.UTF8, "application/json");
var result = client.PostAsync(url, content).Result;
this._logger.LogDebug($"{result.StatusCode}:{result.Content.ReadAsStringAsync().Result}");
}
catch (Exception ex)
{
ex.PrintStack();
this._logger.LogError(ex.ToString());
}
}
return Ok();
}
private void RemoveJobs()
{
var client = _httpClientFactory.CreateClient();
var url = _cfg.GetConnectionString("JobServer") + $"/RecurringJob/RemoveAll";
using var content = new StringContent("", Encoding.UTF8, "application/json");
var result = client.PostAsync(url, content).Result;
this._logger.LogDebug($"{result.StatusCode}:{result.Content.ReadAsStringAsync().Result}");
}
}
}

@ -4,7 +4,7 @@
<SatelliteResourceLanguages>Zh-CN</SatelliteResourceLanguages>
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
<GenerateAssemblyProductAttribute>true</GenerateAssemblyProductAttribute>
<Version>1.0.0.2</Version>
<Version>1.0.0.3</Version>
<DockerComposeProjectPath>..\docker-compose.dcproj</DockerComposeProjectPath>
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
</PropertyGroup>

@ -1,5 +1,6 @@
using Application.Domain.Entities;
using Application.Models;
using Hangfire;
using Infrastructure.Application.Services.Settings;
using Infrastructure.Data;
using Infrastructure.Events;
@ -11,12 +12,10 @@ using Microsoft.AspNetCore.SignalR;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Vibrant.InfluxDB.Client;
@ -62,6 +61,7 @@ namespace IoTCenter.Services
private readonly IRepository<Organ> _organRepo;
private readonly IRepository<OrganNode> _organNodeRepo;
private readonly IRepository<Device> _deviceRepo;
private readonly IRepository<OrganSceneTimer> _organSceneTimerRepo;
private readonly IRepository<OrganSceneTigger> _sceneTiggerRepo;
private readonly ISceneTiggerService _sceneTiggerService;
private readonly IHubContext<IoTCenterHub> _hub;
@ -76,6 +76,7 @@ namespace IoTCenter.Services
IRepository<Organ> organRepo,
IRepository<OrganNode> organNodeRepo,
IRepository<Device> deviceRepo,
IRepository<OrganSceneTimer> organSceneTimerRepo,
IRepository<OrganSceneTigger> sceneTiggerRepo,
ISceneTiggerService sceneTiggerService,
IHubContext<IoTCenterHub> hub,
@ -90,6 +91,7 @@ namespace IoTCenter.Services
this._organRepo = organRepo;
this._organNodeRepo = organNodeRepo;
this._deviceRepo = deviceRepo;
this._organSceneTimerRepo = organSceneTimerRepo;
this._sceneTiggerRepo = sceneTiggerRepo;
this._sceneTiggerService = sceneTiggerService;
this._hub = hub;
@ -101,34 +103,19 @@ namespace IoTCenter.Services
public void Handle(EntityInsertedEvent<OrganSceneTimer> message)
{
var timer = message.Data;
var url = _cfg.GetConnectionString("JobServer") + "/RecurringJob/AddOrUpdate";
var id = timer.Id.ToString();
this.UpdateJobServer(url, new
{
id,
url = $"{_cfg.GetConnectionString("JobCallBack")}/{id}",
cron = timer.Cron
});
RecurringJob.AddOrUpdate(timer.Id.ToString(), () => Handle(timer.Id), timer.Cron, TimeZoneInfo.Local);
}
public void Handle(EntityUpdatedEvent<OrganSceneTimer> message)
{
var timer = message.Data;
var url = _cfg.GetConnectionString("JobServer") + "/RecurringJob/AddOrUpdate";
var id = timer.Id.ToString();
this.UpdateJobServer(url, new
{
id,
url = $"{_cfg.GetConnectionString("JobCallBack")}/{id}",
cron = timer.Cron
});
RecurringJob.AddOrUpdate(timer.Id.ToString(), () => Handle(timer.Id), timer.Cron, TimeZoneInfo.Local);
}
public void Handle(EntityDeletedEvent<OrganSceneTimer> message)
{
var timer = message.Data;
var url = _cfg.GetConnectionString("JobServer") + $"/RecurringJob/Remove/{timer.Id}";
this.UpdateJobServer(url);
RecurringJob.RemoveIfExists(timer.Id.ToString());
}
#endregion timer
@ -290,23 +277,6 @@ namespace IoTCenter.Services
#endregion Scene
private void UpdateJobServer(string url, object data = null)
{
try
{
this._logger.LogDebug($"update job server");
var client = _httpClientFactory.CreateClient();
using var content = new StringContent(JsonConvert.SerializeObject(data), Encoding.UTF8, "application/json");
var result = client.PostAsync(url, content).Result;
this._logger.LogDebug($"{result.StatusCode}:{result.Content.ReadAsStringAsync().Result}");
}
catch (Exception ex)
{
ex.PrintStack();
this._logger.LogError(ex.ToString());
}
}
private void TiggerHandle(BaseEvent<Data> message)
{
try
@ -366,7 +336,7 @@ namespace IoTCenter.Services
try
{
this._hub.ServerToClient(Methods.ExecCommand, sceneCommand.CommandId, sceneCommand.Command.Device.Node.Number, null);
Delay(sceneCommand.Command.Delay);
Delay(_settingService, sceneCommand.Command.Delay);
}
catch (Exception ex)
{
@ -444,27 +414,6 @@ namespace IoTCenter.Services
};
}
private void Delay(int commandDelay)
{
var delay = 0;
try
{
delay = Convert.ToInt32(this._settingService.GetSetting("delay").Value);
}
catch (Exception ex)
{
this._logger.LogError(ex.ToString());
}
if (commandDelay > 0)
{
delay += commandDelay;
}
if (delay > 0)
{
Thread.Sleep(delay);
}
}
public void Handle(NodeClientConnectedEvent message)
{
var organ = this._organRepo.Table().FirstOrDefault(o => o.Number == message.OrganNumber);
@ -489,5 +438,59 @@ namespace IoTCenter.Services
}
}
}
public void Handle(Guid id)
{
GlobalTimerExec(_logger, _settingService, _organSceneTimerRepo, _hub, id);
}
public static void GlobalTimerExec(ILogger _logger, ISettingService _settingService, IRepository<OrganSceneTimer> _organSceneTimerRepo, IHubContext<IoTCenterHub> _hub, Guid id)
{
try
{
_logger.LogInformation($"global timer exec at {DateTime.Now.ToString("G")}:{id}");
var timer = _organSceneTimerRepo.ReadOnlyTable()
.Include(o => o.OrganScene).ThenInclude(o => o.OrganSceneCommands).ThenInclude(o => o.Command).ThenInclude(o => o.Device).ThenInclude(o => o.Node)
.FirstOrDefault(o => o.Id == id);
if (timer != null)
{
foreach (var sceneCommand in timer.OrganScene.OrganSceneCommands.OrderBy(o => o.Command.DisplayOrder))
{
try
{
_hub.ServerToClient(Methods.ExecCommand, sceneCommand.CommandId, sceneCommand.Command.Device.Node.Number, null);
Delay(_settingService, sceneCommand.Command.Delay);
}
catch (Exception ex)
{
_logger.LogError(ex.ToString());
}
}
}
else
{
_logger.LogError($"timer {id} does not exist");
}
}
catch (Exception ex)
{
_logger.LogError(ex.ToString());
}
}
public static void Delay(ISettingService _settingService, int delay)
{
if (int.TryParse(_settingService.GetSetting("delay").Value, out int commandDelay))
{
if (commandDelay > 0)
{
delay += commandDelay;
}
}
if (delay > 0)
{
Thread.Sleep(delay);
}
}
}
}

@ -12,8 +12,6 @@
"mysql": "Server=localhost;Port=3306;Database=iotcenter;Uid=root;Pwd=aA123456!;",
"HangfireConnection": "Server=localhost;Port=3306;Database=jobserver;Uid=root;Pwd=aA123456!;Allow User Variables=True;",
"redis": "localhost:6379,password=aA123456!,allowAdmin=true",
"srs": "http://localhost:1985",
"JobServer": "http://localhost/JobServer",
"JobCallBack": "http://localhost/IoTCenter/api/v1/Api/ExecTimer"
"srs": "http://localhost:1985"
}
}

@ -7,9 +7,7 @@
"mysql": "Server=172.172.0.30;Port=3306;Database=iotcenter;Uid=root;Pwd=aA123456!;",
"HangfireConnection": "Server=172.172.0.30;Port=3306;Database=jobserver;Uid=root;Pwd=aA123456!;Allow User Variables=True;",
"redis": "172.172.0.40:6379,password=aA123456!,allowAdmin=true",
"srs": "http://172.172.0.60:1985",
"JobServer": "http://172.172.0.12/JobServer",
"JobCallBack": "http://172.172.0.12/IoTCenter/api/v1/Api/ExecTimer"
"srs": "http://172.172.0.60:1985"
},
"influxdb": {
"url": "http://172.172.0.50:8086",

@ -61,9 +61,7 @@
"mysql": "Server=mysql;Port=3306;Database=iotcenter;Uid=root;Pwd=aA123456!;",
"HangfireConnection": "Server=mysql;Port=3306;Database=jobserver;Uid=root;Pwd=aA123456!;Allow User Variables=True;",
"redis": "redis:6379,password=aA123456!,allowAdmin=true",
"srs": "http://srs:1985",
"JobServer": "http://jobserver/JobServer",
"JobCallBack": "http://iotcenter/IoTCenter/api/v1/Api/ExecTimer"
"srs": "http://srs:1985"
},
"AppSettings": {
"database": "mysql",

@ -34,6 +34,25 @@ namespace IoTNode
public void OnModelCreating(ModelBuilder modelBuilder)
{
IoTSharedDbConfig.OnModelCreating(modelBuilder);
modelBuilder.Ignore<NodeCategory>();
modelBuilder.Ignore<NodeCategoryNode>();
modelBuilder.Ignore<NodeCategoryNode>();
modelBuilder.Ignore<NodeCategoryNode>();
modelBuilder.Ignore<Organ>();
modelBuilder.Ignore<Organ>();
modelBuilder.Ignore<OrganUser>();
modelBuilder.Ignore<OrganUser>();
modelBuilder.Ignore<OrganUser>();
modelBuilder.Ignore<OrganNode>();
modelBuilder.Ignore<OrganNode>();
modelBuilder.Ignore<OrganNode>();
modelBuilder.Ignore<OrganNode>();
modelBuilder.Ignore<OrganScene>();
modelBuilder.Ignore<OrganSceneCommand>();
modelBuilder.Ignore<OrganSceneCommand>();
modelBuilder.Ignore<OrganSceneTimer>();
modelBuilder.Ignore<OrganSceneTigger>();
modelBuilder.Ignore<OrganSceneTigger>();
}
public void Seed(DbContext db)

@ -61,7 +61,7 @@
});
},
updateTimer: function () {
axios.post(this.baseUrl + '/IoTCenter/api/v1/site/UpdateTimer')
axios.post(this.baseUrl + '/IoTCenter/api/v1/api/UpdateTimer')
.then(function (response) {
Swal.fire({ title: '操作完成', timer: 1500 });
})

@ -20,7 +20,7 @@
},
methods: {
updateTimer: function () {
axios.post(this.baseUrl + '/IoTCenter/api/v1/site/UpdateTimer')
axios.post(this.baseUrl + '/IoTCenter/api/v1/api/UpdateTimer')
.then(function (response) {
Swal.fire({ title: '操作完成', timer: 1500 });
})

@ -125,15 +125,6 @@ services:
- mysql
- redis
#定时任务
jobserver:
image: ${DOCKER_REGISTRY-}jobserver
build:
context: .
dockerfile: JobServer/Dockerfile
depends_on:
- mysql
#docker管理
portainer:
image: portainer/portainer:1.24.1

@ -29,7 +29,6 @@ Copy-Item ../projects/WebMVC/wwwroot/* ./dist/linux-x64/publish/apps/WebMVC/www
Copy-Item ../projects/WebSPA/wwwroot/* ./dist/linux-x64/publish/apps/WebSPA/wwwroot -recurse
dotnet publish ../projects/UserCenter/UserCenter.csproj -c Release -r linux-x64 -p:PublishSingleFile=true -o ../publish/dist/linux-x64/publish/apps/UserCenter
dotnet publish ../projects/JobServer/JobServer.csproj -c Release -r linux-x64 -p:PublishSingleFile=true -o ../publish/dist/linux-x64/publish/apps/JobServer
dotnet publish ../projects/IoTCenter/IoTCenter.csproj -c Release -r linux-x64 -p:PublishSingleFile=true -o ../publish/dist/linux-x64/publish/apps/IoTCenter

@ -38,20 +38,3 @@ services:
networks:
default:
ipv4_address: 172.172.0.80
jobserver:
image: mcr.microsoft.com/dotnet/core/runtime-deps:3.1-focal
restart: always
environment:
- TZ=Asia/Shanghai
- ASPNETCORE_ENVIRONMENT=Docker
command: bash -c "sleep 3 && chmod +x /JobServer/JobServer && cd /JobServer && ./JobServer"
depends_on:
- mysql
ports:
- 8013:80
volumes:
- ./apps/JobServer:/JobServer
- ./docker/log/JobServer:/JobServer/logs
networks:
default:
ipv4_address: 172.172.0.90

Loading…
Cancel
Save