dev #2

Merged
wenjy merged 2 commits from dev into master 3 weeks ago

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

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

@ -57,5 +57,11 @@ namespace Sln.Iot.Model.dao
/// </summary>
[SugarColumn(ColumnName = "cause")]
public string cause { get; set; }
/// <summary>
/// 告警记录ID推送数据使用ORM不用
/// </summary>
[SugarColumn(IsIgnore = true)]
public long alarmId { get; set; }
}
}

@ -0,0 +1,83 @@
#region << 版 本 注 释 >>
/*--------------------------------------------------------------------
* (c) 2025 Wen JY
* CLR4.0.30319.42000
* ThinkPad T14
* Sln.Iot.Model.dao
* 50695B31-9DE2-4EE5-A13D-D58B53CDEBBA
*
* WenJY
*
* 2025-06-05 10:38:09
* V1.0.0
*
*
*--------------------------------------------------------------------
*
*
*
*
* V1.0.0
*--------------------------------------------------------------------*/
#endregion << 版 本 注 释 >>
using SqlSugar;
namespace Sln.Iot.Model.dao;
///<summary>
///告警数据记录
///</summary>
[SugarTable("ems_record_alarm_data"), Tenant("tao_iot")]
public class RecordAlarmData
{
/// <summary>
/// 编号
///</summary>
[SugarColumn(ColumnName = "obj_id", IsPrimaryKey = true)]
public long objid { get; set; }
/// <summary>
/// Desc:计量设备编号
/// Default:
/// Nullable:False
/// </summary>
[SugarColumn(IsPrimaryKey=true,ColumnName="monitor_id")]
public string monitorId {get;set;}
/// <summary>
/// Desc:采集设备编号
/// Default:
/// Nullable:True
/// </summary>
[SugarColumn(ColumnName="collect_device_id")]
public string collectDeviceId {get;set;}
/// <summary>
/// 触发规则0大于 1小于
/// </summary>
[SugarColumn(ColumnName = "alarm_type")]
public int triggerRule { get; set; }
/// <summary>
/// 监测字段0温度1湿度2振动-速度(mm/s)3振动-位移(um)4振动-加速度(g)5振动-温度(℃),6-噪音7-照度)
/// </summary>
[SugarColumn(ColumnName = "cause")]
public int monitorField { get;set; }
/// <summary>
/// 告警值
/// </summary>
[SugarColumn(ColumnName = "alarm_data")]
public decimal alarmValue { get;set; }
/// <summary>
/// 采集时间
///</summary>
[SugarColumn(ColumnName="collect_time" )]
public DateTime? collectTime { get; set; }
}

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

@ -0,0 +1,9 @@
using Sln.Iot.Model.dao;
using Sln.Iot.Repository.service.@base;
namespace Sln.Iot.Repository.service;
public interface IRecordAlarmDataService:IBaseService<RecordAlarmData>
{
}

@ -0,0 +1,36 @@
#region << 版 本 注 释 >>
/*--------------------------------------------------------------------
* (c) 2025 Wen JY
* CLR4.0.30319.42000
* ThinkPad T14
* Sln.Iot.Repository.service.Impl
* 0838E02D-6FDB-4D1D-8A1F-B78B582EE185
*
* WenJY
*
* 2025-06-05 10:46:10
* V1.0.0
*
*
*--------------------------------------------------------------------
*
*
*
*
* V1.0.0
*--------------------------------------------------------------------*/
#endregion << 版 本 注 释 >>
using Sln.Iot.Model.dao;
using Sln.Iot.Repository.service.@base;
namespace Sln.Iot.Repository.service.Impl;
public class RecordAlarmDataServiceImpl: BaseServiceImpl<RecordAlarmData>, IRecordAlarmDataService
{
public RecordAlarmDataServiceImpl(Repository<RecordAlarmData> rep) : base(rep)
{
}
}

@ -1,198 +0,0 @@
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);
}
}
}
}

@ -1,28 +0,0 @@
<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.

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

@ -19,8 +19,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sln.Iot.Serilog", "Sln.Iot.
EndProject
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
Debug|Any CPU = Debug|Any CPU
@ -59,10 +57,6 @@ 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,10 +7,7 @@ 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
{
@ -78,9 +75,6 @@ namespace Sln.Iot
);
}
};
ServiceProvider.UseSerialPortExtensions();
await Task.Delay(-1);
}

@ -14,7 +14,6 @@
<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>
@ -28,9 +27,6 @@
<None Update="appsettings.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="libnserial.so.1">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>

Binary file not shown.
Loading…
Cancel
Save