change - 串口数据解析逻辑处理

pull/1/head
wenjy 3 weeks ago
parent 1762b1c88a
commit f94b325429

@ -25,7 +25,11 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using Dm.util;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Sln.Iot.Business.@base;
@ -35,6 +39,7 @@ using Sln.Iot.Model.dao;
using Sln.Iot.Model.dto;
using Sln.Iot.Repository.service;
using Sln.Iot.Serilog;
using Sln.Iot.Socket;
using Sln.Iot.Socket.Adapter;
using TouchSocket.Core;
using TouchSocket.Sockets;
@ -47,10 +52,26 @@ namespace Sln.Iot.Business
public class IotEnvBusiness:BaseBusiness
{
private readonly IRecordIotEnvInstantService? _service;
private readonly IBaseAlarmRuleService _alarmRuleService;
private readonly WebSocketBusiness _webSocket;
private readonly TcpServer _tcpServer;
private readonly IBaseMonitorInfoService _monitorInfoService;
public IotEnvBusiness(SerilogHelper logger, AppConfig appConfig, StringChange stringChange, IRecordIotEnvInstantService? service) : base(logger, appConfig, stringChange)
public IotEnvBusiness(SerilogHelper logger, AppConfig appConfig, StringChange stringChange, IRecordIotEnvInstantService? service,
IBaseAlarmRuleService alarmRuleService, WebSocketBusiness webSocket, TcpServer tcpServer
, IBaseMonitorInfoService monitorInfoService) : base(logger, appConfig, stringChange)
{
_service = service;
_alarmRuleService = alarmRuleService;
_webSocket = webSocket;
_tcpServer = tcpServer;
_monitorInfoService = monitorInfoService;
}
public override FilterResult BufferAnalysis(ISocketClient client, BufferRequestInfo requestInfo, int bodyLength)
@ -139,17 +160,16 @@ namespace Sln.Iot.Business
ValueIsNan(ref f_vibrationSpeed);
iotEnvInstant.VibrationSpeed = (decimal) f_vibrationSpeed;
iotEnvInstant.vibrationSpeed = (decimal) f_vibrationSpeed;
break;
case CommParams.VibrationDisplacement: //振动-位移
bodyLength = 58;
byteBlock.Read(out byte[] vibrationDisplacement, 4);
base._stringChange.SwapBytes(ref vibrationDisplacement);
float f_vibrationDisplacement = BitConverter.ToSingle(vibrationDisplacement, 0);
ValueIsNan(ref f_vibrationDisplacement);
iotEnvInstant.VibrationDisplacement = (decimal)f_vibrationDisplacement;
iotEnvInstant.vibrationDisplacement = (decimal)f_vibrationDisplacement;
break;
case CommParams.VibrationAcceleration: //振动-加速度
byteBlock.Read(out byte[] vibrationAcceleration, 4);
@ -158,7 +178,7 @@ namespace Sln.Iot.Business
ValueIsNan(ref f_vibrationAcceleration);
iotEnvInstant.VibrationAcceleration = (decimal)f_vibrationAcceleration;
iotEnvInstant.vibrationAcceleration = (decimal)f_vibrationAcceleration;
break;
case CommParams.VibrationTemp: //振动-温度
byteBlock.Read(out byte[] vibrationTemp, 4);
@ -167,7 +187,7 @@ namespace Sln.Iot.Business
ValueIsNan(ref f_vibrationTemp);
iotEnvInstant.VibrationTemp = (decimal)f_vibrationTemp;
iotEnvInstant.vibrationTemp = (decimal)f_vibrationTemp;
break;
case CommParams.CJSJ:
byteBlock.Read(out byte[] b_CJSJ, 6);
@ -203,10 +223,14 @@ namespace Sln.Iot.Business
{
ParamVerification(ref result);
}
SendData(result);
var inRes = _service.SplitInsert(result,out List<long> insertIds);
_logger.Info($"{amount}个物联网数据解析处理完成,保存{result.Count}个物联网数据,保存{(inRes ? "" : "")}");
ParamAlarmFilter(result);
}
else
{
@ -276,28 +300,28 @@ namespace Sln.Iot.Business
continue;
}
if (item.VibrationSpeed == _appConfig.virtualValue)
if (item.vibrationSpeed == _appConfig.virtualValue)
{
_logger.Info($"MonitorId:{item.monitorId},振动速度值为 FF FF FF FF已启用过滤不保存该表数据");
iotEnvInstants.RemoveAt(i);
continue;
}
if (item.VibrationDisplacement == _appConfig.virtualValue)
if (item.vibrationDisplacement == _appConfig.virtualValue)
{
_logger.Info($"MonitorId:{item.monitorId},振动位移值为 FF FF FF FF已启用过滤不保存该表数据");
iotEnvInstants.RemoveAt(i);
continue;
}
if (item.VibrationAcceleration == _appConfig.virtualValue)
if (item.vibrationAcceleration == _appConfig.virtualValue)
{
_logger.Info($"MonitorId:{item.monitorId},振动加速度值为 FF FF FF FF已启用过滤不保存该表数据");
iotEnvInstants.RemoveAt(i);
continue;
}
if (item.VibrationTemp == _appConfig.virtualValue)
if (item.vibrationTemp == _appConfig.virtualValue)
{
_logger.Info($"MonitorId:{item.monitorId},振动温度值为 FF FF FF FF已启用过滤不保存该表数据");
iotEnvInstants.RemoveAt(i);
@ -305,5 +329,150 @@ namespace Sln.Iot.Business
}
}
}
/// <summary>
///
/// </summary>
/// <param name="iotEnvInstants"></param>
public void SendData(List<RecordIotEnvInstant> iotEnvInstants)
{
lock (string.Empty)
{
foreach (var iotEnvInstant in iotEnvInstants)
{
Thread.Sleep(200);
var monitorInfo = _monitorInfoService.Query(x => x.monitorId == iotEnvInstant.monitorId).FirstOrDefault();
StringBuilder sb = new StringBuilder();
if (monitorInfo != null)
{
sb.Append(iotEnvInstant.monitorId);
sb.Append("-");
sb.Append(monitorInfo.monitorType);
if (monitorInfo.monitorType == 5 || monitorInfo.monitorType == 6)
{
sb.Append("-");
sb.Append(iotEnvInstant.temperature);
}
if (monitorInfo.monitorType == 6)
{
sb.Append("-");
sb.Append(iotEnvInstant.humidity);
}
if (monitorInfo.monitorType == 7)
{
sb.Append("-");
sb.Append(iotEnvInstant.noise);
}
if (monitorInfo.monitorType == 8)
{
sb.Append("-");
sb.Append(iotEnvInstant.illuminance);
}
if (monitorInfo.monitorType == 10)
{
sb.Append("-");
sb.Append(iotEnvInstant.vibrationSpeed);
sb.Append("-");
sb.Append(iotEnvInstant.vibrationAcceleration);
sb.Append("-");
sb.Append(iotEnvInstant.vibrationDisplacement);
sb.Append("-");
sb.Append(iotEnvInstant.vibrationTemp);
}
sb.Append(";");
}
//string str = $"{iotEnvInstant.monitorId}-{iotEnvInstant.temperature}-{iotEnvInstant.humidity}-{iotEnvInstant.noise}-{iotEnvInstant.illuminance}-{iotEnvInstant.vibrationSpeed}-{iotEnvInstant.vibrationAcceleration}-{iotEnvInstant.vibrationDisplacement}-{iotEnvInstant.vibrationTemp}";
string str = sb.ToString();
byte[] bytes = StringToBytesUsingASCII(str);
_tcpServer.SendDataToRecevieDevice(bytes);
}
}
}
public static byte[] StringToBytesUsingASCII(string input)
{
if (input == null)
{
throw new ArgumentNullException(nameof(input), "输入字符串不能为 null。");
}
// 使用 ASCII 编码将字符串转换为字节数组
return Encoding.ASCII.GetBytes(input);
}
/// <summary>
/// 报警参数过滤
/// </summary>
/// <param name="iotEnvInstants"></param>
private void ParamAlarmFilter(List<RecordIotEnvInstant> iotEnvInstants)
{
if (iotEnvInstants == null)
{
throw new ArgumentNullException(nameof(iotEnvInstants), "报警参数过滤异常,传入参数为空");
}
// 预编译比较委托(避免循环内重复编译)
static Func<decimal, decimal, bool> 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<Func<decimal, decimal, bool>>(comparison, x, y).Compile();
}
var fieldAccessors = new Dictionary<int, Func<RecordIotEnvInstant, decimal>>
{
{ 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<BaseAlarmRule> ruleRes = new List<BaseAlarmRule>();
List<string> alarmContents = new List<string>();
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);
}
}
}
}

