using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Http; using System.Net.Sockets; using System.Threading; using System.Threading.Tasks; using System.Web; using Application.Domain.Entities; using Application.Models; using Application.Services; using Infrastructure.Data; using Infrastructure.Extensions; using Infrastructure.Web.SignalR; using Microsoft.AspNetCore.SignalR; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Newtonsoft.Json; namespace IoTNode.Services { public class NodeService : INodeService, IDisposable { private IServiceProvider applicationServices; private CancellationTokenSource _tokenSource; public NodeService(IServiceProvider applicationServices) { this.applicationServices = applicationServices; this._tokenSource = new CancellationTokenSource(); } public bool EditNode(EditNodeModel model) { try { using (var scope = applicationServices.CreateScope()) { var repo = scope.ServiceProvider.GetService>(); var entity = repo.Table().FirstOrDefault(o => o.Id == model.Id); entity.Name = model.Name; if (repo.SaveChanges() > 0) { this.SendToPage(scope, $"node-{entity.Number}", "UpdateNode", entity.ToJson()); } return true; } } catch (Exception ex) { ex.PrintStack(); return false; } } public bool DeleteNode(Guid id) { try { using (var scope = applicationServices.CreateScope()) { var repo = scope.ServiceProvider.GetService>(); var entity = repo.Table().FirstOrDefault(o => o.Id == id); repo.Delete(entity); repo.SaveChanges(); return true; } } catch (Exception ex) { ex.PrintStack(); return false; } } public bool EditDevice(EditDeviceModel model) { try { using (var scope = applicationServices.CreateScope()) { var repo = scope.ServiceProvider.GetService>(); var entity = repo.Table().FirstOrDefault(o => o.Id == model.Id); entity.DisplayName = model.DisplayName; if (repo.SaveChanges() > 0) { var device = repo.ReadOnlyTable() .Include(o => o.Node) .Include(o => o.Data) .Include(o => o.Apis).ThenInclude(o => o.Parameters) .FirstOrDefault(o => o.Id == entity.Id); this.SendToPage(scope, $"node-{device.Node.Number}", "UpdateDevice", device.ToJson()); } return true; } } catch (Exception ex) { ex.PrintStack(); return false; } } public bool DeleteDevice(Guid id) { try { using (var scope = applicationServices.CreateScope()) { var repo = scope.ServiceProvider.GetService>(); var entity = repo.Table().FirstOrDefault(o => o.Id == id); if (entity != null) { var nodeRepo = scope.ServiceProvider.GetService>(); var number = nodeRepo.ReadOnlyTable().FirstOrDefault(o => o.Id == entity.NodeId).Number; repo.Delete(entity); if (repo.SaveChanges() > 0) { this.SendToPage(scope, $"node-{number}", "DeleteDevice", entity.Number); } } return true; } } catch (Exception ex) { ex.PrintStack(); return false; } } public bool CreateSence(EditSenceModel model) { try { using (var scope = applicationServices.CreateScope()) { var repo = scope.ServiceProvider.GetService>(); var entity = new Sence().From(model); repo.Add(entity); if (repo.SaveChanges() > 0) { var nodeRepo = scope.ServiceProvider.GetService>(); var number = nodeRepo.ReadOnlyTable().FirstOrDefault(o => o.Id == entity.NodeId).Number; this.SendToPage(scope, $"node-{number}", "UpdateSence", entity.ToJson()); } return true; } } catch (Exception ex) { ex.PrintStack(); return false; } } public bool EditSence(EditSenceModel model) { try { using (var scope = applicationServices.CreateScope()) { var repo = scope.ServiceProvider.GetService>(); var entity = repo.Table().FirstOrDefault(o => o.Id == model.Id); entity.From(model); if (repo.SaveChanges() > 0) { var nodeRepo = scope.ServiceProvider.GetService>(); var number = nodeRepo.ReadOnlyTable().FirstOrDefault(o => o.Id == entity.NodeId).Number; this.SendToPage(scope, $"node-{number}", "UpdateSence", entity.ToJson()); } return true; } } catch (Exception ex) { ex.PrintStack(); return false; } } public bool DeleteSence(Guid id) { try { using (var scope = applicationServices.CreateScope()) { var repo = scope.ServiceProvider.GetService>(); var entity = repo.Table().FirstOrDefault(o => o.Id == id); if (entity != null) { var nodeRepo = scope.ServiceProvider.GetService>(); var number = nodeRepo.ReadOnlyTable().FirstOrDefault(o => o.Id == entity.NodeId).Number; repo.Delete(entity); if (repo.SaveChanges() > 0) { this.SendToPage(scope, $"node-{number}", "DeleteSence", id.ToString()); } } return true; } } catch (Exception ex) { ex.PrintStack(); return false; } } public bool CreateCommand(EditCommandModel model) { try { using (var scope = applicationServices.CreateScope()) { var repo = scope.ServiceProvider.GetService>(); var entity = new Command().From(model); entity.QueryString = model.GetQueryString(); repo.Add(entity); repo.SaveChanges(); return true; } } catch (Exception ex) { ex.PrintStack(); return false; } } public bool EditCommand(EditCommandModel model) { try { using (var scope = applicationServices.CreateScope()) { var repo = scope.ServiceProvider.GetService>(); var entity = repo.Table().FirstOrDefault(o => o.Id == model.Id); entity.From(model); entity.QueryString = model.GetQueryString(); repo.SaveChanges(); return true; } } catch (Exception ex) { ex.PrintStack(); return false; } } public bool DeleteCommand(Guid id) { try { using (var scope = applicationServices.CreateScope()) { var repo = scope.ServiceProvider.GetService>(); var entity = repo.Table().FirstOrDefault(o => o.Id == id); if (entity != null) { repo.Delete(entity); repo.SaveChanges(); } return true; } } catch (Exception ex) { ex.PrintStack(); return false; } } public ApiResponse Exec(Guid id, string cmd, string query) { try { using (var scope = applicationServices.CreateScope()) { var deviceRepo = scope.ServiceProvider.GetService>(); var device = deviceRepo.ReadOnlyTable().Include(o => o.Apis).Include(o => o.Data).FirstOrDefault(o => o.Id == id); if (device.Name == "主机" && cmd == "21boot") { this.BootStrapPCByMacAddress(device.Number); return ApiResponse.AsyncSuccess(); } var url = $"{device.BaseUrl}/{cmd}{query}"; url = url.SetParam("id", device.Number); if (device.Name == "红外转发器") { var api = device.Apis.FirstOrDefault(o => o.Command == cmd); var keySets = device.Data.FirstOrDefault(o => o.Key == "hidden")?.Value ?? ""; var array = JsonConvert.DeserializeObject>(keySets) ?? new List(); if (cmd == "26add" || cmd == "25update" || cmd == "24delete") { var values = HttpUtility.ParseQueryString(query); if (cmd == "26add") { var code = values.Get("newcode"); var name = values.Get("name"); if (!array.Any(o => o.code == code)) { array.Add(new IrDataModel { code = code, name = name, irType = "00", status = "0", keyset = code }); } } else if (cmd == "25update") { var code = values.Get("code"); var name = values.Get("name"); var item = array.FirstOrDefault(o => o.code == code); if (item != null) { item.name = name; } } else if (cmd == "24delete") { } url = url.SetParam("hidden", array.ToJson()); } } return ExecUrl(scope, url); } } catch (Exception ex) { ex.PrintStack(); return ApiResponse.Error(ex); } } public ApiResponse Sence(Guid id) { try { using (var scope = applicationServices.CreateScope()) { var httpClientFactory = scope.ServiceProvider.GetService(); var senceRepo = scope.ServiceProvider.GetService>(); var sence = senceRepo.ReadOnlyTable() .Include(o => o.Commands) .ThenInclude(o => o.Api) .ThenInclude(o => o.Device) .FirstOrDefault(o => o.Id == id); foreach (var item in sence.Commands) { var device = item.Api.Device; var url = $"{device.BaseUrl}/{item.Api.Command}?id={device.Number}"; if (!string.IsNullOrEmpty(item.QueryString)) { url += $"&{item.QueryString}"; } Console.WriteLine($"start:{url}"); var task = httpClientFactory.CreateClient().GetAsync(url); task.Wait(); using (var response = task.Result) { using (var content = response.Content) { var result = content.ReadAsStringAsync().Result; Console.WriteLine($"end:{url}:{result}"); } } } } return ApiResponse.AsyncSuccess(); } catch (Exception ex) { ex.PrintStack(); return ApiResponse.Error(ex); } } public ApiResponse ExecAll(List id, string cmd, string query) { try { using (var scope = applicationServices.CreateScope()) { foreach (var deviceId in id) { this.Exec(deviceId, cmd, query); } } return ApiResponse.AsyncSuccess(); } catch (Exception ex) { ex.PrintStack(); return ApiResponse.Error(ex); } } private ApiResponse ExecUrl(IServiceScope scope, string url) { Console.WriteLine($"start:{url}"); var httpClientFactory = scope.ServiceProvider.GetService(); var task = httpClientFactory.CreateClient().GetAsync(url); task.Wait(); using (var response = task.Result) { using (var content = response.Content) { var value = content.ReadAsStringAsync().Result; Console.WriteLine($"end:{url}:{value}"); var result = value.FromJson(); return result; } } } private void BootStrapPCByMacAddress(string mac) { var message = ""; for (int i = 0; i < 12; i++) { message += "f"; } for (int i = 0; i < 16; i++) { message += mac; } var data = message.HexToBytes(); using (var client = new UdpClient(new IPEndPoint(Helper.Instance.GetLocalIP(), 0))) { client.Send(data, data.Length, new IPEndPoint(IPAddress.Parse("255.255.255.255"), 9)); } Console.WriteLine("boot"); } private void SendToPage(IServiceScope scope, string group, string method, string data) { try { var hc = scope.ServiceProvider.GetService>(); hc.Clients.Group(group).SendAsync(method, data); } catch (Exception ex) { ex.PrintStack(); } } public void Notify() { try { using (var scope = applicationServices.CreateScope()) { var configuration = scope.ServiceProvider.GetService(); if (configuration.GetValue("notify:enabled")) { var schoolUrl = $"http://{configuration["notify:host"]}/Notify/Update"; var nodeRepo = scope.ServiceProvider.GetService>(); var node = nodeRepo.ReadOnlyTable().Include(o => o.Sences).Include(o => o.Devices).FirstOrDefault(); var data = node.ToJson(); var httpClientFactory = scope.ServiceProvider.GetService(); var task = httpClientFactory.CreateClient().PostAsync(schoolUrl, new StringContent(data)); task.Wait(); using (var response = task.Result) { using (var content = response.Content) { var result = content.ReadAsStringAsync().Result; Console.WriteLine($"server response:{schoolUrl}:{result}"); } } } } } catch (Exception ex) { ex.PrintStack(); } } public void Start() { Task.Run(async () => { while (!_tokenSource.IsCancellationRequested) { try { Console.WriteLine("send data to iot center..."); Notify(); } catch (Exception ex) { ex.PrintStack(); } await Task.Delay(5 * 60 * 1000); } }); } public void Dispose() { this._tokenSource.Cancel(); } } }