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; + } +}