@ -6,6 +6,10 @@
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Fleck" Version="1.2.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Sln.Iot.Common\Sln.Iot.Common.csproj" />
<ProjectReference Include="..\Sln.Iot.Model\Sln.Iot.Model.csproj" />

@ -0,0 +1,63 @@
using Fleck;
using Sln.Iot.Serilog;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Sln.Iot.Business
{
public class WebSocketBusiness
{
private List<IWebSocketConnection> allSockets = new List<IWebSocketConnection>();
private readonly SerilogHelper _logger;
public WebSocketBusiness(SerilogHelper serilogHelper)
{
_logger = serilogHelper;
}
public void Init()
{
var server = new Fleck.WebSocketServer($"ws://0.0.0.0:7181");
server.Start(socket =>
{
socket.OnOpen = () =>
{
var data = socket.ConnectionInfo;
_logger.Info("WebSocket Open!");
allSockets.Add(socket);
};
socket.OnClose = () =>
{
_logger.Info("WebSocket Close!");
allSockets.Remove(socket);
};
socket.OnMessage = message =>
{
//ReceivedMessageRequestInfoEvent?.Invoke(socket, message);
};
});
}
public void PushMsg(string msg)
{
try
{
foreach (var socket in allSockets.ToList())
{
socket.Send(msg);
_logger.Info($"WebSocket推送信息:{msg}");
}
}
catch (Exception ex)
{
_logger.Info($"WebSocket推送信息异常:{ex.Message}");
}
}
}
}

