using System; using System.Collections.Generic; using System.Linq; using System.Net.Http; using System.Net.Sockets; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using Application.Domain.Entities; using Infrastructure.Data; using Infrastructure.Extensions; using Infrastructure.Models; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Polly; using RJCP.IO.Ports; namespace LiChuangService { public class DeviceService2 : IDisposable { private readonly IHostingEnvironment _env; private readonly IConfiguration _configuration; private readonly IHttpClientFactory _httpClientFactory; private readonly IServiceProvider _applicationServices; private CancellationTokenSource _tokenSource; private static readonly object lockObject = new Object(); public DeviceService2(IHostingEnvironment env, IServiceProvider applicationServices, IConfiguration configuration, IHttpClientFactory httpClientFactory) { this._env = env; this._applicationServices = applicationServices; this._configuration = configuration; this._httpClientFactory = httpClientFactory; this._tokenSource = new CancellationTokenSource(); } public void Start() { Task.Run(async () => { while (!_tokenSource.IsCancellationRequested) { try { Console.WriteLine("timer ..."); Policy.Timeout(3).Execute(() => Notify()); } catch (Exception ex) { ex.PrintStack(); } await Task.Delay(this._configuration.GetValue("timer.seconds") * 1000); } }); } public void Exec(string code) { using (var scope = _applicationServices.CreateScope()) { var repo = scope.ServiceProvider.GetService>(); var button = repo.ReadOnlyTable().FirstOrDefault(o => o.Name == code); if (button != null) { this.Exec(button); } } } public void Exec(Button button) { using (var src = new SerialPortStream(button.SerialPort, button.Baud, button.Data, (RJCP.IO.Ports.Parity)button.Partity, (RJCP.IO.Ports.StopBits)button.StopBits)) { src.Open(); var data = button.Message.HexToBytes(); src.Write(data, 0, data.Length); src.Flush(); src.Close(); } } public void Notify() { Console.WriteLine("notify start ..."); lock (lockObject) { try { using (var client = new TcpClient()) { var tcpIp = this._configuration["tcp.ip"]; var tcpPort = this._configuration.GetValue("tcp.port"); client.Connect(tcpIp, tcpPort); using (var stream = client.GetStream()) { var addressData = this.GetAddress(stream); var address = BitConverter.ToString(addressData).Replace("-", ""); Console.WriteLine($"address:{address}"); var nodesStatus = GetNodeStatus(stream, addressData); Console.WriteLine($"nodes:{BitConverter.ToString(nodesStatus)}"); for (int i = 0; i < nodesStatus.Length; i++) { if (nodesStatus[i] == 0x01) { Console.WriteLine($"node online:{i + 1}"); NotifyModel model = null; var type = GetNodeType(stream, addressData, i + 1); if (type == 2) { var switchStatusData = GetSwitchStatus(stream, addressData, i + 1); var switchStatus = switchStatusData.ToBitString(); model = CreateModel("二路灯开关", address + i, "switch2", "switch"); model.Data.Add(new DataModel { Type = DataValueType.Text.ToString(), Key = "status", Name = "L1状态", Value = switchStatus[7] == '1' ? "开" : "关", DisplayOrder = 1 }); model.Data.Add(new DataModel { Type = DataValueType.Text.ToString(), Key = "status", Name = "L2状态", Value = switchStatus[6] == '1' ? "开" : "关", DisplayOrder = 2 }); } else if (type == 3) { var switchStatusData = GetSwitchStatus(stream, addressData, i + 1); model = CreateModel("一路插座", address + i, "socket1", "socket"); model.Data.Add(new DataModel { Type = DataValueType.Text.ToString(), Key = "status", Name = "状态", Value = switchStatusData == 0x01 ? "开" : "关", DisplayOrder = 1 }); } else if (type == 4) { var switchStatusData = GetSwitchStatus(stream, addressData, i + 1); model = CreateModel("二路插座", address + i, "socket2", "switch"); model.Data.Add(new DataModel { Type = DataValueType.Text.ToString(), Key = "status", Name = "状态", Value = switchStatusData == 0x01 ? "开" : "关", DisplayOrder = 1 }); } var url = $"http://{this._configuration["node.url"]}/Notify"; Console.WriteLine(url); var hc = this._httpClientFactory.CreateClient(); var task = this._httpClientFactory.CreateClient().PostAsync(url, new FormUrlEncodedContent(model.ToList())); task.Wait(); using (var response = task.Result) { using (var content = response.Content) { var value = content.ReadAsStringAsync().Result; Console.WriteLine($"end:{url}:{value}"); } } } else if (nodesStatus[i] == 0x02) { Console.WriteLine($"node offline:{i + 1}"); } } } } } catch (Exception ex) { ex.PrintStack(); } } Console.WriteLine("notify end ..."); } public void SwitchAllOn(string id) { //throw new NotImplementedException(); } public void SwitchAllOff(string id) { //throw new NotImplementedException(); } private NotifyModel CreateModel(string name, string number, string path, string icon) { var host = string.IsNullOrEmpty(this._configuration["server.ip"]) ? Helper.Instance.GetLocalIP().ToString() : this._configuration["server.ip"]; var port = Convert.ToInt32(Regex.Match(this._configuration["server.urls"], @"(?<=:)\d+").Value); return new NotifyModel { CategoryName = "电器", CategoryNumber = "20", Name = name, Number = number, Icon = icon, IsOnline = true, BaseUrl = $"http://{host}:{port}/{path}", ApiPath = "/api" }; } private byte[] Command(byte[] data) { var command = new List { 0xfe, 0xa5, 0x00 }; command.Add((byte)data.Length); command.AddRange(data); command.Add((byte)command.Skip(2).Select(o => Convert.ToInt32(o)).Sum()); return command.ToArray(); } private byte[] Data(byte[] data, bool crc16 = false) { var command = new List { 0xfe, 0xa5, 0x01 }; command.Add((byte)data.Length); command.AddRange(data); if (crc16) { var crc = Crc16.ComputeChecksum(data); command.Add(crc[1]); command.Add(crc[0]); } else { command.Add((byte)command.Skip(2).Select(o => Convert.ToInt32(o)).Sum()); } return command.ToArray(); } private byte[] GetAddress(NetworkStream stream) { var list = new List() { 0x0c }; this.Write(stream, Command(list.ToArray())); var buffer = new byte[256]; var length = stream.Read(buffer); Console.WriteLine($">address:{BitConverter.ToString(buffer, 0, length)}"); var address = buffer.Skip(5).Take(8).ToArray(); return address; } private byte[] GetNodeStatus(NetworkStream stream, byte[] address) { var list = new List() { 0x15 }; list.AddRange(address); list.Add(0x00); this.Write(stream, Command(list.ToArray())); var buffer = new byte[256]; var length = stream.Read(buffer); Console.WriteLine($">node status:{BitConverter.ToString(buffer, 0, length)}"); var status = buffer.Skip(14).Take(100).ToArray(); return status; } private byte GetNodeType(NetworkStream stream, byte[] address, int i) { var list = new List() { 0x16 }; list.AddRange(address); list.Add(0x00); var modbusdata = new List { (byte)i,0x03,0x00,0x0f,0x00,0x01 }.ToArray(); var modbus = new List(); modbus.AddRange(modbusdata); var crc = Crc16.ComputeChecksum(modbusdata); modbus.Add(crc[1]); modbus.Add(crc[0]); list.AddRange(modbus); this.Write(stream, Data(list.ToArray())); var buffer = new byte[256]; var length = stream.Read(buffer); Console.WriteLine($">type:{BitConverter.ToString(buffer, 0, length)}"); return buffer.Skip(14 + 3).Take(1).ToArray()[0]; } private byte GetSwitchStatus(NetworkStream stream, byte[] address, int i) { var list = new List() { 0x16 }; list.AddRange(address); list.Add(0x00); var modbusdata = new List { (byte)i, 0x01,0x00,0x00,0x00,0x04 }.ToArray(); var modbus = new List(); modbus.AddRange(modbusdata); var crc = Crc16.ComputeChecksum(modbusdata); modbus.Add(crc[1]); modbus.Add(crc[0]); list.AddRange(modbus); this.Write(stream, Data(list.ToArray())); var buffer = new byte[256]; var length = stream.Read(buffer); Console.WriteLine($">device status:{BitConverter.ToString(buffer, 0, length)}"); return buffer.Skip(17).Take(1).ToArray()[0]; } private void Write(NetworkStream stream, byte[] data) { Thread.Sleep(200); stream.Write(data); } public void Dispose() { Console.WriteLine("LiChuangService dispose..."); this._tokenSource.Cancel(); } } }