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 _logger; private readonly IConfiguration _configuration; private readonly IHttpContextAccessor _httpContextAccessor; private readonly IHttpClientFactory _httpClientFactory; private readonly IHubContext _pageHubContext; private readonly IRepository _nodeRepo; private readonly IRepository _deviceRepo; private readonly IRepository _senceRepo; public NotifyController(ILogger logger, IConfiguration configuration, IHttpContextAccessor httpContextAccessor, IHttpClientFactory httpClientFactory, IHubContext pageHubContext, IRepository nodeRepository, IRepository deviceReposigory, IRepository 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 Index() { try { var model = this.ReadPostData(); var newDevice = model.FromJson(); 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 { 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(); 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); } } } }