@ -23,10 +23,13 @@
#endregion << 版 本 注 释 >>
using Fleck;
using Microsoft.Extensions.DependencyInjection;
using Sln.Iot.Common;
using Sln.Iot.Config;
using Sln.Iot.Model.dto;
using Sln.Iot.Serilog;
using Sln.Iot.Socket;
using Sln.Iot.Socket.Adapter;
using TouchSocket.Core;
using TouchSocket.Sockets;
@ -40,12 +43,13 @@ namespace Sln.Iot.Business.@base
public AppConfig _appConfig;
public StringChange _stringChange;
public BaseBusiness(SerilogHelper logger,AppConfig appConfig,StringChange stringChange)
{
_logger = logger;
_appConfig = appConfig;
_stringChange = stringChange;
}
/// <summary>
@ -147,5 +151,6 @@ namespace Sln.Iot.Business.@base
}
}
}
}
}

@ -70,6 +70,11 @@ namespace Sln.Iot.Config
/// </summary>
public string redisConfig { get; set; }
/// <summary>
/// 串口配置
/// </summary>
public SerialPortConfig serialPortConfig { get; set; }
public AppConfig Value => this;
}
}

@ -0,0 +1,41 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Sln.Iot.Config
{
public class SerialPortConfig
{
/// <summary>
/// 串口名称
/// </summary>
public string PortName { get; set; }
/// <summary>
/// 波特率
/// </summary>
public int BaudRate { get; set; }
/// <summary>
/// 奇偶校验
/// </summary>
public int Parity { get; set; }
/// <summary>
/// 停止位
/// </summary>
public int StopBits { get; set; }
/// <summary>
/// 数据位
/// </summary>
public int DataBits { get; set; }
/// <summary>
///
/// </summary>
public int Handshake { get; set; }
}
}

