using Application.Domain.Entities; using Infrastructure.Application.Services.Settings; using Infrastructure.Data; using Infrastructure.Events; using Infrastructure.Extensions; using IoT.Shared.Application.Models; using IoT.Shared.Services; using Microsoft.AspNetCore.Hosting; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using NJsonSchema; using System; using System.ComponentModel.DataAnnotations; using System.Globalization; using System.Linq; using System.Net.Http; using System.Threading; using System.Threading.Tasks; namespace IoTNode.DeviceServices { public class BaseDeviceService : IHostedService { internal readonly IServiceProvider _applicationServices; protected readonly IWebHostEnvironment _env; public BaseDeviceService(IServiceProvider applicationServices, IWebHostEnvironment env) { this._applicationServices = applicationServices; this._env = env; } protected string GetSetting(string name) { using var scope = _applicationServices.CreateScope(); return scope.ServiceProvider.GetRequiredService().GetSetting(name).Value; } public virtual Task StartAsync(CancellationToken cancellationToken) { Task.Run(async () => { while (!cancellationToken.IsCancellationRequested) { try { Execute(); } catch (Exception ex) { ex.PrintStack(); } await Task.Delay(Convert.ToInt32(GetSetting("timer.seconds")) * 1000).ConfigureAwait(true); } },cancellationToken); return Task.CompletedTask; } public virtual void Execute() { } public virtual Task StopAsync(CancellationToken cancellationToken) { return Task.CompletedTask; } public IoTProduct UpdateProduct(string productName, string productNumber, string path, string productIcon) { var scope = _applicationServices.CreateScope(); // var productRepo = scope.ServiceProvider.GetService>(); var product = productRepo.ReadOnlyTable().FirstOrDefault(o => o.Number == productNumber); if (product == null) { product = new IoTProduct { Id = $"productid-{productNumber}".ToGuid(), Number = productNumber, Name = productName, Path = path, Image = $"/images/{productIcon}.svg", Template = productIcon }; if (!string.IsNullOrEmpty(path)) { var iotNodeClient = scope.ServiceProvider.GetService(); product.ApiJson = iotNodeClient.GetApiJson(path); //OpenApiService.UpdateApi(product); } productRepo.Add(product); productRepo.SaveChanges(); } // if (this.GetSetting("notify:enabled") == "true") { try { var settingRepo = scope.ServiceProvider.GetRequiredService(); var factory = scope.ServiceProvider.GetRequiredService(); var notifyHost = settingRepo.GetValue("notify:host"); var url = $"{notifyHost}/Server/HasProduct/{productNumber}"; var httpClient = factory.CreateClient(); var response = httpClient.GetStringAsync(url).Result.FromJson(); if (!response) { scope.ServiceProvider.GetRequiredService().ClientToServer($"{nameof(IoTProduct)}{nameof(EntityUpdated)}", product, null); } } catch (Exception ex) { ex.PrintStack(); scope.ServiceProvider.GetRequiredService>().LogError(ex.ToString()); } } return product; } public void DeleteDevice(Guid id) { using var scope = _applicationServices.CreateScope(); var repo = scope.ServiceProvider.GetRequiredService>(); var entity = repo.Table().FirstOrDefault(o => o.Id == id); if (entity != null) { repo.Delete(entity); repo.SaveChanges(); } } public Guid? GetIoTDeviceId(string number) { using var scope = _applicationServices.CreateScope(); var repo = scope.ServiceProvider.GetRequiredService>(); return repo.ReadOnlyTable() .Where(o => o.Number == number) .Select(o => o.Id) .FirstOrDefault(); } public IoTDevice GetIoTDevice(string number) { using var scope = _applicationServices.CreateScope(); var repo = scope.ServiceProvider.GetRequiredService>(); return repo.ReadOnlyTable().FirstOrDefault(o => o.Number == number); } public string GetIoTDataValue(Guid deviceId, DataKeys key) { using var scope = _applicationServices.CreateScope(); var repo = scope.ServiceProvider.GetRequiredService>(); var name = key.GetName(); return repo.ReadOnlyTable() .Where(o => o.IoTDeviceId == deviceId && o.Key == name) .Select(o => o.Value) .FirstOrDefault(); } public void AddIoTData(Guid deviceId, DataKeys key, object value, string description = "", string name = null,string unit=null) { using var scope = _applicationServices.CreateScope(); var repo = scope.ServiceProvider.GetRequiredService>(); var keyValue = key.GetName(); var data = repo.Table().FirstOrDefault(o => o.IoTDeviceId == deviceId && o.Key == keyValue); if (data == null) { data = this.CreateIoTData(deviceId, key, value, description,name,unit); repo.Add(data); this.UpdateIoTDataValue(data, value); repo.SaveChanges(); } } public IoTData UpdateIoTData(Guid deviceId, DataKeys key, object value, string description = "",string name=null, string unit = null) { using var scope = _applicationServices.CreateScope(); var repo = scope.ServiceProvider.GetRequiredService>(); var keyValue = key.GetName(); var data = repo.Table().FirstOrDefault(o => o.IoTDeviceId == deviceId && o.Key == keyValue); if (data == null) { data = this.CreateIoTData(deviceId, key, value, description,name,unit); repo.Add(data); } else { var model = this.CreateIoTData(deviceId, key, value, description,name,unit); data.FromDto(model); } this.UpdateIoTDataValue(data, value); repo.SaveChanges(); return data; } private void UpdateIoTDataValue(IoTData data, object value) { if (data.ValueType == IoTValueType.Int) { data.IntValue = Convert.ToInt32(value); data.Value = data.IntValue.ToString(); } else if (data.ValueType == IoTValueType.Double) { data.DoubleValue = Convert.ToDouble(value); data.Value = data.DoubleValue.Value.ToString("f2"); } else if (data.ValueType == IoTValueType.DateTime) { var timestamp = Convert.ToInt64(value, CultureInfo.InvariantCulture); data.DateTimeValue = DateTimeOffset.FromUnixTimeMilliseconds(timestamp).DateTime; data.Value = Convert.ToString(value); } else if (data.ValueType == IoTValueType.Object) { data.Value = value.ToJson(); data.ValueSchema = JsonSchema.FromType(value.GetType()).ToJson(); } else if (data.ValueType == IoTValueType.Array) { data.Value = value.ToJson(); data.ValueSchema = JsonSchema.FromType(value.GetType().GetGenericArguments().First()).ToJson(); } else { data.Value = Convert.ToString(value); } } private IoTData CreateIoTData(Guid deviceId, DataKeys key, object value, string description = "",string name=null,string unit=null) { var config = key.GetAttribute() ?? new IoTDataConfigAttribute(); var data = new IoTData { IoTDeviceId = deviceId, Key = key.GetName(), DataType = config.PropType, ValueType = config.ValueType, Name = name??key.GetDisplayName(), Unit = unit ?? config.Unit, Description = description, EnumValues = config.GetEnumValues(), Timestamp = DateTimeOffset.Now.ToUnixTimeMilliseconds(), Hidden = config.Hide }; return data; } } }