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.
iot/projects/IoTCenter/Controllers/NotifyController.cs

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