using Dm.util; using Microsoft.Extensions.DependencyInjection; using Newtonsoft.Json; using RJCP.IO.Ports; using Sln.Iot.Business; using Sln.Iot.Common; using Sln.Iot.Config; using Sln.Iot.Model.dao; using Sln.Iot.Model.dto; using Sln.Iot.Repository.service; using Sln.Iot.Serilog; using SqlSugar; using System; using System.Linq.Expressions; using System.Net.WebSockets; using System.Text; using TouchSocket.Core; using TouchSocket.Sockets; namespace Sln.Iot.Serial { public static class SerialExtensions { public static void UseSerialPortExtensions(this IServiceProvider service) { IRecordIotEnvInstantService instantService = service.GetService(); IBaseAlarmRuleService _alarmRuleService = service.GetService(); WebSocketBusiness webSocket = service.GetService(); var logger = service.GetService(); try { var appConfig = service.GetService(); var tcpClient = service.GetService(); var stringChange = service.GetService(); SerialPortStream serialPort = new SerialPortStream(appConfig.serialPortConfig.PortName); serialPort.BaudRate = appConfig.serialPortConfig.BaudRate; serialPort.Parity = Parity.None; serialPort.StopBits = StopBits.One; serialPort.DataBits = appConfig.serialPortConfig.DataBits; serialPort.Handshake = Handshake.None; serialPort.DataReceived += (sender, e) => { lock (string.Empty) { try { byte[] receivedData = new byte[serialPort.BytesToRead]; serialPort.Read(receivedData, 0, receivedData.Length); string str = Encoding.ASCII.GetString(receivedData); logger.Info($"串口服务接收到数据:{str}"); List< RecordIotEnvInstant > iotEnvInstants = new List< RecordIotEnvInstant >(); string[] monitorInfos = str.Split(';'); foreach ( string monitorInfo in monitorInfos ) { if (monitorInfo.Length < 12) { continue; } logger.Info($"解析串口数据:{monitorInfo}"); RecordIotEnvInstant iotEnvInstant = new RecordIotEnvInstant(); string[] strs = monitorInfo.Replace(";","").Split('-'); iotEnvInstant.monitorId = strs[0]; if (strs[1] == "5" || strs[1] == "6") { iotEnvInstant.temperature = decimal.Parse(strs[2].Trim()); } if (strs[1] == "6") { iotEnvInstant.humidity = decimal.Parse(strs[3].Trim()); } if (strs[1] == "7") { iotEnvInstant.noise = decimal.Parse(strs[2].Trim()); } if (strs[1] == "8") { iotEnvInstant.illuminance = decimal.Parse(strs[2].Trim()); } if (strs[1] == "10") { iotEnvInstant.vibrationSpeed = decimal.Parse(strs[2].Trim()); iotEnvInstant.vibrationAcceleration = decimal.Parse(strs[3].Trim()); iotEnvInstant.vibrationDisplacement = decimal.Parse(strs[4].Trim()); iotEnvInstant.vibrationTemp = decimal.Parse(strs[5].Trim()); } iotEnvInstant.collectTime = DateTime.Now; iotEnvInstant.recordTime = DateTime.Now; iotEnvInstants.Add(iotEnvInstant); Thread.Sleep(200); } var inRes = instantService.SplitInsert(iotEnvInstants, out List insertIds); logger.Info($"物联网数据保存{(inRes ? "成功" : "失败")}"); ParamAlarmFilter(iotEnvInstants,_alarmRuleService,logger, webSocket); } catch (Exception ex) { logger.Info($"串口接收数据异常:{ex.Message}"); } } }; serialPort.Open(); logger.Info($"串口服务加载启动成功"); } catch (Exception ex) { logger.Error($"串口服务加载异常:{ex.Message}"); } } private static void ParamAlarmFilter(List iotEnvInstants, IBaseAlarmRuleService _alarmRuleService, SerilogHelper _logger, WebSocketBusiness _webSocket) { if (iotEnvInstants == null) { throw new ArgumentNullException(nameof(iotEnvInstants), "报警参数过滤异常,传入参数为空"); } // 预编译比较委托(避免循环内重复编译) static Func CreateComparer(int triggerRule) { ParameterExpression x = Expression.Parameter(typeof(decimal), "x"); ParameterExpression y = Expression.Parameter(typeof(decimal), "y"); BinaryExpression comparison = triggerRule == 0 ? Expression.GreaterThan(x, y) : Expression.LessThan(x, y); return Expression.Lambda>(comparison, x, y).Compile(); } var fieldAccessors = new Dictionary> { { 0, item => item.temperature }, { 1, item => item.humidity }, { 2, item => item.vibrationSpeed }, { 3, item => item.vibrationDisplacement }, { 4, item => item.vibrationAcceleration }, { 5, item => item.vibrationTemp }, { 6, item => item.noise }, { 7, item => item.illuminance } }; foreach (var item in iotEnvInstants) { var alarmRules = _alarmRuleService.Query(x => x.monitorId == item.monitorId); List ruleRes = new List(); List alarmContents = new List(); foreach (var rule in alarmRules) { decimal paramValue = fieldAccessors.TryGetValue(rule.monitorField, out var accessor) ? accessor(item) : 0; var comparer = CreateComparer(rule.triggerRule); if (comparer(paramValue, rule.triggerValue)) { ruleRes.Add(rule); alarmContents.Add($"{item.monitorId}传感器数据在{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}触发{rule.ruleName}异常告警,告警规则:{(rule.triggerRule == 0 ? "大于" : "小于")},阈值:{rule.triggerValue},详细信息:{rule.cause}"); } } MonitorAlarmDto monitorAlarmDto = new MonitorAlarmDto() { monitorId = item.monitorId, isFlag = ruleRes.Count() > 0 ? 1 : 0, deviceParam = item, alarmRules = ruleRes, alarmContents = alarmContents, recordTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() }; string str = JsonConvert.SerializeObject(monitorAlarmDto); _logger.Alarm($"传感器数据推送:{str}"); _webSocket.PushMsg(str); } } } }