@ -0,0 +1,61 @@
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Sln.Iot.Model.dao
{
[SugarTable("ems_record_alarm_rule"), TenantAttribute("tao_iot")]
public class BaseAlarmRule
{
/// <summary>
/// 编号
///</summary>
[SugarColumn(ColumnName = "obj_id", IsPrimaryKey = true)]
public long objid { get; set; }
/// <summary>
/// 计量设备编号
///</summary>
[SugarColumn(ColumnName = "monitor_id")]
public string monitorId { get; set; }
/// <summary>
/// 规则编号
/// </summary>
[SugarColumn(ColumnName = "rule_id")]
public string ruleId { get;set; }
/// <summary>
/// 规则名称
/// </summary>
[SugarColumn(ColumnName = "rule_name")]
public string ruleName { get; set; }
/// <summary>
/// 触发规则0大于 1小于
/// </summary>
[SugarColumn(ColumnName = "trigger_rule")]
public int triggerRule { get; set; }
/// <summary>
/// 监测字段0温度1湿度2振动-速度(mm/s)3振动-位移(um)4振动-加速度(g)5振动-温度(℃),6-噪音7-照度)
/// </summary>
[SugarColumn(ColumnName = "monitor_field")]
public int monitorField { get;set; }
/// <summary>
/// 阈值
/// </summary>
[SugarColumn(ColumnName = "trigger_value")]
public decimal triggerValue { get; set; }
/// <summary>
/// 备注
/// </summary>
[SugarColumn(ColumnName = "cause")]
public string cause { get; set; }
}
}

@ -78,26 +78,26 @@ namespace Sln.Iot.Model.dao
/// 振动-速度
/// </summary>
[SugarColumn(ColumnName = "vibration_speed")]
public decimal VibrationSpeed { get; set; }
public decimal vibrationSpeed { get; set; }
/// <summary>
/// 振动-位移
/// </summary>
[SugarColumn(ColumnName = "vibration_displacement")]
public decimal VibrationDisplacement { get; set; }
public decimal vibrationDisplacement { get; set; }
/// <summary>
/// 振动-加速度
/// </summary>
[SugarColumn(ColumnName = "vibration_acceleration")]
public decimal VibrationAcceleration { get; set; }
public decimal vibrationAcceleration { get; set; }
/// <summary>
/// 振动-温度
/// </summary>
[SugarColumn(ColumnName = "vibration_temp")]
public decimal VibrationTemp { get; set; }
public decimal vibrationTemp { get; set; }
/// <summary>

@ -46,22 +46,23 @@ namespace Sln.Iot.Model.dto
/// <summary>
/// 振动-速度
/// </summary>
public const uint VibrationSpeed = 0x8E54;
public const uint VibrationSpeed = 0x8E55;
/// <summary>
/// 振动-位移
/// </summary>
public const uint VibrationDisplacement = 0x8E55;
public const uint VibrationDisplacement = 0x8E56;
/// <summary>
/// 振动-加速度
/// </summary>
public const uint VibrationAcceleration = 0x8E56;
public const uint VibrationAcceleration = 0x8E57;
/// <summary>
/// 振动-温度
/// </summary>
public const uint VibrationTemp = 0x8E57;
public const uint VibrationTemp = 0x8E54;
/// <summary>
/// 采集时间

@ -0,0 +1,43 @@
using Sln.Iot.Model.dao;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Sln.Iot.Model.dto
{
public class MonitorAlarmDto
{
/// <summary>
/// 设备编号
/// </summary>
public string monitorId { get;set; }
/// <summary>
/// 是否报警1-是;0-否
/// </summary>
public int isFlag { get;set; }
/// <summary>
/// 设备参数
/// </summary>
public RecordIotEnvInstant deviceParam { get;set; }
/// <summary>
/// 告警规则
/// </summary>
public List<BaseAlarmRule> alarmRules { get;set; }
/// <summary>
/// 报警内容
/// </summary>
public List<string> alarmContents { get;set; }
/// <summary>
/// 记录时间
/// </summary>
public long recordTime { get;set; }
}
}

@ -0,0 +1,14 @@
using Sln.Iot.Model.dao;
using Sln.Iot.Repository.service.@base;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Sln.Iot.Repository.service
{
public interface IBaseAlarmRuleService : IBaseService<BaseAlarmRule>
{
}
}

