Former-commit-id: ffdd571ebce4f1e34e4ed39cbf57f493cc08bc8e
TangShanKaiPing
wanggang 5 years ago
parent 54708e5680
commit 2e5da57423

@ -1 +1,9 @@
.vs
.vs
bin
obj
log
portainer
mysql
influxdb
srs/objs

@ -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);
}

@ -20,6 +20,9 @@ namespace Application.Domain.Entities
[Display(Name = "隐藏")]
public bool Disabled { get; set; }
[Display(Name = "延迟")]
public int Delay { get; set; }
/// <summary>
/// 参数
/// </summary>

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

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

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

@ -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)
{

@ -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<Command> 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<IHttpClientFactory>().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<ISettingService>();
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);
}
}
}
}

@ -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<ApiController> _logger;
private readonly IRepository<Scene> _sceneRepo;
private readonly IRepository<SceneCommand> _sceneCommandRepo;
private readonly IRepository<SceneTimer> _sceneTimerRepo;
private readonly IRepository<Command> _commandRepo;
private readonly IRepository<Device> _deviceRepo;
private readonly IRepository<SceneTimer> _sceneTimerRepo;
private readonly IHubContext<IoTCenterHub> _hub;
public ApiController(
ISettingService settingService,
ILogger<ApiController> logger,
IRepository<Scene> sceneRepo,
IRepository<SceneCommand> sceneCommandRepo,
IRepository<SceneTimer> sceneTimerRepo,
IRepository<Command> commandRepo,
IRepository<Device> deviceRepo,
IRepository<SceneTimer> sceneTimerRepo,
IHubContext<IoTCenterHub> 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);
}
}
/// <summary>
/// job server call back
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
[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);
}
}
}
}

@ -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<NodeController> _logger;
private readonly ISettingService _settingService;
private readonly IRepository<Node> _nodeRepo;
private readonly IRepository<Device> _deviceRepo;
private readonly IHubContext<IoTCenterHub> _hub;
public NodeController(IRepository<Node> nodeRepo,
public NodeController(
ILogger<NodeController> logger,
ISettingService settingService,
IRepository<Node> nodeRepo,
IRepository<Device> deviceRepo,
IHubContext<IoTCenterHub> 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);
}
}
}
}

@ -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<NodeCategory>().Add(new NodeCategory { Name = "智慧教室", Template = "node" });

@ -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"]

@ -5,10 +5,15 @@
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<Deterministic>false</Deterministic>
<DockerComposeProjectPath>..\docker-compose.dcproj</DockerComposeProjectPath>
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
</PropertyGroup>
<ItemGroup>
<Compile Include="..\Version.cs" Link="Version.cs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.10.9" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Infrastructure\Infrastructure.csproj" />
<ProjectReference Include="..\IoT.Shared\IoT.Shared.csproj" />

@ -22,6 +22,12 @@
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "http://localhost:8011"
},
"Docker": {
"commandName": "Docker",
"launchBrowser": true,
"launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}",
"publishAllPorts": true
}
}
}

@ -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<EntityInsertedEvent<Organ>>,
IEventHander<EntityUpdatedEvent<Organ>>,
IEventHander<EntityInsertedEvent<SceneTimer>>,
IEventHander<EntityUpdatedEvent<SceneTimer>>,
IEventHander<EntityDeletedEvent<SceneTimer>>,
@ -48,6 +52,7 @@ namespace IoTCenter.Services
IEventHander<NodeClientConnectedEvent>
{
private readonly IConfiguration _cfg;
private readonly ISettingService _settingService;
private readonly ILogger<IoTCenterEventHandler> _logger;
private readonly IRepository<Node> _nodeRepo;
private readonly IRepository<Organ> _organRepo;
@ -60,6 +65,7 @@ namespace IoTCenter.Services
private readonly IHttpClientFactory _httpClientFactory;
public IoTCenterEventHandler(IConfiguration cfg,
ISettingService settingService,
ILogger<IoTCenterEventHandler> logger,
IRepository<Node> nodeRepo,
IRepository<Organ> 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<Node> message)
{
this.Notify(message);
this.UpdateOrganNode(message.Data);
}
public void Handle(EntityUpdatedEvent<Node> message)
{
this.Notify(message);
this.UpdateOrganNode(message.Data);
}
public void Handle(EntityDeletedEvent<Node> message)
@ -168,6 +177,22 @@ namespace IoTCenter.Services
#endregion Node
#region organ
public void Handle(EntityInsertedEvent<Organ> message)
{
this.Notify(message);
this.UpdateOrganNode(message.Data);
}
public void Handle(EntityUpdatedEvent<Organ> message)
{
this.Notify(message);
this.UpdateOrganNode(message.Data);
}
#endregion organ
#region Device
public void Handle(EntityInsertedEvent<Device> 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());
}
}
}
}

