You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
408 lines
16 KiB
408 lines
16 KiB
using Application.Domain.Entities;
|
|
using Application.Models;
|
|
using Infrastructure.Data;
|
|
using Infrastructure.Extensions;
|
|
using Infrastructure.Jwt;
|
|
using Infrastructure.Web;
|
|
using IoTCenter.Services;
|
|
using Microsoft.AspNetCore.Authorization;
|
|
using Microsoft.AspNetCore.Mvc;
|
|
using Microsoft.AspNetCore.SignalR;
|
|
using Microsoft.EntityFrameworkCore;
|
|
using Microsoft.Extensions.Configuration;
|
|
using Microsoft.Extensions.Hosting;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using Vibrant.InfluxDB.Client;
|
|
using Vibrant.InfluxDB.Client.Rows;
|
|
|
|
namespace IoTCenter.Controllers
|
|
{
|
|
[Device]
|
|
public class AppController : Controller
|
|
{
|
|
private readonly IHostEnvironment _env;
|
|
private readonly IConfiguration _configuration;
|
|
private readonly IJwtHelper _jwtHelper;
|
|
private readonly IRepository<Category> _categoryRepo;
|
|
private readonly IRepository<Product> _productRepo;
|
|
private readonly IRepository<Node> _nodeRepo;
|
|
private readonly IRepository<Scene> _sceneRepo;
|
|
private readonly IRepository<SceneCommand> _sceneCommandRepo;
|
|
private readonly IRepository<Command> _commandRepo;
|
|
private readonly IRepository<Device> _deviceRepo;
|
|
private readonly IRepository<LiveRecord> _liveRecordRepo;
|
|
private readonly IHubContext<IoTCenterHub> _hub;
|
|
|
|
public AppController(
|
|
IHostEnvironment env,
|
|
IConfiguration configuration,
|
|
IJwtHelper jwtHelper,
|
|
IRepository<Category> categoryRepo,
|
|
IRepository<Product> productRepo,
|
|
IRepository<Node> nodeRepo,
|
|
IRepository<Scene> sceneRepo,
|
|
IRepository<SceneCommand> sceneCommandRepo,
|
|
IRepository<Command> commandRepo,
|
|
IRepository<Device> deviceRepo,
|
|
IRepository<LiveRecord> liveRecordRepo,
|
|
IHubContext<IoTCenterHub> hub)
|
|
{
|
|
this._env = env;
|
|
this._configuration = configuration;
|
|
this._jwtHelper = jwtHelper;
|
|
this._categoryRepo = categoryRepo;
|
|
this._productRepo = productRepo;
|
|
this._nodeRepo = nodeRepo;
|
|
this._sceneRepo = sceneRepo;
|
|
this._sceneCommandRepo = sceneCommandRepo;
|
|
this._commandRepo = commandRepo;
|
|
this._deviceRepo = deviceRepo;
|
|
this._liveRecordRepo = liveRecordRepo;
|
|
this._hub = hub;
|
|
}
|
|
|
|
[Authorize]
|
|
public IActionResult Index()
|
|
{
|
|
return View();
|
|
}
|
|
|
|
public IActionResult GetProducts(string token)
|
|
{
|
|
var userName = this._jwtHelper.GetPayload(token)["UserName"].ToString();
|
|
var model = this._productRepo.ReadOnlyTable().Select(o => new
|
|
{
|
|
o.Id,
|
|
o.Number,
|
|
o.Name,
|
|
o.Image,
|
|
DeviceCount = o.Devices.Count()
|
|
}).ToList();
|
|
return Json(model);
|
|
}
|
|
|
|
public IActionResult GetNodes(string token)
|
|
{
|
|
var userName = this._jwtHelper.GetPayload(token)["UserName"].ToString();
|
|
var model = this._nodeRepo.ReadOnlyTable()
|
|
.Include(o => o.Scenes)
|
|
.OrderBy(o => o.DisplayOrder)
|
|
.ThenBy(o => o.Name)
|
|
.Select(o => new
|
|
{
|
|
o.Id,
|
|
o.Number,
|
|
o.Name,
|
|
o.Image,
|
|
o.DisplayOrder,
|
|
o.Scenes,
|
|
DeviceCount = o.Devices.Count
|
|
})
|
|
.ToList();
|
|
return Json(model);
|
|
}
|
|
|
|
public IActionResult GetNode(string token, string number)
|
|
{
|
|
var userName = this._jwtHelper.GetPayload(token)["UserName"].ToString();
|
|
var model = this._nodeRepo.ReadOnlyTable()
|
|
.Include(o => o.Scenes)
|
|
.Include(o => o.Devices)
|
|
.ThenInclude(o => o.Data)
|
|
.Include(o => o.Devices)
|
|
.ThenInclude(o => o.Commands)
|
|
.FirstOrDefault(o => o.Number == number);
|
|
return Json(model);
|
|
}
|
|
|
|
public IActionResult GetTemplate(string template)
|
|
{
|
|
return Content(System.IO.File.ReadAllText(Path.Combine(this._env.ContentRootPath, "wwwroot", template)));
|
|
}
|
|
|
|
//
|
|
public IActionResult GetSceneList(string token)
|
|
{
|
|
var userName = this._jwtHelper.GetPayload(token)["UserName"].ToString();
|
|
var model = this._sceneRepo.ReadOnlyTable()
|
|
.Where(o => o.NodeId == null)
|
|
.ToList();
|
|
return Json(model);
|
|
}
|
|
|
|
public IActionResult GetDevice(string token, string number)
|
|
{
|
|
var userName = this._jwtHelper.GetPayload(token)["UserName"].ToString();
|
|
var model = this._deviceRepo.ReadOnlyTable()
|
|
.Include(o => o.Data)
|
|
.FirstOrDefault(o => o.Number == number);
|
|
return Json(model);
|
|
}
|
|
|
|
[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1031:不捕获常规异常类型", Justification = "<挂起>")]
|
|
public IActionResult ExecApi(CallApiRequest request)
|
|
{
|
|
try
|
|
{
|
|
var device = this._deviceRepo.ReadOnlyTable().Include(o => o.Node).FirstOrDefault(o => o.Number == request.Number);
|
|
if (device != null)
|
|
{
|
|
var query = string.Empty;
|
|
var parameters = Request.Method.ToUpper() == "GET" ? Request.Query.ToArray() : Request.Form.ToArray();
|
|
foreach (var item in parameters.Where(o => o.Key != "ConnectionId" && o.Key != "Method"))
|
|
{
|
|
query = query.SetParam(item.Key, item.Value);
|
|
}
|
|
|
|
var message = $"{request.Method}{query}";
|
|
this._hub.Clients.Group(device.Node.Number).SendAsync(Methods.ServerToClient, Methods.ExecApi, message, request.ConnectionId);
|
|
}
|
|
return Json(ApiResponse.AsyncSuccess());
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
ex.PrintStack();
|
|
return Json(ApiResponse.Error(ex));
|
|
}
|
|
}
|
|
|
|
[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1031:不捕获常规异常类型", Justification = "<挂起>")]
|
|
public IActionResult ExecApiAll(string connectionId, string node, string cmd, List<Guid> id)
|
|
{
|
|
try
|
|
{
|
|
var query = string.Empty;
|
|
foreach (var item in Request.Query.Where(o => o.Key != "node" && o.Key != "cmd" && !o.Key.StartsWith("id[")))
|
|
{
|
|
query = query.SetParam(item.Key, item.Value);
|
|
}
|
|
//this._pageHubContext.Clients.Group(node).SendAsync(nameof(INodeService.ExecAll), connectionId, id, cmd, query);
|
|
return Json(ApiResponse.AsyncSuccess());
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
ex.PrintStack();
|
|
return Json(ApiResponse.Error(ex));
|
|
}
|
|
}
|
|
|
|
[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1031:不捕获常规异常类型", Justification = "<挂起>")]
|
|
public IActionResult ExecScene(string connectionId, Guid id)
|
|
{
|
|
try
|
|
{
|
|
var scene = this._sceneRepo.ReadOnlyTable().Include(o => o.Node).FirstOrDefault(o => o.Id == id);
|
|
this._hub.ServerToClient(scene.Node.Number, Methods.ExecScene, id, connectionId);
|
|
return Json(ApiResponse.AsyncSuccess());
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
ex.PrintStack();
|
|
return Json(ApiResponse.Error(ex));
|
|
}
|
|
}
|
|
|
|
[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1031:不捕获常规异常类型", Justification = "<挂起>")]
|
|
public IActionResult ExecGlobalScene(string connectionId, Guid id)
|
|
{
|
|
try
|
|
{
|
|
var commands = this._sceneCommandRepo.ReadOnlyTable()
|
|
.Include(o => o.Command).ThenInclude(o => o.Device).ThenInclude(o => o.Node)
|
|
.Where(o => o.SceneId == id)
|
|
.Select(o => o.Command)
|
|
.ToList();
|
|
foreach (var command in commands)
|
|
{
|
|
try
|
|
{
|
|
this._hub.ServerToClient(command.Device.Node.Number, Methods.ExecCommand, command.Id, connectionId);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
ex.PrintStack();
|
|
}
|
|
}
|
|
return Json(ApiResponse.AsyncSuccess());
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
ex.PrintStack();
|
|
return Json(ApiResponse.Error(ex));
|
|
}
|
|
}
|
|
|
|
[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1031:不捕获常规异常类型", Justification = "<挂起>")]
|
|
public IActionResult ExecCommand(string connectionId, Guid id)
|
|
{
|
|
try
|
|
{
|
|
var command = this._commandRepo.ReadOnlyTable().Include(o => o.Device).ThenInclude(o => o.Node).FirstOrDefault(o => o.Id == id);
|
|
this._hub.ServerToClient(command.Device.Node.Number, Methods.ExecCommand, command.Id, connectionId);
|
|
return Json(ApiResponse.AsyncSuccess());
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
ex.PrintStack();
|
|
return Json(ApiResponse.Error(ex));
|
|
}
|
|
}
|
|
|
|
public IActionResult Data(Guid id, string time = "10m")
|
|
{
|
|
var device = this._deviceRepo.ReadOnlyTable().Include(o => o.Node).Include(o => o.Data).FirstOrDefault(o => o.Id == id);
|
|
var url = this._configuration["influxdb:url"];
|
|
var usr = this._configuration["influxdb:usr"];
|
|
var pwd = this._configuration["influxdb:pwd"];
|
|
var dbName = "iot";
|
|
var measurementName = "data";
|
|
var list = new List<object>();
|
|
using (var client = new InfluxClient(new Uri(url), usr, pwd))
|
|
{
|
|
var fileds = String.Join(',', device.Data
|
|
.Where(o => o.Type == DeviceDataType.Int || o.Type == DeviceDataType.Float)
|
|
.Select(o => o.Key));
|
|
var query = $"select {fileds} from {measurementName} where time>now()-{time} and DeviceNumber = '{device.Number}' limit 10000";
|
|
var result = client.ReadAsync<DynamicInfluxRow>(dbName, query).Result;
|
|
var rows = result.Results.FirstOrDefault()?
|
|
.Series.FirstOrDefault()?
|
|
.Rows;
|
|
var labels = rows?.Select(o => o.Timestamp.Value).Select(o => o.ToString("MM-dd HH:mm:ss")).ToList() ?? new List<string>();
|
|
foreach (var data in device.Data.Where(o => o.Type == DeviceDataType.Int || o.Type == DeviceDataType.Float))
|
|
{
|
|
list.Add(new
|
|
{
|
|
id = data.Key,
|
|
label = data.Name,
|
|
labels,
|
|
data = rows?.Select(o => o.GetField(data.Key)).ToList() ?? new List<object>()
|
|
});
|
|
}
|
|
}
|
|
return Json(list);
|
|
}
|
|
|
|
public IActionResult AllPowerOn(string connectionId, string[] nodes)
|
|
{
|
|
this.Power(connectionId, nodes, "On", o => o.Name.Contains("开关") || o.Name.Contains("插座"));
|
|
return Json(ApiResponse.AsyncSuccess());
|
|
}
|
|
|
|
public IActionResult AllPowerOff(string connectionId, string[] nodes)
|
|
{
|
|
this.Power(connectionId, nodes, "Off", o => o.Name.Contains("开关") || o.Name.Contains("插座"));
|
|
return Json(ApiResponse.AsyncSuccess());
|
|
}
|
|
|
|
public IActionResult AllSwitchOn(string connectionId, string[] nodes)
|
|
{
|
|
this.Power(connectionId, nodes, "On", o => o.Name.Contains("一路开关"));
|
|
return Json(ApiResponse.AsyncSuccess());
|
|
}
|
|
|
|
public IActionResult AllSwitchOff(string connectionId, string[] nodes)
|
|
{
|
|
this.Power(connectionId, nodes, "Off", o => o.Name.Contains("一路开关"));
|
|
return Json(ApiResponse.AsyncSuccess());
|
|
}
|
|
|
|
public IActionResult AllSwitch3On(string connectionId, string[] nodes)
|
|
{
|
|
this.Power(connectionId, nodes, "On", o => o.Name.Contains("三路开关"));
|
|
return Json(ApiResponse.AsyncSuccess());
|
|
}
|
|
|
|
public IActionResult AllSwitch3Off(string connectionId, string[] nodes)
|
|
{
|
|
this.Power(connectionId, nodes, "Off", o => o.Name.Contains("三路开关"));
|
|
return Json(ApiResponse.AsyncSuccess());
|
|
}
|
|
|
|
public IActionResult AllSocketOn(string connectionId, string[] nodes)
|
|
{
|
|
this.Power(connectionId, nodes, "On", o => o.Name.Contains("插座"));
|
|
return Json(ApiResponse.AsyncSuccess());
|
|
}
|
|
|
|
public IActionResult AllSocketOff(string connectionId, string[] nodes)
|
|
{
|
|
this.Power(connectionId, nodes, "Off", o => o.Name.Contains("插座"));
|
|
return Json(ApiResponse.AsyncSuccess());
|
|
}
|
|
|
|
public IActionResult NodePowerOn(string connectionId, string node)
|
|
{
|
|
this.Power(connectionId, new string[] { node }, "On", o => o.Name.Contains("开关") || o.Name.Contains("插座"));
|
|
return Json(ApiResponse.AsyncSuccess());
|
|
}
|
|
|
|
public IActionResult NodePowerOff(string connectionId, string node)
|
|
{
|
|
this.Power(connectionId, new string[] { node }, "Off", o => o.Name.Contains("开关") || o.Name.Contains("插座"));
|
|
return Json(ApiResponse.AsyncSuccess());
|
|
}
|
|
|
|
public IActionResult NodeSwitchOn(string connectionId, string node)
|
|
{
|
|
this.Power(connectionId, new string[] { node }, "On", o => o.Name.Contains("一路开关"));
|
|
return Json(ApiResponse.AsyncSuccess());
|
|
}
|
|
|
|
public IActionResult NodeSwitchOff(string connectionId, string node)
|
|
{
|
|
this.Power(connectionId, new string[] { node }, "Off", o => o.Name.Contains("一路开关"));
|
|
return Json(ApiResponse.AsyncSuccess());
|
|
}
|
|
|
|
public IActionResult NodeSwitch3On(string connectionId, string node)
|
|
{
|
|
this.Power(connectionId, new string[] { node }, "On", o => o.Name.Contains("三路开关"));
|
|
return Json(ApiResponse.AsyncSuccess());
|
|
}
|
|
|
|
public IActionResult NodeSwitch3Off(string connectionId, string node)
|
|
{
|
|
this.Power(connectionId, new string[] { node }, "Off", o => o.Name.Contains("三路开关"));
|
|
return Json(ApiResponse.AsyncSuccess());
|
|
}
|
|
|
|
public IActionResult NodeSocketOn(string connectionId, string node)
|
|
{
|
|
this.Power(connectionId, new string[] { node }, "On", o => o.Name.Contains("插座"));
|
|
return Json(ApiResponse.AsyncSuccess());
|
|
}
|
|
|
|
public IActionResult NodeSocketOff(string connectionId, string node)
|
|
{
|
|
this.Power(connectionId, new string[] { node }, "Off", o => o.Name.Contains("插座"));
|
|
return Json(ApiResponse.AsyncSuccess());
|
|
}
|
|
|
|
[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1031:不捕获常规异常类型", Justification = "<挂起>")]
|
|
private void Power(string connectionId, string[] nodes, string command, Func<Device, bool> func)
|
|
{
|
|
var devices = this._deviceRepo.ReadOnlyTable()
|
|
.Include(o => o.Node)
|
|
.Include(o => o.Product.Apis)
|
|
.Where(o => nodes.Contains(o.Node.Number))
|
|
.Where(func)
|
|
.ToList();
|
|
foreach (var device in devices)
|
|
{
|
|
try
|
|
{
|
|
var api = device.Product.Apis.FirstOrDefault(o => o.Command == command);
|
|
var message = $"{api.Path}{api.Command}?number={device.Number}";
|
|
this._hub.Clients.Group(device.Node.Number).SendAsync(Methods.ServerToClient, Methods.ExecApi, message, connectionId);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
ex.PrintStack();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} |