@ -0,0 +1,17 @@
using Sln.Iot.Model.dao;
using Sln.Iot.Repository.service.@base;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Sln.Iot.Repository.service.Impl
{
public class BaseAlarmRuleServiceImpl : BaseServiceImpl<BaseAlarmRule>, IBaseAlarmRuleService
{
public BaseAlarmRuleServiceImpl(Repository<BaseAlarmRule> rep) : base(rep)
{
}
}
}

@ -0,0 +1,198 @@
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<IRecordIotEnvInstantService>();
IBaseAlarmRuleService _alarmRuleService = service.GetService<IBaseAlarmRuleService>();
WebSocketBusiness webSocket = service.GetService<WebSocketBusiness>();
var logger = service.GetService<SerilogHelper>();
try
{
var appConfig = service.GetService<AppConfig>();
var tcpClient = service.GetService<TcpClient>();
var stringChange = service.GetService<StringChange>();
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<long> 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<RecordIotEnvInstant> iotEnvInstants, IBaseAlarmRuleService _alarmRuleService, SerilogHelper _logger, WebSocketBusiness _webSocket)
{
if (iotEnvInstants == null)
{
throw new ArgumentNullException(nameof(iotEnvInstants), "报警参数过滤异常,传入参数为空");
}
// 预编译比较委托(避免循环内重复编译)
static Func<decimal, decimal, bool> 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<Func<decimal, decimal, bool>>(comparison, x, y).Compile();
}
var fieldAccessors = new Dictionary<int, Func<RecordIotEnvInstant, decimal>>
{
{ 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<BaseAlarmRule> ruleRes = new List<BaseAlarmRule>();
List<string> alarmContents = new List<string>();
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);
}
}
}
}

@ -0,0 +1,28 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="RJCP.SerialPortStream" Version="3.0.3" />
<PackageReference Include="System.IO.Ports" Version="9.0.5" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Sln.Iot.Business\Sln.Iot.Business.csproj" />
<ProjectReference Include="..\Sln.Iot.Common\Sln.Iot.Common.csproj" />
<ProjectReference Include="..\Sln.Iot.Model\Sln.Iot.Model.csproj" />
<ProjectReference Include="..\Sln.Iot.Repository\Sln.Iot.Repository.csproj" />
<ProjectReference Include="..\Sln.Iot.Socket\Sln.Iot.Socket.csproj" />
</ItemGroup>
<ItemGroup>
<None Update="libnserial.so.1">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>

Binary file not shown.

@ -48,11 +48,11 @@ namespace Sln.Iot.Serilog
.Filter.ByIncludingOnly(logEvent => logEvent.Properties.ContainsKey("Module") && logEvent.Properties["Module"].ToString().Contains("Info"))
.WriteTo.File(Path.Combine($"{logPath}/Info/", "Info.log"), rollingInterval: RollingInterval.Day))
.WriteTo.Logger(lc => lc
.Filter.ByIncludingOnly(logEvent => logEvent.Properties.ContainsKey("Module") && logEvent.Properties["Module"].ToString().Contains("Plc"))
.WriteTo.File(Path.Combine($"{logPath}/Plc/", "Plc.log"), rollingInterval: RollingInterval.Day))
.Filter.ByIncludingOnly(logEvent => logEvent.Properties.ContainsKey("Module") && logEvent.Properties["Module"].ToString().Contains("Iot"))
.WriteTo.File(Path.Combine($"{logPath}/Iot/", "Iot.log"), rollingInterval: RollingInterval.Day))
.WriteTo.Logger(lc => lc
.Filter.ByIncludingOnly(logEvent => logEvent.Properties.ContainsKey("Module") && logEvent.Properties["Module"].ToString().Contains("Camera"))
.WriteTo.File(Path.Combine($"{logPath}/Camera/", "Camera.log"), rollingInterval: RollingInterval.Day))
.Filter.ByIncludingOnly(logEvent => logEvent.Properties.ContainsKey("Module") && logEvent.Properties["Module"].ToString().Contains("Alarm"))
.WriteTo.File(Path.Combine($"{logPath}/Alarm/", "Alarm.log"), rollingInterval: RollingInterval.Day))
.WriteTo.Logger(lc => lc
.Filter.ByIncludingOnly(logEvent => logEvent.Properties.ContainsKey("Module") && logEvent.Properties["Module"].ToString().Contains("Error"))
.WriteTo.File(Path.Combine($"{logPath}/Error/", "Error.log"), rollingInterval: RollingInterval.Day))