@ -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,

@ -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<Node>().Add(new Node
{
Id = $"nodeid-{sn}".ToGuid(),
OrganName = "默认机构名称",
OrganNumber = "默认机构编码",
Name = "节点",
Number = sn,
IsOnline = true,

@ -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,

@ -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"]

@ -6,6 +6,8 @@
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<Deterministic>false</Deterministic>
<DockerComposeProjectPath>..\docker-compose.dcproj</DockerComposeProjectPath>
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
</PropertyGroup>
<ItemGroup>
@ -16,6 +18,7 @@
<PackageReference Include="Hangfire.AspNetCore" Version="1.7.11" />
<PackageReference Include="Hangfire.Dashboard.BasicAuthorization" Version="1.0.2" />
<PackageReference Include="Hangfire.MySqlStorage" Version="2.0.2" />
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.10.9" />
<PackageReference Include="Serilog.Extensions.Logging" Version="3.0.1" />
<PackageReference Include="Serilog.Settings.Configuration" Version="3.1.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="3.1.1" />

@ -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
}
}
}

@ -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"]
ENTRYPOINT ["dotnet", "UserCenter.dll"]

@ -6,6 +6,7 @@
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<Deterministic>false</Deterministic>
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
<DockerComposeProjectPath>..\docker-compose.dcproj</DockerComposeProjectPath>
</PropertyGroup>
<ItemGroup>
<Compile Include="..\Version.cs" Link="Version.cs" />

@ -1,4 +1,4 @@
using System.Reflection;
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0.515")]
[assembly: AssemblyInformationalVersion("1.0.0.521")]

@ -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"]

@ -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
}
}
}

@ -3,9 +3,12 @@
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<SatelliteResourceLanguages>en</SatelliteResourceLanguages>
<DockerComposeProjectPath>..\docker-compose.dcproj</DockerComposeProjectPath>
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.SpaServices.Extensions" Version="3.1.4" />
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.10.9" />
</ItemGroup>
</Project>

@ -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"]

@ -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
}
}
}

@ -3,9 +3,12 @@
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<SatelliteResourceLanguages>en</SatelliteResourceLanguages>
<DockerComposeProjectPath>..\docker-compose.dcproj</DockerComposeProjectPath>
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.SpaServices.Extensions" Version="3.1.4" />
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.10.9" />
</ItemGroup>
</Project>

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" Sdk="Microsoft.Docker.Sdk">
<PropertyGroup Label="Globals">
<ProjectVersion>2.1</ProjectVersion>
<DockerTargetOS>Linux</DockerTargetOS>
<ProjectGuid>db048e66-3411-41f6-86f7-a8f73a9f806a</ProjectGuid>
<DockerLaunchAction>LaunchBrowser</DockerLaunchAction>
<DockerServiceUrl>{Scheme}://localhost:{ServicePort}</DockerServiceUrl>
<DockerServiceName>webmvc</DockerServiceName>
</PropertyGroup>
<ItemGroup>
<None Include="docker-compose.override.yml">
<DependentUpon>docker-compose.yml</DependentUpon>
</None>
<None Include="docker-compose.yml" />
<None Include=".dockerignore" />
</ItemGroup>
</Project>

@ -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"

@ -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

@ -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-----

@ -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-----

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

@ -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

@ -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;
}
}
Loading…
Cancel
Save