diff --git a/projects/.gitignore b/projects/.gitignore
index 0a343817..82a1b88d 100644
--- a/projects/.gitignore
+++ b/projects/.gitignore
@@ -1 +1,9 @@
-.vs
\ No newline at end of file
+.vs
+bin
+obj
+log
+portainer
+mysql
+influxdb
+srs/objs
+
diff --git a/projects/Infrastructure/Web/SignalR/BasePageHub.cs b/projects/Infrastructure/Web/SignalR/BasePageHub.cs
index 81bf50a3..4c75f824 100644
--- a/projects/Infrastructure/Web/SignalR/BasePageHub.cs
+++ b/projects/Infrastructure/Web/SignalR/BasePageHub.cs
@@ -28,11 +28,6 @@ namespace Infrastructure.Web.SignalR
{
Context.Items["type"] = type;
}
- var organ = Context.GetHttpContext().Request.Query["organ"].ToString();
- if (!string.IsNullOrEmpty(organ))
- {
- Context.Items["organ"] = organ;
- }
this.Clients.Group(Context.ConnectionId).SendAsync("Connected", Context.ConnectionId);
}
diff --git a/projects/IoT.Shared/Application/Domain/Entities/Command.cs b/projects/IoT.Shared/Application/Domain/Entities/Command.cs
index 90059baf..e64eb7de 100644
--- a/projects/IoT.Shared/Application/Domain/Entities/Command.cs
+++ b/projects/IoT.Shared/Application/Domain/Entities/Command.cs
@@ -20,6 +20,9 @@ namespace Application.Domain.Entities
[Display(Name = "隐藏")]
public bool Disabled { get; set; }
+ [Display(Name = "延迟")]
+ public int Delay { get; set; }
+
///
/// 参数
///
diff --git a/projects/IoT.Shared/Application/Domain/Entities/Node.cs b/projects/IoT.Shared/Application/Domain/Entities/Node.cs
index 59037dd1..ea8245a4 100644
--- a/projects/IoT.Shared/Application/Domain/Entities/Node.cs
+++ b/projects/IoT.Shared/Application/Domain/Entities/Node.cs
@@ -7,6 +7,13 @@ namespace Application.Domain.Entities
[Display(Name = "节点")]
public class Node : BaseEntity
{
+ [Display(Name = "机构名称")]
+ public string OrganName { get; set; }
+
+ [Display(Name = "机构编号")]
+ [Required]
+ public string OrganNumber { get; set; }
+
[Display(Name = "节点名称")]
public string Name { get; set; }
diff --git a/projects/IoT.Shared/Application/Models/EditCommandModel.cs b/projects/IoT.Shared/Application/Models/EditCommandModel.cs
index 1067c876..38d8d472 100644
--- a/projects/IoT.Shared/Application/Models/EditCommandModel.cs
+++ b/projects/IoT.Shared/Application/Models/EditCommandModel.cs
@@ -36,6 +36,9 @@ namespace Application.Models
[Display(Name = "隐藏")]
public bool Disabled { get; set; }
+ [Display(Name = "延迟")]
+ public int Delay { get; set; }
+
[HiddenInput(DisplayValue = false)]
[ScaffoldColumn(true)]
public string QueryString { get; set; }
diff --git a/projects/IoT.Shared/Application/Models/EditNodeModel.cs b/projects/IoT.Shared/Application/Models/EditNodeModel.cs
index d2feb3e5..788ee2a6 100644
--- a/projects/IoT.Shared/Application/Models/EditNodeModel.cs
+++ b/projects/IoT.Shared/Application/Models/EditNodeModel.cs
@@ -7,6 +7,16 @@ namespace Application.Models
[Display(Name = "节点")]
public class EditNodeModel : EditModel
{
+ [Display(Name = "机构名称")]
+ [MaxLength(64, ErrorMessage = "{0}最大长度为{1}")]
+ [Required(ErrorMessage = nameof(RequiredAttribute))]
+ public string OrganName { get; set; }
+
+ [Display(Name = "机构编码")]
+ [MaxLength(64, ErrorMessage = "{0}最大长度为{1}")]
+ [Required(ErrorMessage = nameof(RequiredAttribute))]
+ public string OrganNumber { get; set; }
+
[Display(Name = "节点名称")]
[Required(ErrorMessage = nameof(RequiredAttribute))]
public string Name { get; set; }
diff --git a/projects/IoT.Shared/Services/IoTCenter/IoTCenterHub.cs b/projects/IoT.Shared/Services/IoTCenter/IoTCenterHub.cs
index 3cc4fc53..cb6fb877 100644
--- a/projects/IoT.Shared/Services/IoTCenter/IoTCenterHub.cs
+++ b/projects/IoT.Shared/Services/IoTCenter/IoTCenterHub.cs
@@ -5,7 +5,6 @@ using Infrastructure.Events;
using Infrastructure.Extensions;
using Infrastructure.Web.SignalR;
using IoT.Shared.Services;
-using IoT.Shared.Services.IoTCenter;
using Microsoft.AspNetCore.SignalR;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
@@ -102,11 +101,6 @@ namespace IoTCenter.Services
try
{
this._nodeRepo.SaveChanges();
- var organ = Context.Items["organ"] as string;
- if (!string.IsNullOrEmpty(organ))
- {
- this._publisher.Publish(new NodeClientConnectedEvent { NodeNumber = node.Number, OrganNumber = organ });
- }
}
catch (Exception ex)
{
diff --git a/projects/IoT.Shared/Services/IoTNode/IoTNodeClient.cs b/projects/IoT.Shared/Services/IoTNode/IoTNodeClient.cs
index 1e80bf2e..51e4d1c4 100644
--- a/projects/IoT.Shared/Services/IoTNode/IoTNodeClient.cs
+++ b/projects/IoT.Shared/Services/IoTNode/IoTNodeClient.cs
@@ -18,6 +18,7 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net.Http;
+using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
@@ -134,8 +135,7 @@ namespace IoT.Shared.Services
private void InitConnection()
{
this._notifyHost = GetSetting("notify:host");
- var organ = GetSetting("organ");
- var url = $"{this._notifyHost}/hub?type=node&organ={organ}&group={GetSetting("sn")}";
+ var url = $"{this._notifyHost}/hub?type=node&group={GetSetting("sn")}";
this._logger.LogDebug($"init connection for {url}");
if (this.Connection != null)
{
@@ -402,7 +402,7 @@ namespace IoT.Shared.Services
public void ExecCommands(List commands)
{
using var scope = this._applicationServices.CreateScope();
- foreach (var command in commands)
+ foreach (var command in commands.OrderBy(o => o.DisplayOrder))
{
try
{
@@ -411,6 +411,7 @@ namespace IoT.Shared.Services
var url = this.GetCommandUrl(command);
var httpClient = scope.ServiceProvider.GetService().CreateClient();
var result = httpClient.GetStringAsync(url).Result;
+ Delay(command.Delay);
}
catch (Exception ex)
{
@@ -494,5 +495,29 @@ namespace IoT.Shared.Services
return null;
}
}
+
+ private void Delay(int commandDelay)
+ {
+ using var scope = _applicationServices.CreateScope();
+ var serviceProvider = scope.ServiceProvider;
+ var settingService = serviceProvider.GetService();
+ var delay = 0;
+ try
+ {
+ delay = Convert.ToInt32(settingService.GetSetting("delay").Value);
+ }
+ catch (Exception ex)
+ {
+ this._logger.LogError(ex.ToString());
+ }
+ if (commandDelay > 0)
+ {
+ delay += commandDelay;
+ }
+ if (delay > 0)
+ {
+ Thread.Sleep(delay);
+ }
+ }
}
}
\ No newline at end of file
diff --git a/projects/IoTCenter/Api/ApiController.cs b/projects/IoTCenter/Api/ApiController.cs
index a2ec4b13..a7c474bd 100644
--- a/projects/IoTCenter/Api/ApiController.cs
+++ b/projects/IoTCenter/Api/ApiController.cs
@@ -1,7 +1,7 @@
using Application.Domain.Entities;
using Application.Models;
+using Infrastructure.Application.Services.Settings;
using Infrastructure.Data;
-using Infrastructure.Extensions;
using IoTCenter.Services;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.SignalR;
@@ -10,6 +10,7 @@ using Microsoft.Extensions.Logging;
using System;
using System.ComponentModel.DataAnnotations;
using System.Linq;
+using System.Threading;
namespace IoTCenter.Api.Controllers
{
@@ -18,34 +19,37 @@ namespace IoTCenter.Api.Controllers
[ApiController]
public class ApiController : ControllerBase
{
+ private readonly ISettingService _settingService;
private readonly ILogger _logger;
private readonly IRepository _sceneRepo;
private readonly IRepository _sceneCommandRepo;
+ private readonly IRepository _sceneTimerRepo;
private readonly IRepository _commandRepo;
private readonly IRepository _deviceRepo;
- private readonly IRepository _sceneTimerRepo;
private readonly IHubContext _hub;
public ApiController(
+ ISettingService settingService,
ILogger logger,
IRepository sceneRepo,
IRepository sceneCommandRepo,
+ IRepository sceneTimerRepo,
IRepository commandRepo,
IRepository deviceRepo,
- IRepository sceneTimerRepo,
IHubContext hub)
{
+ this._settingService = settingService;
this._logger = logger;
this._sceneRepo = sceneRepo;
+ this._sceneTimerRepo = sceneTimerRepo;
this._sceneCommandRepo = sceneCommandRepo;
this._commandRepo = commandRepo;
this._deviceRepo = deviceRepo;
- this._sceneTimerRepo = sceneTimerRepo;
this._hub = hub;
}
[HttpPost]
- public ActionResult ExecApi([FromBody]ApiRequestModel model)
+ public ActionResult ExecApi([FromBody] ApiRequestModel model)
{
try
{
@@ -54,13 +58,13 @@ namespace IoTCenter.Api.Controllers
}
catch (Exception ex)
{
- ex.PrintStack();
+ this._logger.LogError(ex.ToString());
return Problem(ex.Message);
}
}
[HttpPost]
- public ActionResult ExecScene([FromBody][Required]Guid id)
+ public ActionResult ExecScene([FromBody][Required] Guid id)
{
try
{
@@ -78,15 +82,16 @@ namespace IoTCenter.Api.Controllers
.Where(o => o.SceneId == id)
.Select(o => o.Command)
.ToList();
- foreach (var command in commands)
+ foreach (var command in commands.OrderBy(o => o.DisplayOrder))
{
try
{
this._hub.ServerToClient(Methods.ExecCommand, command.Id, command.Device.Node.Number, null);
+ Delay(command.Delay);
}
catch (Exception ex)
{
- ex.PrintStack();
+ this._logger.LogError(ex.ToString());
}
}
}
@@ -95,13 +100,13 @@ namespace IoTCenter.Api.Controllers
}
catch (Exception ex)
{
- ex.PrintStack();
+ this._logger.LogError(ex.ToString());
return Problem(ex.Message);
}
}
[HttpPost]
- public ActionResult ExecCommand([FromBody][Required]Guid id)
+ public ActionResult ExecCommand([FromBody][Required] Guid id)
{
try
{
@@ -111,14 +116,19 @@ namespace IoTCenter.Api.Controllers
}
catch (Exception ex)
{
- ex.PrintStack();
+ this._logger.LogError(ex.ToString());
return Problem(ex.Message);
}
}
+ ///
+ /// job server call back
+ ///
+ ///
+ ///
[HttpPost]
[Route("{id}")]
- public ActionResult ExecTimer([Required]Guid id)
+ public ActionResult ExecTimer([Required] Guid id)
{
try
{
@@ -128,15 +138,16 @@ namespace IoTCenter.Api.Controllers
.FirstOrDefault(o => o.Id == id);
if (timer != null)
{
- foreach (var sceneCommand in timer.Scene.SceneCommands)
+ foreach (var sceneCommand in timer.Scene.SceneCommands.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)
{
- ex.PrintStack();
+ this._logger.LogError(ex.ToString());
}
}
}
@@ -148,7 +159,7 @@ namespace IoTCenter.Api.Controllers
}
catch (Exception ex)
{
- ex.PrintStack();
+ this._logger.LogError(ex.ToString());
return Problem(ex.Message);
}
}
@@ -163,5 +174,26 @@ namespace IoTCenter.Api.Controllers
this._hub.ServerToClient(Methods.ExecApiRequest, message, group, connectionId);
}
}
+
+ 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);
+ }
+ }
}
}
\ No newline at end of file
diff --git a/projects/IoTCenter/Api/NodeController.cs b/projects/IoTCenter/Api/NodeController.cs
index 82ddd7e7..8b642117 100644
--- a/projects/IoTCenter/Api/NodeController.cs
+++ b/projects/IoTCenter/Api/NodeController.cs
@@ -1,5 +1,6 @@
using Application.Domain.Entities;
using Application.Models;
+using Infrastructure.Application.Services.Settings;
using Infrastructure.Data;
using Infrastructure.Extensions;
using IoTCenter.Services;
@@ -9,6 +10,8 @@ using Microsoft.EntityFrameworkCore;
using System;
using System.ComponentModel.DataAnnotations;
using System.Linq;
+using System.Threading;
+using Microsoft.Extensions.Logging;
namespace IoTCenter.Api.Controllers
{
@@ -17,14 +20,21 @@ namespace IoTCenter.Api.Controllers
[ApiController]
public class NodeController : ControllerBase
{
+ private readonly ILogger _logger;
+ private readonly ISettingService _settingService;
private readonly IRepository _nodeRepo;
private readonly IRepository _deviceRepo;
private readonly IHubContext _hub;
- public NodeController(IRepository nodeRepo,
+ public NodeController(
+ ILogger logger,
+ ISettingService settingService,
+ IRepository nodeRepo,
IRepository deviceRepo,
IHubContext hub)
{
+ this._logger = logger;
+ this._settingService = settingService;
this._nodeRepo = nodeRepo;
this._deviceRepo = deviceRepo;
this._hub = hub;
@@ -59,7 +69,7 @@ namespace IoTCenter.Api.Controllers
}
[HttpPost]
- public ActionResult GetNode([Required]string number)
+ public ActionResult GetNode([Required] string number)
{
try
{
@@ -80,25 +90,25 @@ namespace IoTCenter.Api.Controllers
}
[HttpPost]
- public ActionResult PowerOn([FromBody][Required]string number)
+ public ActionResult PowerOn([FromBody][Required] string number)
{
return this.Power(number, "On");
}
[HttpPost]
- public ActionResult PowerOff([FromBody][Required]string number)
+ public ActionResult PowerOff([FromBody][Required] string number)
{
return this.Power(number, "Off");
}
[HttpPost]
- public ActionResult Upload([FromBody][Required]string number)
+ public ActionResult Upload([FromBody][Required] string number)
{
this._hub.ServerToClient(Methods.UploadNode, "", number);
return Ok();
}
- public IActionResult Stop([FromBody][Required]string number)
+ public IActionResult Stop([FromBody][Required] string number)
{
this._hub.ServerToClient(Methods.StopNode, "", number);
return Ok();
@@ -122,6 +132,7 @@ namespace IoTCenter.Api.Controllers
{
var message = $"{api.Path}{api.Command}?number={device.Number}";
this._hub.ServerToClient(Methods.ExecApiRequest, message, device.Node.Number, null);
+ Delay(0);
}
}
catch (Exception ex)
@@ -132,5 +143,26 @@ namespace IoTCenter.Api.Controllers
return Ok();
}
+
+ 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);
+ }
+ }
}
}
\ No newline at end of file
diff --git a/projects/IoTCenter/DbConfig.cs b/projects/IoTCenter/DbConfig.cs
index 168fae50..962eb471 100644
--- a/projects/IoTCenter/DbConfig.cs
+++ b/projects/IoTCenter/DbConfig.cs
@@ -85,6 +85,7 @@ namespace IoTCenter
set.Add(new Setting { Name = "sn", Value = macAddress, Type = SettingType.Text });
set.Add(new Setting { Name = "id", Value = macAddress.Md5(), Type = SettingType.Text });
set.Add(new Setting { Name = "code", Value = "根据id生成的授权码", Type = SettingType.Text });
+ set.Add(new Setting { Name = "delay", Value = "500", Type = SettingType.Text });
db.SaveChanges();
//
db.Set().Add(new NodeCategory { Name = "智慧教室", Template = "node" });
diff --git a/projects/IoTCenter/Dockerfile b/projects/IoTCenter/Dockerfile
new file mode 100644
index 00000000..5bcae962
--- /dev/null
+++ b/projects/IoTCenter/Dockerfile
@@ -0,0 +1,23 @@
+#See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging.
+
+FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim AS base
+WORKDIR /app
+EXPOSE 80
+
+FROM mcr.microsoft.com/dotnet/core/sdk:3.1-buster AS build
+WORKDIR /src
+COPY ["IoTCenter/IoTCenter.csproj", "IoTCenter/"]
+COPY ["IoT.Shared/IoT.Shared.csproj", "IoT.Shared/"]
+COPY ["Infrastructure/Infrastructure.csproj", "Infrastructure/"]
+RUN dotnet restore "IoTCenter/IoTCenter.csproj"
+COPY . .
+WORKDIR "/src/IoTCenter"
+RUN dotnet build "IoTCenter.csproj" -c Release -o /app/build
+
+FROM build AS publish
+RUN dotnet publish "IoTCenter.csproj" -c Release -o /app/publish
+
+FROM base AS final
+WORKDIR /app
+COPY --from=publish /app/publish .
+ENTRYPOINT ["dotnet", "IoTCenter.dll"]
diff --git a/projects/IoTCenter/IoTCenter.csproj b/projects/IoTCenter/IoTCenter.csproj
index 21aa933a..f230bfba 100644
--- a/projects/IoTCenter/IoTCenter.csproj
+++ b/projects/IoTCenter/IoTCenter.csproj
@@ -5,10 +5,15 @@
true
false
false
+ ..\docker-compose.dcproj
+ Linux
+
+
+
diff --git a/projects/IoTCenter/Properties/launchSettings.json b/projects/IoTCenter/Properties/launchSettings.json
index 5355c0c8..47862b0a 100644
--- a/projects/IoTCenter/Properties/launchSettings.json
+++ b/projects/IoTCenter/Properties/launchSettings.json
@@ -22,6 +22,12 @@
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "http://localhost:8011"
+ },
+ "Docker": {
+ "commandName": "Docker",
+ "launchBrowser": true,
+ "launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}",
+ "publishAllPorts": true
}
}
}
\ No newline at end of file
diff --git a/projects/IoTCenter/Services/IoTCenterEventHandler.cs b/projects/IoTCenter/Services/IoTCenterEventHandler.cs
index a5c8b08c..8444c612 100644
--- a/projects/IoTCenter/Services/IoTCenterEventHandler.cs
+++ b/projects/IoTCenter/Services/IoTCenterEventHandler.cs
@@ -1,5 +1,6 @@
using Application.Domain.Entities;
using Application.Models;
+using Infrastructure.Application.Services.Settings;
using Infrastructure.Data;
using Infrastructure.Events;
using Infrastructure.Extensions;
@@ -17,6 +18,7 @@ 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;
using Vibrant.InfluxDB.Client.Rows;
@@ -24,6 +26,8 @@ using Vibrant.InfluxDB.Client.Rows;
namespace IoTCenter.Services
{
public class IoTCenterEventHandler :
+ IEventHander>,
+ IEventHander>,
IEventHander>,
IEventHander>,
IEventHander>,
@@ -48,6 +52,7 @@ namespace IoTCenter.Services
IEventHander
{
private readonly IConfiguration _cfg;
+ private readonly ISettingService _settingService;
private readonly ILogger _logger;
private readonly IRepository _nodeRepo;
private readonly IRepository _organRepo;
@@ -60,6 +65,7 @@ namespace IoTCenter.Services
private readonly IHttpClientFactory _httpClientFactory;
public IoTCenterEventHandler(IConfiguration cfg,
+ ISettingService settingService,
ILogger logger,
IRepository nodeRepo,
IRepository organRepo,
@@ -72,6 +78,7 @@ namespace IoTCenter.Services
IHttpClientFactory httpClientFactory)
{
this._cfg = cfg;
+ this._settingService = settingService;
this._logger = logger;
this._nodeRepo = nodeRepo;
this._organRepo = organRepo;
@@ -154,11 +161,13 @@ namespace IoTCenter.Services
public void Handle(EntityInsertedEvent message)
{
this.Notify(message);
+ this.UpdateOrganNode(message.Data);
}
public void Handle(EntityUpdatedEvent message)
{
this.Notify(message);
+ this.UpdateOrganNode(message.Data);
}
public void Handle(EntityDeletedEvent message)
@@ -168,6 +177,22 @@ namespace IoTCenter.Services
#endregion Node
+ #region organ
+
+ public void Handle(EntityInsertedEvent message)
+ {
+ this.Notify(message);
+ this.UpdateOrganNode(message.Data);
+ }
+
+ public void Handle(EntityUpdatedEvent message)
+ {
+ this.Notify(message);
+ this.UpdateOrganNode(message.Data);
+ }
+
+ #endregion organ
+
#region Device
public void Handle(EntityInsertedEvent message)
@@ -320,11 +345,12 @@ namespace IoTCenter.Services
var tigger = this._sceneTiggerRepo.ReadOnlyTable()
.Include(o => o.Scene).ThenInclude(o => o.SceneCommands).ThenInclude(o => o.Command).ThenInclude(o => o.Device).ThenInclude(o => o.Node)
.FirstOrDefault(o => o.Id == tiggerId);
- foreach (var sceneCommand in tigger.Scene.SceneCommands)
+ foreach (var sceneCommand in tigger.Scene.SceneCommands.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)
{
@@ -338,7 +364,7 @@ namespace IoTCenter.Services
var url = _cfg["influxdb:url"];
var usr = _cfg["influxdb:usr"];
var pwd = _cfg["influxdb:pwd"];
- var device = _deviceRepo.ReadOnlyTable().FirstOrDefault(o => o.Id == data.DeviceId);
+ var device = _deviceRepo.ReadOnlyTable().Include(o => o.Node).FirstOrDefault(o => o.Id == data.DeviceId);
Task.Run(async () =>
{
try
@@ -361,6 +387,8 @@ namespace IoTCenter.Services
{
Timestamp = DateTimeOffset.FromUnixTimeMilliseconds(data.Timestamp).DateTime
};
+ row.Fields.Add("OrganName", device.Node.Name);
+ row.Fields.Add("OrganNumber", device.Node.Number);
row.Fields.Add("DeviceNumber", device.Number);
row.Fields.Add("DeviceName", device.Name);
row.Fields.Add(data.Key, this.GetDataValue(data));
@@ -390,6 +418,27 @@ 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);
@@ -414,5 +463,49 @@ namespace IoTCenter.Services
}
}
}
+
+ private void UpdateOrganNode(Node node)
+ {
+ try
+ {
+ var organ = this._organRepo.ReadOnlyTable().FirstOrDefault(o => o.Number == node.OrganNumber);
+ if (organ != null)
+ {
+ var organNode = this._organNodeRepo.Table().FirstOrDefault(o => o.NodeId == node.Id);
+ if (organNode == null)
+ {
+ organNode = new OrganNode { OrganId = organ.Id, NodeId = node.Id };
+ this._organNodeRepo.Add(organNode);
+ this._organNodeRepo.SaveChanges();
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ this._logger.LogError(ex.ToString());
+ }
+ }
+
+ private void UpdateOrganNode(Organ organ)
+ {
+ try
+ {
+ var nodes = this._nodeRepo.ReadOnlyTable().Where(o => o.OrganNumber == organ.Number).Select(o => o.Id).ToList();
+ foreach (var nodeId in nodes)
+ {
+ var organNode = this._organNodeRepo.Table().FirstOrDefault(o => o.NodeId == nodeId);
+ if (organNode == null)
+ {
+ organNode = new OrganNode { OrganId = organ.Id, NodeId = nodeId };
+ this._organNodeRepo.Add(organNode);
+ this._organNodeRepo.SaveChanges();
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ this._logger.LogError(ex.ToString());
+ }
+ }
}
}
\ No newline at end of file
diff --git a/projects/IoTCenter/db.sql b/projects/IoTCenter/db.sql
index 6f790b24..579c7509 100644
--- a/projects/IoTCenter/db.sql
+++ b/projects/IoTCenter/db.sql
@@ -18,6 +18,8 @@ CREATE TABLE "iot_LiveRecord" (
CREATE TABLE "iot_Node" (
"Id" TEXT NOT NULL CONSTRAINT "PK_iot_Node" PRIMARY KEY,
"IsDeleted" TEXT NULL,
+ "OrganName" TEXT NULL,
+ "OrganNumber" TEXT NOT NULL,
"Name" TEXT NULL,
"Number" TEXT NOT NULL,
"IsOnline" INTEGER NOT NULL,
@@ -211,6 +213,7 @@ CREATE TABLE "iot_Command" (
"Name" TEXT NULL,
"DisplayOrder" INTEGER NOT NULL,
"Disabled" INTEGER NOT NULL,
+ "Delay" INTEGER NOT NULL,
"QueryString" TEXT NULL,
"ApiId" TEXT NOT NULL,
"DeviceId" TEXT NOT NULL,
diff --git a/projects/IoTNode/DbConfig.cs b/projects/IoTNode/DbConfig.cs
index d4d999f5..1fec5bba 100644
--- a/projects/IoTNode/DbConfig.cs
+++ b/projects/IoTNode/DbConfig.cs
@@ -68,7 +68,6 @@ namespace IoTNode
set.Add(new Setting { Name = "name", Value = "物联节点", Type = SettingType.Text });
set.Add(new Setting { Name = "logo", Value = "/images/logo.png", Type = SettingType.ImageUrl });
set.Add(new Setting { Name = "copyright", Value = "Copyright © {0} Company. All rights reserved", Type = SettingType.Html });
- set.Add(new Setting { Name = "organ", Value = "", Type = SettingType.Text });
//
var macAddress = Helper.Instance.GetMacAddress();
set.Add(new Setting { Name = "sn", Value = macAddress, Type = SettingType.Text });
@@ -89,12 +88,15 @@ namespace IoTNode
set.Add(new Setting { Name = "ffmpeg.args", Value = " -y -threads {0} -rtsp_transport tcp -use_wallclock_as_timestamps 1 -stimeout 3000000 -i \"{1}\" -fflags +genpts -c copy -f flv \"{2}\"" });
set.Add(new Setting { Name = "fbee.writelist", Value = "" });
set.Add(new Setting { Name = "camera.writelist", Value = "" });
+ set.Add(new Setting { Name = "delay", Value = "500", Type = SettingType.Text });
db.SaveChanges();
var sn = macAddress;
db.Set().Add(new Node
{
Id = $"nodeid-{sn}".ToGuid(),
+ OrganName = "默认机构名称",
+ OrganNumber = "默认机构编码",
Name = "节点",
Number = sn,
IsOnline = true,
diff --git a/projects/IoTNode/db.sql b/projects/IoTNode/db.sql
index 96f975ff..0db08ff2 100644
--- a/projects/IoTNode/db.sql
+++ b/projects/IoTNode/db.sql
@@ -9,6 +9,8 @@ CREATE TABLE "iot_Category" (
CREATE TABLE "iot_Node" (
"Id" TEXT NOT NULL CONSTRAINT "PK_iot_Node" PRIMARY KEY,
"IsDeleted" TEXT NULL,
+ "OrganName" TEXT NULL,
+ "OrganNumber" TEXT NOT NULL,
"Name" TEXT NULL,
"Number" TEXT NOT NULL,
"IsOnline" INTEGER NOT NULL,
@@ -168,6 +170,7 @@ CREATE TABLE "iot_Command" (
"Name" TEXT NULL,
"DisplayOrder" INTEGER NOT NULL,
"Disabled" INTEGER NOT NULL,
+ "Delay" INTEGER NOT NULL,
"QueryString" TEXT NULL,
"ApiId" TEXT NOT NULL,
"DeviceId" TEXT NOT NULL,
diff --git a/projects/JobServer/Dockerfile b/projects/JobServer/Dockerfile
new file mode 100644
index 00000000..c0d63a71
--- /dev/null
+++ b/projects/JobServer/Dockerfile
@@ -0,0 +1,21 @@
+#See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging.
+
+FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim AS base
+WORKDIR /app
+EXPOSE 80
+
+FROM mcr.microsoft.com/dotnet/core/sdk:3.1-buster AS build
+WORKDIR /src
+COPY ["JobServer/JobServer.csproj", "JobServer/"]
+RUN dotnet restore "JobServer/JobServer.csproj"
+COPY . .
+WORKDIR "/src/JobServer"
+RUN dotnet build "JobServer.csproj" -c Release -o /app/build
+
+FROM build AS publish
+RUN dotnet publish "JobServer.csproj" -c Release -o /app/publish
+
+FROM base AS final
+WORKDIR /app
+COPY --from=publish /app/publish .
+ENTRYPOINT ["dotnet", "JobServer.dll"]
diff --git a/projects/JobServer/JobServer.csproj b/projects/JobServer/JobServer.csproj
index 39c84903..cab1e357 100644
--- a/projects/JobServer/JobServer.csproj
+++ b/projects/JobServer/JobServer.csproj
@@ -6,6 +6,8 @@
true
false
false
+ ..\docker-compose.dcproj
+ Linux
@@ -16,6 +18,7 @@
+
diff --git a/projects/JobServer/Properties/launchSettings.json b/projects/JobServer/Properties/launchSettings.json
index c9374916..676e5661 100644
--- a/projects/JobServer/Properties/launchSettings.json
+++ b/projects/JobServer/Properties/launchSettings.json
@@ -1,4 +1,4 @@
-{
+{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
@@ -18,10 +18,16 @@
"JobServer": {
"commandName": "Project",
"launchBrowser": true,
- "applicationUrl": "http://localhost:8013",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
- }
+ },
+ "applicationUrl": "http://localhost:8013"
+ },
+ "Docker": {
+ "commandName": "Docker",
+ "launchBrowser": true,
+ "launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}",
+ "publishAllPorts": true
}
}
}
\ No newline at end of file
diff --git a/projects/UserCenter/Dockerfile b/projects/UserCenter/Dockerfile
index 676b782d..e0baf2f0 100644
--- a/projects/UserCenter/Dockerfile
+++ b/projects/UserCenter/Dockerfile
@@ -19,4 +19,4 @@ RUN dotnet publish "UserCenter.csproj" -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
-ENTRYPOINT ["dotnet", "UserCenter.dll"]
\ No newline at end of file
+ENTRYPOINT ["dotnet", "UserCenter.dll"]
diff --git a/projects/UserCenter/UserCenter.csproj b/projects/UserCenter/UserCenter.csproj
index 75bd5fef..e059c784 100644
--- a/projects/UserCenter/UserCenter.csproj
+++ b/projects/UserCenter/UserCenter.csproj
@@ -6,6 +6,7 @@
false
false
Linux
+ ..\docker-compose.dcproj
diff --git a/projects/Version.cs b/projects/Version.cs
index 010c1212..4d9490e8 100644
--- a/projects/Version.cs
+++ b/projects/Version.cs
@@ -1,4 +1,4 @@
using System.Reflection;
[assembly: AssemblyVersion("1.0.0.0")]
-[assembly: AssemblyInformationalVersion("1.0.0.515")]
\ No newline at end of file
+[assembly: AssemblyInformationalVersion("1.0.0.521")]
\ No newline at end of file
diff --git a/projects/WebMVC/Dockerfile b/projects/WebMVC/Dockerfile
new file mode 100644
index 00000000..22b21930
--- /dev/null
+++ b/projects/WebMVC/Dockerfile
@@ -0,0 +1,21 @@
+#See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging.
+
+FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim AS base
+WORKDIR /app
+EXPOSE 80
+
+FROM mcr.microsoft.com/dotnet/core/sdk:3.1-buster AS build
+WORKDIR /src
+COPY ["WebMVC/WebMVC.csproj", "WebMVC/"]
+RUN dotnet restore "WebMVC/WebMVC.csproj"
+COPY . .
+WORKDIR "/src/WebMVC"
+RUN dotnet build "WebMVC.csproj" -c Release -o /app/build
+
+FROM build AS publish
+RUN dotnet publish "WebMVC.csproj" -c Release -o /app/publish
+
+FROM base AS final
+WORKDIR /app
+COPY --from=publish /app/publish .
+ENTRYPOINT ["dotnet", "WebMVC.dll"]
diff --git a/projects/WebMVC/Properties/launchSettings.json b/projects/WebMVC/Properties/launchSettings.json
index 3d78e8c3..31334ade 100644
--- a/projects/WebMVC/Properties/launchSettings.json
+++ b/projects/WebMVC/Properties/launchSettings.json
@@ -1,4 +1,4 @@
-{
+{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
@@ -18,10 +18,16 @@
"WebMVC": {
"commandName": "Project",
"launchBrowser": true,
- "applicationUrl": "http://localhost:5001",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
- }
+ },
+ "applicationUrl": "http://localhost:5001"
+ },
+ "Docker": {
+ "commandName": "Docker",
+ "launchBrowser": true,
+ "launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}",
+ "publishAllPorts": true
}
}
}
\ No newline at end of file
diff --git a/projects/WebMVC/WebMVC.csproj b/projects/WebMVC/WebMVC.csproj
index e58c9bba..8bfa36c3 100644
--- a/projects/WebMVC/WebMVC.csproj
+++ b/projects/WebMVC/WebMVC.csproj
@@ -3,9 +3,12 @@
netcoreapp3.1
en
+ ..\docker-compose.dcproj
+ Linux
+
\ No newline at end of file
diff --git a/projects/WebSPA/Dockerfile b/projects/WebSPA/Dockerfile
new file mode 100644
index 00000000..81118c44
--- /dev/null
+++ b/projects/WebSPA/Dockerfile
@@ -0,0 +1,21 @@
+#See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging.
+
+FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim AS base
+WORKDIR /app
+EXPOSE 80
+
+FROM mcr.microsoft.com/dotnet/core/sdk:3.1-buster AS build
+WORKDIR /src
+COPY ["WebSPA/WebSPA.csproj", "WebSPA/"]
+RUN dotnet restore "WebSPA/WebSPA.csproj"
+COPY . .
+WORKDIR "/src/WebSPA"
+RUN dotnet build "WebSPA.csproj" -c Release -o /app/build
+
+FROM build AS publish
+RUN dotnet publish "WebSPA.csproj" -c Release -o /app/publish
+
+FROM base AS final
+WORKDIR /app
+COPY --from=publish /app/publish .
+ENTRYPOINT ["dotnet", "WebSPA.dll"]
diff --git a/projects/WebSPA/Properties/launchSettings.json b/projects/WebSPA/Properties/launchSettings.json
index 20887ee7..00786f41 100644
--- a/projects/WebSPA/Properties/launchSettings.json
+++ b/projects/WebSPA/Properties/launchSettings.json
@@ -1,4 +1,4 @@
-{
+{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
@@ -18,10 +18,16 @@
"WebSPA": {
"commandName": "Project",
"launchBrowser": true,
- "applicationUrl": "http://localhost:5002",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
- }
+ },
+ "applicationUrl": "http://localhost:5002"
+ },
+ "Docker": {
+ "commandName": "Docker",
+ "launchBrowser": true,
+ "launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}",
+ "publishAllPorts": true
}
}
}
\ No newline at end of file
diff --git a/projects/WebSPA/WebSPA.csproj b/projects/WebSPA/WebSPA.csproj
index e58c9bba..8bfa36c3 100644
--- a/projects/WebSPA/WebSPA.csproj
+++ b/projects/WebSPA/WebSPA.csproj
@@ -3,9 +3,12 @@
netcoreapp3.1
en
+ ..\docker-compose.dcproj
+ Linux
+
\ No newline at end of file
diff --git a/projects/docker-compose.dcproj b/projects/docker-compose.dcproj
new file mode 100644
index 00000000..1b6d80dd
--- /dev/null
+++ b/projects/docker-compose.dcproj
@@ -0,0 +1,18 @@
+
+
+
+ 2.1
+ Linux
+ db048e66-3411-41f6-86f7-a8f73a9f806a
+ LaunchBrowser
+ {Scheme}://localhost:{ServicePort}
+ webmvc
+
+
+
+ docker-compose.yml
+
+
+
+
+
\ No newline at end of file
diff --git a/projects/docker-compose.override.yml b/projects/docker-compose.override.yml
new file mode 100644
index 00000000..f8fa2e61
--- /dev/null
+++ b/projects/docker-compose.override.yml
@@ -0,0 +1,36 @@
+version: '3.4'
+
+services:
+ webmvc:
+ environment:
+ - ASPNETCORE_ENVIRONMENT=Development
+ ports:
+ - "80"
+
+ usercenter:
+ environment:
+ - ASPNETCORE_ENVIRONMENT=Development
+ ports:
+ - "80"
+
+
+ iotcenter:
+ environment:
+ - ASPNETCORE_ENVIRONMENT=Development
+ ports:
+ - "80"
+
+
+ jobserver:
+ environment:
+ - ASPNETCORE_ENVIRONMENT=Development
+ ports:
+ - "80"
+
+
+ webspa:
+ environment:
+ - ASPNETCORE_ENVIRONMENT=Development
+ ports:
+ - "80"
+
diff --git a/projects/docker-compose.yml b/projects/docker-compose.yml
new file mode 100644
index 00000000..36dc3e9e
--- /dev/null
+++ b/projects/docker-compose.yml
@@ -0,0 +1,83 @@
+version: "3.4"
+
+services:
+ portainer:
+ image: portainer/portainer:1.23.2
+ ports:
+ - 9000:9000
+ volumes:
+ - /var/run/docker.sock:/var/run/docker.sock
+ - ./portainer/data:/data
+ mysql:
+ image: mysql:8.0
+ restart: always
+ hostname: mysql
+ environment:
+ MYSQL_ROOT_PASSWORD: root
+ command: --default-authentication-plugin=mysql_native_password
+ volumes:
+ - ./mysql:/var/lib/mysql
+ influxdb:
+ image: influxdb:1.8
+ restart: always
+ hostname: influxdb
+ environment:
+ TZ: "Asia/Shanghai"
+ INFLUXDB_ADMIN_ENABLED: "true"
+ INFLUXDB_ADMIN_USER: admin
+ INFLUXDB_ADMIN_PASSWORD: admin
+ volumes:
+ - ./influxdb:/var/lib/influxdb
+ srs:
+ image: ossrs/srs:v4.0.23
+ environment:
+ TZ: "Asia/Shanghai"
+ restart: always
+ ports:
+ - 1935:1935
+ - 1985:1985
+ volumes:
+ - ./srs/conf/srs.conf:/usr/local/srs/conf/srs.conf
+ - ./log/srs:/usr/local/srs/objs/log
+ - ./srs/objs/nginx/html/video:/usr/local/srs/objs/nginx/html/video
+ usercenter:
+ image: ${DOCKER_REGISTRY-}usercenter
+ build:
+ context: .
+ dockerfile: UserCenter/Dockerfile
+ iotcenter:
+ image: ${DOCKER_REGISTRY-}iotcenter
+ build:
+ context: .
+ dockerfile: IoTCenter/Dockerfile
+ jobserver:
+ image: ${DOCKER_REGISTRY-}jobserver
+ build:
+ context: .
+ dockerfile: JobServer/Dockerfile
+ webmvc:
+ image: ${DOCKER_REGISTRY-}webmvc
+ build:
+ context: .
+ dockerfile: WebMVC/Dockerfile
+ webspa:
+ image: ${DOCKER_REGISTRY-}webspa
+ build:
+ context: .
+ dockerfile: WebSPA/Dockerfile
+ nginx:
+ image: nginx:1.18
+ restart: always
+ environment:
+ TZ: "Asia/Shanghai"
+ ports:
+ - 80:80
+ - 443:443
+ depends_on:
+ - webmvc
+ - usercenter
+ volumes:
+ - ./nginx/nginx.conf:/etc/nginx/nginx.conf
+ - ./nginx/edusoa.key:/etc/nginx/edusoa.key
+ - ./nginx/edusoa.pem:/etc/nginx/edusoa.pem
+ - ./log/nginx:/var/log/nginx
diff --git a/projects/nginx/edusoa.key b/projects/nginx/edusoa.key
new file mode 100644
index 00000000..3902431d
--- /dev/null
+++ b/projects/nginx/edusoa.key
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEowIBAAKCAQEA5vvS8tFXCO/L7gPl/x8iqkJBjWM9MsvNHTkiqJa7gP1CA1bO
+qp4yVtVUdikiz8bmFchgfZHUs7QhZC3KM0araAFwym/SgAN4/STO+Mj9EHqVJqlu
+k6kwZHTF77sZDppbyCEARf0ev5cGKQ44V0xHROOywdHbn0gTLX+Pz+4giPA5lQt+
+hxAL7dYDpumY3H0ZSO/+bn4YFCTHPdIkEqVJ0ifhCR/FR/x+GxAvosU29IV0/Vdj
+X1YFq6Si4jMMNlJwgAwkdXTMOlaLe3fKv4X59aIHcBZecv7FukAm4WSPgHKrvwnv
+wHDQsV3qRqtxUQzvVbuqTaowaMrK+OeBgASRLQIDAQABAoIBAG65mM29fDNUgDWA
+uOgrTLrBOBtGzzdiatjvYqXeW9Phk5t2KWuwmgD2Ep7x6TYg6nrWqyqGlafvWXJk
+YOFjpxccWa0xHX8wKvduhajM8ELOAGGgJtmx6Pi+4YOh9MkDRawR5cenJu5Avzs/
+DdMLRb7ISBCRQO6B5m+RDqdmR0JcvJVhg/8EFd/P4VLRVRiUx5kfA0KSLpGFNJ8b
+aYxiHkW/4DIjlRBqa6ClZYjxQqek683h7S9aInB4gLgrA9fGSQ8+mPyvCSaANP79
+Npo0uN9v3ecdC97uDTRdhhxRmXYcXLL3VI17X6YE6YekarLVfHJWpl8coN2ALmZJ
+5vWqeyECgYEA9mSwyr9HB7Iemx7jeJHo79pqWoflqqdYSf35jz6GOSZCkROocLzI
+hVeXXwM1Gb882fRB0GUM+vsX9ypNP4jtelsBHt1CcPmdNYylN9C2+u4R9EPZC6BW
+KiEsTJUmAWEK8poKa/DZBi/NS+wNyWUgkpwsFr9XbOzuPaMOVIldjDcCgYEA7/1T
+hSpZ9WdIDhdavjr7roBD0/90G4Q8gBUlf/g04c0Xp9FzXDQdH1S0zeYbp+yqbWE9
+P+pic35UVlB58WvtM4IjAoD9Leae58TSh0TER66jU9lssS9obWyH3sfpXswcRpyW
+oOlX7bJ8N8YAAhXGCVlAGrZj+VAtB5QaIIQJg7sCgYEAy2ULXBLSO9QZ18uD03//
+XiBbMyiDuoAyLcJuRIVEn+CpisFDhu0QSqKn3lLzfrGTNgigW7tPH9AvVGWjJxON
+ljeRkTztH/2ufQoBSTYOFs54G7/2Z9aPym9f9kgY+4J0Wxg2CizjumuzeTz/lITa
+gqxQ6OZC8TQU5uS3a6mJg7kCgYAp/443NrMphBqTBLlHozDaV+4G0qSyEBE6ZPj8
+DSbMAUVLhBcJIsGZ8wv1IHjkiUFGBQdgARebmJcPx+OfQUDwi6yuyn4EI2DZtJMX
+QwyKcuB4Uwt3cpF23NBmR1vq0BN+s/aUUGGn4l1ksUzdEIxopGrYgeS7A7Htqphr
+6k9z8wKBgBwcnQJIY2g0cxkt6Idn2Ck2cn0UV0UMH78YqN4FE9LmkFlKw7eE7FiB
+MH4hAVqSAJ64AKEv5Jt6MZamHPPmSj7A6Tj8F1KbJcGZvCpyfo1b76/LRKd1uzAV
+CkjdHPp+tLywydadCRuHxtbSpLF9N91hIMDpdvLzQ3qclhT6GjtF
+-----END RSA PRIVATE KEY-----
diff --git a/projects/nginx/edusoa.pem b/projects/nginx/edusoa.pem
new file mode 100644
index 00000000..6bc12156
--- /dev/null
+++ b/projects/nginx/edusoa.pem
@@ -0,0 +1,91 @@
+-----BEGIN CERTIFICATE-----
+MIIG2DCCBcCgAwIBAgIQDVAa3KQd3HqHhEcYxvwUETANBgkqhkiG9w0BAQsFADBf
+MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
+d3cuZGlnaWNlcnQuY29tMR4wHAYDVQQDExVHZW9UcnVzdCBDTiBSU0EgQ0EgRzEw
+HhcNMTkwODAyMDAwMDAwWhcNMjEwODAxMTIwMDAwWjCBkjELMAkGA1UEBhMCQ04x
+DzANBgNVBAgMBuWQieaelzEPMA0GA1UEBwwG6ZW/5pilMTMwMQYDVQQKDCrkuJzl
+jJfluIjlpKfnkIbmg7Pova/ku7bogqHku73mnInpmZDlhazlj7gxFTATBgNVBAsM
+DFRlYWNoICZTdHVkeTEVMBMGA1UEAwwMKi5lZHVzb2EuY29tMIIBIjANBgkqhkiG
+9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5vvS8tFXCO/L7gPl/x8iqkJBjWM9MsvNHTki
+qJa7gP1CA1bOqp4yVtVUdikiz8bmFchgfZHUs7QhZC3KM0araAFwym/SgAN4/STO
++Mj9EHqVJqluk6kwZHTF77sZDppbyCEARf0ev5cGKQ44V0xHROOywdHbn0gTLX+P
+z+4giPA5lQt+hxAL7dYDpumY3H0ZSO/+bn4YFCTHPdIkEqVJ0ifhCR/FR/x+GxAv
+osU29IV0/VdjX1YFq6Si4jMMNlJwgAwkdXTMOlaLe3fKv4X59aIHcBZecv7FukAm
+4WSPgHKrvwnvwHDQsV3qRqtxUQzvVbuqTaowaMrK+OeBgASRLQIDAQABo4IDWjCC
+A1YwHwYDVR0jBBgwFoAUkZ9eMRWuEJ+tYMH3wcyqSDQvDCYwHQYDVR0OBBYEFCfR
+yJ1xXm33YNyzOHnTZM2dFccPMCMGA1UdEQQcMBqCDCouZWR1c29hLmNvbYIKZWR1
+c29hLmNvbTAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsG
+AQUFBwMCMHUGA1UdHwRuMGwwNKAyoDCGLmh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNv
+bS9HZW9UcnVzdENOUlNBQ0FHMS5jcmwwNKAyoDCGLmh0dHA6Ly9jcmw0LmRpZ2lj
+ZXJ0LmNvbS9HZW9UcnVzdENOUlNBQ0FHMS5jcmwwTAYDVR0gBEUwQzA3BglghkgB
+hv1sAQEwKjAoBggrBgEFBQcCARYcaHR0cHM6Ly93d3cuZGlnaWNlcnQuY29tL0NQ
+UzAIBgZngQwBAgIwbwYIKwYBBQUHAQEEYzBhMCEGCCsGAQUFBzABhhVodHRwOi8v
+b2NzcC5kY29jc3AuY24wPAYIKwYBBQUHMAKGMGh0dHA6Ly9jcmwuZGlnaWNlcnQt
+Y24uY29tL0dlb1RydXN0Q05SU0FDQUcxLmNydDAJBgNVHRMEAjAAMIIBfQYKKwYB
+BAHWeQIEAgSCAW0EggFpAWcAdgC72d+8H4pxtZOUI5eqkntHOFeVCqtS6BqQlmQ2
+jh7RhQAAAWxQXW/EAAAEAwBHMEUCIQDZhWuvn5hItpDiryuFo0ed2a6qCyu+6Nzj
+hoFpYvhLLwIgNL7a0HNsWdPORihBATnbip942aQ+Wvz1N07/qQ3OJD8AdgCHdb/n
+WXz4jEOZX73zbv9WjUdWNv9KtWDBtOr/XqCDDwAAAWxQXXBiAAAEAwBHMEUCIQCl
+yTwBdNkJQMilIoRQrQOvbvihB4uvLMlssZknLmFsHAIgXt1Vn/ETW1xdyvzQH+vx
+nrYdPP4NfmL7lU+tpa5tbDEAdQBElGUusO7Or8RAB9io/ijA2uaCvtjLMbU/0zOW
+tbaBqAAAAWxQXW95AAAEAwBGMEQCICkw8IA+wHkgV10OkfsbEVYFVEpA13+Z3aYb
+2mH89UA+AiAFyKjBvB+2kqFojAAPmUp8rgkgkY/f39MzCl4NOmmunjANBgkqhkiG
+9w0BAQsFAAOCAQEAdsJDXde74RTRXW7ZEa7FQuaQKZFQkEKUPtRTr2RqGAPr1eqq
+DmccPGeIAtvQnkOLIN4B0TQxxzniNhkMHTDOWbvzBmMtWjA4h7rH/eu4rKEE4d6E
+zDXqMDAGrV1v8TmfGS7joCAqCBFLOifal8h7MivyMT5hjokTqi4pM+qDt1A+DHj+
+PtDFnNu/3XvYt64saJEtoAdyqT3Tbk8BR8OTzpXPlk5no/qP9p6lX/UoaJ06tasi
+crni8LSYPbaBYT/HbFSzWtwAe5Azn9p9sGSQHgVb2Z4ryCDAwAXZJuy/GfCCvs4w
+Jj9sK+F9aHBzU9PnudLr/vLS6w6BJPpg9E00qw==
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIFGjCCBAKgAwIBAgIQCgRw0Ja8ihLIkKbfgm7sSzANBgkqhkiG9w0BAQsFADBh
+MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
+d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD
+QTAeFw0xOTA2MjAxMjI3NThaFw0yOTA2MjAxMjI3NThaMF8xCzAJBgNVBAYTAlVT
+MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
+b20xHjAcBgNVBAMTFUdlb1RydXN0IENOIFJTQSBDQSBHMTCCASIwDQYJKoZIhvcN
+AQEBBQADggEPADCCAQoCggEBALFJ+j1KeZVG4jzgQob23lQ8PJUNhY31ufZihuUx
+hYc6HSU4Lw0fxfA43a9DpJl74M3E6F1ZRBOfJ+dWnaiyYD0PxRIQd4wJisti4Uad
+vz61IYY/oQ/Elxk/X7GFDquYuxCSyBdHtTVMXCxFSvQ2C/7jWZFDfGGKKNoQSiJy
+wDe8iiHbUOakLMmXmOTZyWJnFdR/TH5YNTiMKCNUPHAleG4IigGxDyL/gbwrdDNi
+bDA4lUNhD0xNvPjQ8BNKqm5HWDvirUuHdC+4hpi0GJO34O3iiRV16YmWTuVFNboU
+LDZ0+PQtctJnatpuZKPGyKX6jCpPvzzPw/EhNDlpEdrYHZMCAwEAAaOCAc4wggHK
+MB0GA1UdDgQWBBSRn14xFa4Qn61gwffBzKpINC8MJjAfBgNVHSMEGDAWgBQD3lA1
+VtFMu2bwo+IbG8OXsj3RVTAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0lBBYwFAYIKwYB
+BQUHAwEGCCsGAQUFBwMCMA8GA1UdEwEB/wQFMAMBAf8wMQYIKwYBBQUHAQEEJTAj
+MCEGCCsGAQUFBzABhhVodHRwOi8vb2NzcC5kY29jc3AuY24wRAYDVR0fBD0wOzA5
+oDegNYYzaHR0cDovL2NybC5kaWdpY2VydC1jbi5jb20vRGlnaUNlcnRHbG9iYWxS
+b290Q0EuY3JsMIHOBgNVHSAEgcYwgcMwgcAGBFUdIAAwgbcwKAYIKwYBBQUHAgEW
+HGh0dHBzOi8vd3d3LmRpZ2ljZXJ0LmNvbS9DUFMwgYoGCCsGAQUFBwICMH4MfEFu
+eSB1c2Ugb2YgdGhpcyBDZXJ0aWZpY2F0ZSBjb25zdGl0dXRlcyBhY2NlcHRhbmNl
+IG9mIHRoZSBSZWx5aW5nIFBhcnR5IEFncmVlbWVudCBsb2NhdGVkIGF0IGh0dHBz
+Oi8vd3d3LmRpZ2ljZXJ0LmNvbS9ycGEtdWEwDQYJKoZIhvcNAQELBQADggEBABfg
+eXrxIrtlixBv+KMDeqKxtNJbZiLDzJBkGCd4HI63X5eS6BElJBn6mI9eYVrr7qOL
+Tp7WiO02Sf1Yrpaz/ePSjZ684o89UAGpxOfbgVSMvo/a07n/220jUWLxzaJhQNLu
+lACXwwWsxYf8twP8glkoIHnUUNTlhsyyl1ZzvVC4bDpI4hC6QkJGync1MNqYSMj8
+tZbhQNw3HdSmcTO0Nc/J/pK2VZc6fFbKBgspmzdHc6jMKG2t4lisXEysS3wPcg0a
+Nfr1Odl5+myh3MnMK08f6pTXvduLz+QZiIh8IYL+Z6QWgTZ9e2jnV8juumX1I8Ge
+7cZdtNnTCB8hFfwGLUA=
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh
+MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
+d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD
+QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT
+MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
+b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG
+9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB
+CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97
+nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt
+43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P
+T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4
+gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO
+BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR
+TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw
+DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr
+hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg
+06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF
+PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls
+YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk
+CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=
+-----END CERTIFICATE-----
\ No newline at end of file
diff --git a/projects/nginx/nginx.conf b/projects/nginx/nginx.conf
new file mode 100644
index 00000000..9fb25577
--- /dev/null
+++ b/projects/nginx/nginx.conf
@@ -0,0 +1,103 @@
+#user nobody;
+worker_processes 1;
+
+#error_log logs/error.log;
+#error_log logs/error.log notice;
+#error_log logs/error.log info;
+
+#pid logs/nginx.pid;
+events {
+ worker_connections 1024;
+}
+
+http {
+ include mime.types;
+ default_type application/octet-stream;
+ types {
+ application/vnd.android.package-archive apk;
+ application/iphone pxl ipa;
+ text/plain plist;
+ }
+
+ sendfile on;
+
+ keepalive_timeout 65;
+
+ # Docker DNS
+ #resolver 127.0.0.11;
+
+ upstream go-fastdfs {
+ server 10.10.24.104:8180;
+ ip_hash;
+ }
+
+ server {
+ listen 80;
+ listen 443 ssl;
+ server_name iot.edusoa.com;
+
+ #ssl on;
+ ssl_certificate edusoa.pem;
+ ssl_certificate_key edusoa.key;
+ ssl_session_timeout 5m;
+ ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
+ ssl_ciphers HIGH:!RC4:!MD5:!aNULL:!eNULL:!NULL:!DH:!EDH:!EXP:+MEDIUM;
+ ssl_prefer_server_ciphers on;
+
+ location / {
+ if ($http_user_agent ~* "(mobile|android|ipad|iphone|ipod|tablet)") {
+ proxy_pass http://webspa;
+ break;
+ }
+ proxy_pass http://webmvc/;
+ }
+
+ location ^~ /dfs/ {
+ proxy_set_header Host $host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_pass http://minio/;
+ }
+
+ location ^~ /live/ {
+ proxy_pass http://srs:8080/live/;
+ }
+
+ location ^~ /video/ {
+ proxy_pass http://srs:8080/video/;
+ }
+
+ location ^~ /UserCenter/ {
+ proxy_pass http://usercenter/UserCenter/;
+ proxy_set_header Host $host:$server_port;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header X-Forwarded-Proto $scheme;
+ }
+
+ location ^~ /IoTCenter/ {
+ proxy_pass http://iotcenter/IoTCenter/;
+ proxy_set_header Host $host:$server_port;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header X-Forwarded-Proto $scheme;
+ }
+
+ location ^~ /IoTCenter/hub {
+ proxy_pass http://iotcenter/IoTCenter/hub;
+ proxy_http_version 1.1;
+ proxy_set_header Upgrade $http_upgrade;
+ proxy_set_header Connection "upgrade";
+ }
+
+ location ^~ /JobServer/ {
+ proxy_pass http://jobserver/JobServer/;
+ proxy_set_header Host $host:$server_port;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header X-Forwarded-Proto $scheme;
+ }
+
+ error_page 500 502 503 504 /50x.html;
+ location = /50x.html {
+ root html;
+ }
+ }
+}
\ No newline at end of file
diff --git a/projects/projects.sln b/projects/projects.sln
index 28467211..211cfb7f 100644
--- a/projects/projects.sln
+++ b/projects/projects.sln
@@ -42,6 +42,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WebSPA", "WebSPA\WebSPA.csp
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JobServer", "JobServer\JobServer.csproj", "{6E2766D8-9ECF-469E-8662-A20F673E52CC}"
EndProject
+Project("{E53339B2-1760-4266-BCC7-CA923CBCF16C}") = "docker-compose", "docker-compose.dcproj", "{DB048E66-3411-41F6-86F7-A8F73A9F806A}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -160,6 +162,18 @@ Global
{6E2766D8-9ECF-469E-8662-A20F673E52CC}.Release|iPhone.Build.0 = Release|Any CPU
{6E2766D8-9ECF-469E-8662-A20F673E52CC}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{6E2766D8-9ECF-469E-8662-A20F673E52CC}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {DB048E66-3411-41F6-86F7-A8F73A9F806A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {DB048E66-3411-41F6-86F7-A8F73A9F806A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {DB048E66-3411-41F6-86F7-A8F73A9F806A}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+ {DB048E66-3411-41F6-86F7-A8F73A9F806A}.Debug|iPhone.Build.0 = Debug|Any CPU
+ {DB048E66-3411-41F6-86F7-A8F73A9F806A}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {DB048E66-3411-41F6-86F7-A8F73A9F806A}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {DB048E66-3411-41F6-86F7-A8F73A9F806A}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {DB048E66-3411-41F6-86F7-A8F73A9F806A}.Release|Any CPU.Build.0 = Release|Any CPU
+ {DB048E66-3411-41F6-86F7-A8F73A9F806A}.Release|iPhone.ActiveCfg = Release|Any CPU
+ {DB048E66-3411-41F6-86F7-A8F73A9F806A}.Release|iPhone.Build.0 = Release|Any CPU
+ {DB048E66-3411-41F6-86F7-A8F73A9F806A}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {DB048E66-3411-41F6-86F7-A8F73A9F806A}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -176,7 +190,7 @@ Global
{6E2766D8-9ECF-469E-8662-A20F673E52CC} = {E1681DC3-9AC2-4FF6-B3DE-37EF826E6F8A}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
- SolutionGuid = {0B7095FB-5E70-4EF8-805A-CB4A91AE4B0A}
BuildVersion_StartDate = 2000/1/1
+ SolutionGuid = {0B7095FB-5E70-4EF8-805A-CB4A91AE4B0A}
EndGlobalSection
EndGlobal
diff --git a/projects/srs/conf/srs.conf b/projects/srs/conf/srs.conf
new file mode 100644
index 00000000..6b31ae33
--- /dev/null
+++ b/projects/srs/conf/srs.conf
@@ -0,0 +1,65 @@
+listen 1935;
+max_connections 1000;
+srs_log_tank file;
+srs_log_file ./objs/log/srs.log;
+daemon off;
+http_api {
+ enabled on;
+ listen 1985;
+ raw_api {
+ enabled on;
+ allow_reload on;
+ allow_query on;
+ allow_update on;
+ }
+}
+http_server {
+ enabled on;
+ listen 8080;
+ dir ./objs/nginx/html;
+}
+stats {
+ network 0;
+ disk sda sdb xvda xvdb;
+}
+vhost __defaultVhost__ {
+ transcode live {
+ enabled off;
+ ffmpeg ./objs/ffmpeg/bin/ffmpeg;
+ engine snapshot {
+ enabled on;
+ iformat flv;
+ vfilter {
+ vf fps=1;
+ }
+ vcodec png;
+ vparams {
+ vframes 1;
+ }
+ acodec an;
+ oformat image2;
+ output ./objs/nginx/html/[app]/[stream].png;
+ }
+ }
+ http_remux {
+ enabled on;
+ mount [vhost]/[app]/[stream].flv;
+ }
+ hls {
+ enabled on;
+ hls_fragment 3;
+ hls_window 10;
+ hls_path ./objs/nginx/html;
+ hls_m3u8_file [app]/[stream].m3u8;
+ hls_ts_file [app]/[stream]-[seq].ts;
+ }
+ dvr {
+ enabled on;
+ dvr_apply none;
+ dvr_path ./objs/nginx/html/video/[app].[stream].[timestamp].mp4;
+ }
+ http_hooks {
+ enabled on;
+ on_dvr http://iotcenter/IoTCenter/api/v1/Srs/OnDvr;
+ }
+}