@ -31,9 +31,9 @@ namespace Sln.Iot.Serilog
public class SerilogHelper
{
private readonly ILogger? Info_logger = Log.ForContext("Module", "Info");
private readonly ILogger? Plc_logger = Log.ForContext("Module", "Plc");
private readonly ILogger? Iot_logger = Log.ForContext("Module", "Iot");
private readonly ILogger? Error_logger = Log.ForContext("Module", "Error");
private readonly ILogger? Camera_logger = Log.ForContext("Module", "Camera");
private readonly ILogger? Alarm_logger = Log.ForContext("Module", "Alarm");
/// <summary>
/// Info日志
@ -48,26 +48,26 @@ namespace Sln.Iot.Serilog
}
/// <summary>
/// Plc日志
/// Iot日志
/// </summary>
/// <param name="msg"></param>
public void Plc(string msg)
public void Iot(string msg)
{
if (Plc_logger != null)
if (Iot_logger != null)
{
this.Plc_logger.Information(msg);
this.Iot_logger.Information(msg);
}
}
/// <summary>
/// 相机日志
/// 设备告警日志
/// </summary>
/// <param name="msg"></param>
public void Camera(string msg)
public void Alarm(string msg)
{
if (Camera_logger != null)
if (Alarm_logger != null)
{
this.Camera_logger.Information(msg);
this.Alarm_logger.Information(msg);
}
}

@ -1,5 +0,0 @@
namespace Sln.Iot.Socket;
public class Class1
{
}

@ -11,6 +11,7 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Sln.Iot.Common\Sln.Iot.Common.csproj" />
<ProjectReference Include="..\Sln.Iot.Serilog\Sln.Iot.Serilog.csproj" />
</ItemGroup>

@ -24,6 +24,8 @@
#endregion << 版 本 注 释 >>
using System;
using System.Text;
using Sln.Iot.Common;
using Sln.Iot.Serilog;
using Sln.Iot.Socket.Adapter;
using TouchSocket.Core;
@ -35,11 +37,13 @@ namespace Sln.Iot.Socket
{
private readonly SerilogHelper _logger;
private readonly TcpService _service;
private readonly StringChange _stringChange;
public TcpServer(SerilogHelper logger, TcpService service)
public TcpServer(SerilogHelper logger, TcpService service, StringChange stringChange)
{
_logger = logger;
_service = service;
_stringChange = stringChange;
}
/// <summary>
@ -66,7 +70,7 @@ namespace Sln.Iot.Socket
_service.Connected = (client, e) => {
_logger.Info($"客户端{client.IP}接入服务成功");
RefreshClientInfoEvent?.Invoke(_service);
return EasyTask.CompletedTask;
return EasyTask.CompletedTask;
};
_service.Disconnected = (client, e) => {
_logger.Info($"客户端{client.IP}断开连接");
@ -77,13 +81,13 @@ namespace Sln.Iot.Socket
{
if (e.RequestInfo is BufferRequestInfo request)
{
_logger.Iot($"收到客户端:{client.Id};原始指令====>>>>{_stringChange.bytesToHexStr(request.buffer.Buffer, request.buffer.Len)}");
string msg = $"收到客户端:{client.Id};指令====>>>>Header:{BitConverter.ToString(request.header).Replace("-", "")};DataType:{request.DataType.ToString("X2")};BufferLength:{request.BufferLength};Body:{BitConverter.ToString(request.Body).Replace("-", "")};CheckBit:{request.CheckBit.ToString("X2")};Tail:{BitConverter.ToString(request.Tail).Replace("-", "")};";
_logger.Info($"{msg}");
ReceivedBufferRequestInfoEvent?.Invoke(client,request);
}
return EasyTask.CompletedTask;
@ -123,5 +127,23 @@ namespace Sln.Iot.Socket
_service.Send(item.Id,"heartbeat");
}
}
public void SendDataToRecevieDevice(byte[] bytes)
{
var clientInfos = _service.SocketClients.GetClients().Where(x => x.Id.Contains("450")).ToList();
if (clientInfos == null)
{
_logger.Info($"连接中不存在450设备");
}
else
{
foreach (var item in clientInfos)
{
item.Send(bytes);
_logger.Info($"向接收设备{item.Id};发送数据:{_stringChange.bytesToHexStr(bytes, bytes.Length)}");
}
}
}
}
}

