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/IoTNode/DeviceServices/BaseDeviceService.cs

250 lines
9.7 KiB

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<ISettingService>().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<IRepository<IoTProduct>>();
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<IoTNodeClient>();
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<ISettingService>();
var factory = scope.ServiceProvider.GetRequiredService<IHttpClientFactory>();
var notifyHost = settingRepo.GetValue("notify:host");
var url = $"{notifyHost}/Server/HasProduct/{productNumber}";
var httpClient = factory.CreateClient();
var response = httpClient.GetStringAsync(url).Result.FromJson<bool>();
if (!response)
{
scope.ServiceProvider.GetRequiredService<IoTNodeClient>().ClientToServer($"{nameof(IoTProduct)}{nameof(EntityUpdated<IoTProduct>)}", product, null);
}
}
catch (Exception ex)
{
ex.PrintStack();
scope.ServiceProvider.GetRequiredService<ILogger<BaseDeviceService>>().LogError(ex.ToString());
}
}
return product;
}
public void DeleteDevice(Guid id)
{
using var scope = _applicationServices.CreateScope();
var repo = scope.ServiceProvider.GetRequiredService<IRepository<IoTDevice>>();
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<IRepository<IoTDevice>>();
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<IRepository<IoTDevice>>();
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<IRepository<IoTData>>();
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<IRepository<IoTData>>();
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<IRepository<IoTData>>();
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<IoTDataConfigAttribute>() ?? 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;
}
}
}