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.
304 lines
12 KiB
304 lines
12 KiB
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Net.Http;
|
|
using System.Threading.Tasks;
|
|
using Application.Domain.Entities;
|
|
using Infrastructure.Data;
|
|
using Infrastructure.Extensions;
|
|
using Infrastructure.Web.SignalR;
|
|
using Microsoft.AspNetCore.Http;
|
|
using Microsoft.AspNetCore.Mvc;
|
|
using Microsoft.AspNetCore.SignalR;
|
|
using Microsoft.EntityFrameworkCore;
|
|
using Microsoft.Extensions.Configuration;
|
|
using Microsoft.Extensions.Logging;
|
|
using Vibrant.InfluxDB.Client;
|
|
using Vibrant.InfluxDB.Client.Rows;
|
|
|
|
namespace IoTCenter.Controllers
|
|
{
|
|
public class NotifyController : Controller
|
|
{
|
|
private readonly static object thisLock = new object();
|
|
private readonly ILogger<NotifyController> _logger;
|
|
private readonly IConfiguration _configuration;
|
|
private readonly IHttpContextAccessor _httpContextAccessor;
|
|
private readonly IHttpClientFactory _httpClientFactory;
|
|
private readonly IHubContext<PageHub> _pageHubContext;
|
|
private readonly IRepository<Node> _nodeRepo;
|
|
private readonly IRepository<Device> _deviceRepo;
|
|
private readonly IRepository<Sence> _senceRepo;
|
|
|
|
public NotifyController(ILogger<NotifyController> logger,
|
|
IConfiguration configuration,
|
|
IHttpContextAccessor httpContextAccessor,
|
|
IHttpClientFactory httpClientFactory,
|
|
IHubContext<PageHub> pageHubContext,
|
|
IRepository<Node> nodeRepository,
|
|
IRepository<Device> deviceReposigory,
|
|
IRepository<Sence> senceRepository)
|
|
{
|
|
this._logger = logger;
|
|
this._configuration = configuration;
|
|
this._httpContextAccessor = httpContextAccessor;
|
|
this._httpClientFactory = httpClientFactory;
|
|
this._pageHubContext = pageHubContext;
|
|
this._nodeRepo = nodeRepository;
|
|
this._deviceRepo = deviceReposigory;
|
|
this._senceRepo = senceRepository;
|
|
}
|
|
|
|
public async Task<IActionResult> Index()
|
|
{
|
|
try
|
|
{
|
|
var model = this.ReadPostData();
|
|
var newDevice = model.FromJson<Device>();
|
|
var node = this._nodeRepo.Table().FirstOrDefault(o => o.Number == newDevice.Node.Number);
|
|
if (node != null && node.Id != newDevice.Node.Id)
|
|
{
|
|
this._nodeRepo.Delete(node);
|
|
this._nodeRepo.SaveChanges();
|
|
node = null;
|
|
}
|
|
if (node == null)
|
|
{
|
|
node = new Node();
|
|
this._nodeRepo.Add(node);
|
|
}
|
|
node.FromPlain(newDevice.Node);
|
|
this._nodeRepo.SaveChanges();
|
|
|
|
var device = this._deviceRepo.Table()
|
|
.Include(o => o.Data)
|
|
.Include(o => o.Apis).ThenInclude(o => o.Parameters)
|
|
.FirstOrDefault(o => o.Number == newDevice.Number);
|
|
|
|
if (device != null && device.Id != newDevice.Id)
|
|
{
|
|
this._deviceRepo.Delete(device);
|
|
this._deviceRepo.SaveChanges();
|
|
device = null;
|
|
}
|
|
if (device == null)
|
|
{
|
|
device = new Device();
|
|
this._deviceRepo.Add(device);
|
|
}
|
|
device.FromPlain(newDevice);
|
|
foreach (var id in device.Data.Select(o => o.Id).ToList())
|
|
{
|
|
if (!newDevice.Data.Any(o => o.Id == id))
|
|
{
|
|
var data = device.Data.FirstOrDefault(o => o.Id == id);
|
|
device.Data.Remove(data);
|
|
}
|
|
}
|
|
foreach (var newData in newDevice.Data)
|
|
{
|
|
var data = device.Data.FirstOrDefault(o => o.Key == newData.Key);
|
|
if (data == null)
|
|
{
|
|
data = new Data();
|
|
device.Data.Add(data);
|
|
}
|
|
data.FromPlain(newData);
|
|
}
|
|
|
|
foreach (var command in device.Apis.Select(o => o.Command).ToList())
|
|
{
|
|
if (!newDevice.Apis.Any(o => o.Command == command))
|
|
{
|
|
var api = device.Apis.FirstOrDefault(o => o.Command == command);
|
|
device.Apis.Remove(api);
|
|
}
|
|
}
|
|
foreach (var newApi in newDevice.Apis)
|
|
{
|
|
var api = device.Apis.FirstOrDefault(o => o.Command == newApi.Command);
|
|
if (api == null)
|
|
{
|
|
api = new Api();
|
|
device.Apis.Add(api);
|
|
}
|
|
api.FromPlain(newApi);
|
|
foreach (var name in api.Parameters.Select(o => o.Name).ToList())
|
|
{
|
|
if (!newApi.Parameters.Any(o => o.Name == name))
|
|
{
|
|
var parameter = api.Parameters.FirstOrDefault(o => o.Name == name);
|
|
api.Parameters.Remove(parameter);
|
|
}
|
|
}
|
|
foreach (var newParameter in newApi.Parameters)
|
|
{
|
|
var parameter = api.Parameters.FirstOrDefault(o => o.Name == newParameter.Name);
|
|
if (parameter == null)
|
|
{
|
|
parameter = new Parameter();
|
|
api.Parameters.Add(parameter);
|
|
}
|
|
parameter.FromPlain(newParameter);
|
|
}
|
|
}
|
|
this._deviceRepo.SaveChanges();
|
|
device.Node = node;
|
|
UpdatePage(device);
|
|
await this.LogToInfluxdbAsync(device);
|
|
return new JsonResult("Succeed");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
ex.PrintStack();
|
|
return new JsonResult(ex.Message);
|
|
}
|
|
}
|
|
|
|
private string ReadPostData()
|
|
{
|
|
using (var tr = new StreamReader(Request.Body))
|
|
{
|
|
return tr.ReadToEnd();
|
|
}
|
|
}
|
|
|
|
private void UpdatePage(Device device)
|
|
{
|
|
var data = device.ToJson();
|
|
this._pageHubContext.Clients.Group($"node-{device.Node.Number}").SendAsync("UpdateDevice", data);
|
|
this._pageHubContext.Clients.Group($"device-{device.Number}").SendAsync("UpdateDevice", data);
|
|
this._pageHubContext.Clients.Group("nodes").SendAsync("UpdateDevice", data);
|
|
}
|
|
|
|
private async Task LogToInfluxdbAsync(Device device)
|
|
{
|
|
try
|
|
{
|
|
var url = this._configuration["influxdb:url"];
|
|
var usr = this._configuration["influxdb:usr"];
|
|
var pwd = this._configuration["influxdb:pwd"];
|
|
var dbName = "iot";
|
|
var measurementName = "data";
|
|
using (var client = new InfluxClient(new Uri(url), usr, pwd))
|
|
{
|
|
await client.CreateDatabaseAsync(dbName);
|
|
var row = new DynamicInfluxRow
|
|
{
|
|
Timestamp = DateTime.UtcNow
|
|
};
|
|
row.Fields.Add("NodeNumber", device.Node.Number);
|
|
row.Fields.Add("NodeName", device.Node.Name);
|
|
row.Fields.Add("DeviceNumber", device.Number);
|
|
row.Fields.Add("DeviceName", device.Name);
|
|
foreach (var item in device.Data)
|
|
{
|
|
row.Fields.Add(item.Key, this.GetDataValue(item));
|
|
}
|
|
|
|
await client.WriteAsync(dbName, measurementName, new List<DynamicInfluxRow> { row });
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
ex.PrintStack();
|
|
}
|
|
}
|
|
|
|
private IComparable GetDataValue(Data deviceData)
|
|
{
|
|
if (deviceData.Type == "Int")
|
|
{
|
|
return int.Parse(deviceData.Value);
|
|
}
|
|
else if (deviceData.Type == "Float")
|
|
{
|
|
return double.Parse(deviceData.Value);
|
|
}
|
|
if (deviceData.Type == "DateTime")
|
|
{
|
|
return DateTime.Parse(deviceData.Value);
|
|
}
|
|
else
|
|
{
|
|
return deviceData.Value;
|
|
}
|
|
}
|
|
|
|
public IActionResult Update()
|
|
{
|
|
try
|
|
{
|
|
var model = this.ReadPostData();
|
|
var newNode = model.FromJson<Node>();
|
|
var node = this._nodeRepo.Table().Include(o => o.Sences).Include(o => o.Devices).FirstOrDefault(o => o.Number == newNode.Number);
|
|
if (node != null && node.Id != newNode.Id)
|
|
{
|
|
this._nodeRepo.Delete(node);
|
|
this._nodeRepo.SaveChanges();
|
|
node = null;
|
|
}
|
|
if (node == null)
|
|
{
|
|
node = new Node();
|
|
this._nodeRepo.Add(node);
|
|
}
|
|
node.FromPlain(newNode);
|
|
this._nodeRepo.SaveChanges();
|
|
foreach (var id in node.Sences.Select(o => o.Id).ToList())
|
|
{
|
|
if (!newNode.Sences.Any(o => o.Id == id))
|
|
{
|
|
node.Sences.Remove(node.Sences.FirstOrDefault(o => o.Id == id));
|
|
this._nodeRepo.SaveChanges();
|
|
this._pageHubContext.Clients.Group($"node-{node.Number}").SendAsync("DeleteSence", id.ToString());
|
|
}
|
|
}
|
|
foreach (var newSence in newNode.Sences)
|
|
{
|
|
var sence = node.Sences.FirstOrDefault(o => o.Id == newSence.Id);
|
|
if (sence == null)
|
|
{
|
|
sence = new Sence();
|
|
node.Sences.Add(sence);
|
|
}
|
|
sence.FromPlain(newSence);
|
|
this._nodeRepo.SaveChanges();
|
|
this._pageHubContext.Clients.Group($"node-{node.Number}").SendAsync("UpdateSence", sence.ToJson());
|
|
}
|
|
foreach (var id in node.Devices.Select(o => o.Id).ToList())
|
|
{
|
|
if (!newNode.Devices.Any(o => o.Id == id))
|
|
{
|
|
var device = node.Devices.FirstOrDefault(o => o.Id == id);
|
|
node.Devices.Remove(device);
|
|
this._nodeRepo.SaveChanges();
|
|
this._pageHubContext.Clients.Group($"node-{node.Number}").SendAsync("DeleteDevice", device.Number);
|
|
this._pageHubContext.Clients.Group($"nodes").SendAsync("DeleteDevice", device.Number);
|
|
}
|
|
}
|
|
foreach (var newDevice in newNode.Devices)
|
|
{
|
|
var device = node.Devices.FirstOrDefault(o => o.Id == newDevice.Id);
|
|
if (device == null)
|
|
{
|
|
device = new Device();
|
|
node.Devices.Add(device);
|
|
}
|
|
device.FromPlain(newDevice);
|
|
this._nodeRepo.SaveChanges();
|
|
var data = device.ToJson();
|
|
//this._pageHubContext.Clients.Group($"node-{node.Number}").SendAsync("UpdateDevice", data);
|
|
this._pageHubContext.Clients.Group($"nodes").SendAsync("UpdateDevice", data);
|
|
}
|
|
return new JsonResult("Succeed");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
ex.PrintStack();
|
|
return new JsonResult(ex.Message);
|
|
}
|
|
}
|
|
}
|
|
} |