@ -3,21 +3,23 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.9.34714.143
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sln.Iot", "Sln.Iot\Sln.Iot.csproj", "{2140AD68-D4CE-44EC-B9D3-20D18EB59F9D}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sln.Iot", "Sln.Iot\Sln.Iot.csproj", "{2140AD68-D4CE-44EC-B9D3-20D18EB59F9D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sln.Iot.Business", "Sln.Iot.Business\Sln.Iot.Business.csproj", "{F59EB67D-66FD-43B9-B6CC-46BF25202C21}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sln.Iot.Business", "Sln.Iot.Business\Sln.Iot.Business.csproj", "{F59EB67D-66FD-43B9-B6CC-46BF25202C21}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sln.Iot.Config", "Sln.Iot.Config\Sln.Iot.Config.csproj", "{2E10DED8-5F53-4ED9-892F-B0007B85806E}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sln.Iot.Config", "Sln.Iot.Config\Sln.Iot.Config.csproj", "{2E10DED8-5F53-4ED9-892F-B0007B85806E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sln.Iot.Common", "Sln.Iot.Common\Sln.Iot.Common.csproj", "{899D8A81-D3E3-4599-8A8C-D60280A777F3}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sln.Iot.Common", "Sln.Iot.Common\Sln.Iot.Common.csproj", "{899D8A81-D3E3-4599-8A8C-D60280A777F3}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sln.Iot.Model", "Sln.Iot.Model\Sln.Iot.Model.csproj", "{503E7EAE-6323-4CE2-AAE4-C6A7CBDFC4B2}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sln.Iot.Model", "Sln.Iot.Model\Sln.Iot.Model.csproj", "{503E7EAE-6323-4CE2-AAE4-C6A7CBDFC4B2}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sln.Iot.Repository", "Sln.Iot.Repository\Sln.Iot.Repository.csproj", "{DA193E49-8B4A-4C8D-B44E-844E22983DA8}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sln.Iot.Repository", "Sln.Iot.Repository\Sln.Iot.Repository.csproj", "{DA193E49-8B4A-4C8D-B44E-844E22983DA8}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sln.Iot.Serilog", "Sln.Iot.Serilog\Sln.Iot.Serilog.csproj", "{A9CCC9F6-BE1C-4B73-AFBF-83D363D7F64F}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sln.Iot.Serilog", "Sln.Iot.Serilog\Sln.Iot.Serilog.csproj", "{A9CCC9F6-BE1C-4B73-AFBF-83D363D7F64F}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sln.Iot.Socket", "Sln.Iot.Socket\Sln.Iot.Socket.csproj", "{5B7C6367-7B41-48A6-9A71-2F191CE14000}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sln.Iot.Socket", "Sln.Iot.Socket\Sln.Iot.Socket.csproj", "{5B7C6367-7B41-48A6-9A71-2F191CE14000}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sln.Iot.Serial", "Sln.Iot.Serial\Sln.Iot.Serial.csproj", "{A030CF57-DAA0-4662-B836-3CFC2CDCD9FE}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -57,6 +59,10 @@ Global
{5B7C6367-7B41-48A6-9A71-2F191CE14000}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5B7C6367-7B41-48A6-9A71-2F191CE14000}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5B7C6367-7B41-48A6-9A71-2F191CE14000}.Release|Any CPU.Build.0 = Release|Any CPU
{A030CF57-DAA0-4662-B836-3CFC2CDCD9FE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A030CF57-DAA0-4662-B836-3CFC2CDCD9FE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A030CF57-DAA0-4662-B836-3CFC2CDCD9FE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A030CF57-DAA0-4662-B836-3CFC2CDCD9FE}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

@ -7,7 +7,10 @@ using Sln.Iot.Config;
using Sln.Iot.Repository;
using Sln.Iot.Serilog;
using Sln.Iot.Socket;
using Sln.Iot.Serial;
using TouchSocket.Sockets;
using TouchSocket.Core;
using Fleck;
namespace Sln.Iot
{
@ -32,6 +35,9 @@ namespace Sln.Iot
var _server = ServiceProvider.GetService<TcpServer>();
_server.Init(appConfig.listernPort);
var _webSocket = ServiceProvider.GetService<WebSocketBusiness>();
_webSocket.Init();
_server.ReceivedBufferRequestInfoEvent += (client, info) =>
{
bool isRet = false;
@ -67,12 +73,14 @@ namespace Sln.Iot
if (_business != null)
{
Parallel.Invoke(
() => _business.ResponseHandle(client, info.buffer),
//() => _business.ResponseHandle(client, info.buffer),
() => _business.BufferAnalysis(client, info, bodyLength)
);
}
};
ServiceProvider.UseSerialPortExtensions();
await Task.Delay(-1);
}
@ -88,6 +96,19 @@ namespace Sln.Iot
return ap;
});
//services.AddSingleton<TcpClient>(provider =>
//{
// TcpClient tcpClient = new TcpClient();
// tcpClient.Setup(new TouchSocketConfig()
// .SetRemoteIPHost("127.0.0.1:6000")
// .ConfigureContainer(a =>
// {
// a.AddConsoleLogger();
// }));
// tcpClient.Connect();
// return tcpClient;
//});
Assembly[] assemblies =
{
Assembly.LoadFrom("Sln.Iot.Repository.dll"),
@ -100,7 +121,7 @@ namespace Sln.Iot
.AddClasses()
.AsImplementedInterfaces()
.AsSelf()
.WithTransientLifetime());
.WithSingletonLifetime());
services.AddSingleton(typeof(SerilogHelper));
services.AddSingleton(typeof(TcpService));

@ -14,6 +14,7 @@
<ProjectReference Include="..\Sln.Iot.Config\Sln.Iot.Config.csproj" />
<ProjectReference Include="..\Sln.Iot.Model\Sln.Iot.Model.csproj" />
<ProjectReference Include="..\Sln.Iot.Repository\Sln.Iot.Repository.csproj" />
<ProjectReference Include="..\Sln.Iot.Serial\Sln.Iot.Serial.csproj" />
<ProjectReference Include="..\Sln.Iot.Serilog\Sln.Iot.Serilog.csproj" />
<ProjectReference Include="..\Sln.Iot.Socket\Sln.Iot.Socket.csproj" />
</ItemGroup>
@ -27,6 +28,9 @@
<None Update="appsettings.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="libnserial.so.1">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>

@ -4,16 +4,22 @@
"listernPort": 6000,
"virtualFlag": true,
"virtualValue": 9999999,
"electricTimeInterval": 1, //
"fluidTimeInterval": 1, //
"receiveDevice": "E0020",
"electricTimeInterval": 1, //
"fluidTimeInterval": 1, //
"SqlConfig": [
{
"configId": "tao_iot", //tao:
"dbType": 0, //tidb mysql
"configId": "tao_iot", //tao:
"dbType": 0, //tidb mysql
"isFlag": true,
//"connStr": "server=127.0.0.1;Port=4000;Database=tao_iot;Uid=root;" //Pwd=haiwei@123;
"connStr": "server=1.13.177.47;Port=3306;Database=tao_iot;Uid=root;Pwd=Haiwei123456;"
"connStr": "server=1.13.177.47;Port=3306;Database=tao_iot;Uid=root;Pwd=Haiwei123456;"
}
],
"serialPortConfig": {
"PortName": "COM1",
"BaudRate": 9600,
"DataBits": 8
}
}
}

Binary file not shown.
Loading…
Cancel
Save