CFXTest
SoulStar 5 months ago
parent e988a202d7
commit be8880f11d

Binary file not shown.

@ -1,76 +0,0 @@
#region << 版 本 注 释 >>
/*--------------------------------------------------------------------
* (c) 2025 WenJY
* CLR4.0.30319.42000
* Mr.Wen's MacBook Pro
* Sln.Iot.Business
* 8BCBBC2D-F2EB-45A3-9DBA-24217C772093
*
* WenJY
*
* 2025-05-07 13:44:30
* V1.0.0
*
*
*--------------------------------------------------------------------
*
*
*
*
* V1.0.0
*--------------------------------------------------------------------*/
#endregion << 版 本 注 释 >>
using System;
using Sln.Iot.Business.@base;
using Sln.Iot.Common;
using Sln.Iot.Config;
using Sln.Iot.Model.dto;
using Sln.Iot.Serilog;
using Sln.Iot.Socket.Adapter;
using TouchSocket.Core;
using TouchSocket.Sockets;
namespace Sln.Iot.Business
{
/// <summary>
/// 校时指令
/// </summary>
public class CheckTimeBusiness:BaseBusiness
{
public CheckTimeBusiness(SerilogHelper logger, AppConfig appConfig, StringChange stringChange) : base(logger, appConfig, stringChange)
{
}
public override FilterResult BufferAnalysis(ISocketClient client, BufferRequestInfo requestInfo, int bodyLength)
{
ResponsePack sendResponsePackInfo = new ResponsePack()
{
m_MessageType = 0x08,
m_PackLen = new byte[] {0x00, 0x06}
};
base.GetMessagePack(ref sendResponsePackInfo,requestInfo.buffer);
DateTime currentTime = DateTime.Now;
byte[] timeBuffer = new byte[]
{
base._stringChange.HexStrTorbytes(currentTime.ToString("ss"))[0],
base._stringChange.HexStrTorbytes(currentTime.ToString("mm"))[0],
base._stringChange.HexStrTorbytes(currentTime.ToString("HH"))[0],
base._stringChange.HexStrTorbytes(currentTime.ToString("dd"))[0],
base._stringChange.HexStrTorbytes(currentTime.ToString("MM"))[0],
base._stringChange.HexStrTorbytes(currentTime.ToString("yy"))[0],
};
base.SendMessageAsync(client, sendResponsePackInfo,timeBuffer);
return FilterResult.Success;
}
public override void ResponseHandle(ISocketClient client, byte[] buffer)
{
//校时指令通过业务数据返回
}
}
}

@ -1,299 +0,0 @@
#region << 版 本 注 释 >>
/*--------------------------------------------------------------------
* (c) 2025 WenJY
* CLR4.0.30319.42000
* Mr.Wen's MacBook Pro
* Sln.Iot.Business
* F35152F4-9983-4881-AB1C-F9561EFAF534
*
* WenJY
*
* 2025-05-20 10:30:12
* V1.0.0
*
*
*--------------------------------------------------------------------
*
*
*
*
* V1.0.0
*--------------------------------------------------------------------*/
#endregion << 版 本 注 释 >>
using System;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
using Sln.Iot.Business.@base;
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 Sln.Iot.Socket.Adapter;
using TouchSocket.Core;
using TouchSocket.Sockets;
namespace Sln.Iot.Business
{
/// <summary>
/// 电能数据
/// </summary>
public class ElectricBusiness:BaseBusiness
{
private Dictionary<string ,DateTime> _lastCollectTimeDict = new Dictionary<string, DateTime>();
private readonly IRecordDnbInstantService? _service;
public ElectricBusiness(SerilogHelper logger, AppConfig appConfig, StringChange stringChange, IRecordDnbInstantService? service) : base(logger, appConfig, stringChange)
{
_service = service;
}
public override FilterResult BufferAnalysis(ISocketClient client, BufferRequestInfo requestInfo, int bodyLength)
{
ByteBlock byteBlock = new ByteBlock(requestInfo.Body);
if (byteBlock.CanReadLen < 1)
{
return FilterResult.Cache;
}
int pos = byteBlock.Pos;
try
{
List<RecordDnbInstant> result = new List<RecordDnbInstant>();
var amount = requestInfo.BufferLength / bodyLength;
_logger.Info($"收到{amount}个电表数据,开始循环解析......");
for (int i = 0; i < amount; i++)
{
RecordDnbInstant dnbInstant = new RecordDnbInstant();
#region 表号解析
byteBlock.Read(out byte[] b_MeterID, 2);
var decParts = b_MeterID.Select(b => $"{b:D2}").ToArray();
var equipId = $"{requestInfo.ColletEquipCode}_{decParts[0]}{decParts[1]}";
#endregion
dnbInstant.monitorId = equipId;
do
{
byteBlock.Read(out byte[] b_UA_flag, 2);
base._stringChange.ConvertBytesToUInt16(b_UA_flag, out uint flag);
switch (flag)
{
case CommParams.AU: //A项电压
byteBlock.Read(out byte[] b_UA, 4);
base._stringChange.SwapBytes(ref b_UA);
float f_UA = BitConverter.ToSingle(b_UA, 0);
ValueIsNan(ref f_UA);
dnbInstant.vA = (decimal) f_UA;
break;
case CommParams.BU: //B项电压
byteBlock.Read(out byte[] b_UB, 4);
base._stringChange.SwapBytes(ref b_UB);
float f_UB = BitConverter.ToSingle(b_UB, 0);
ValueIsNan(ref f_UB);
dnbInstant.vB = (decimal) f_UB;
break;
case CommParams.CU: //C项电压
byteBlock.Read(out byte[] b_UC, 4);
base._stringChange.SwapBytes(ref b_UC);
float f_UC = BitConverter.ToSingle(b_UC, 0);
ValueIsNan(ref f_UC);
dnbInstant.vC = (decimal) f_UC;
break;
case CommParams.AI: //A项电流
byteBlock.Read(out byte[] b_IA, 4);
base._stringChange.SwapBytes(ref b_IA);
float f_IA = BitConverter.ToSingle(b_IA, 0);
ValueIsNan(ref f_IA);
dnbInstant.iA = (decimal) f_IA;
break;
case CommParams.BI: //B项电流
byteBlock.Read(out byte[] b_IB, 4);
base._stringChange.SwapBytes(ref b_IB);
float f_IB = BitConverter.ToSingle(b_IB, 0);
ValueIsNan(ref f_IB);
dnbInstant.iB = (decimal) f_IB;
break;
case CommParams.CI: //C项电流
byteBlock.Read(out byte[] b_IC, 4);
base._stringChange.SwapBytes(ref b_IC);
float f_IC = BitConverter.ToSingle(b_IC, 0);
ValueIsNan(ref f_IC);
dnbInstant.iC = (decimal) f_IC;
break;
case CommParams.GLYS: //功率因数
byteBlock.Read(out byte[] b_GLYS, 4);
base._stringChange.SwapBytes(ref b_GLYS);
float f_GLYS = BitConverter.ToSingle(b_GLYS, 0);
ValueIsNan(ref f_GLYS);
dnbInstant.powerFactor = (decimal) f_GLYS;
break;
case CommParams.YGGL: //有功功率
byteBlock.Read(out byte[] b_YGGL, 4);
base._stringChange.SwapBytes(ref b_YGGL);
float f_YGGL = BitConverter.ToSingle(b_YGGL, 0);
ValueIsNan(ref f_YGGL);
dnbInstant.activePower = Convert.ToDecimal(f_YGGL / 1000);
break;
case CommParams.WGGL: //无功功率
byteBlock.Read(out byte[] b_WGGL, 4);
base._stringChange.SwapBytes(ref b_WGGL);
float f_WGGL = BitConverter.ToSingle(b_WGGL, 0);
ValueIsNan(ref f_WGGL);
dnbInstant.reactivePower = (decimal) f_WGGL;
break;
case CommParams.ZXYGZ: //正向有功
byteBlock.Read(out byte[] b_ZXYGZ, 4);
base._stringChange.SwapBytes(ref b_ZXYGZ);
float f_ZXYGZ = BitConverter.ToSingle(b_ZXYGZ, 0);
ValueIsNan(ref f_ZXYGZ);
dnbInstant.positiveActive = (decimal) f_ZXYGZ;
break;
case CommParams.CJSJ: //采集时间
byteBlock.Read(out byte[] b_CJSJ, 6);
string strDateTime = "20" + b_CJSJ[5].ToString("x2")
+ "-" + b_CJSJ[4].ToString("x2")
+ "-" + b_CJSJ[3].ToString("x2")
+ " " + b_CJSJ[2].ToString("x2")
+ ":" + b_CJSJ[1].ToString("x2")
+ ":" + b_CJSJ[0].ToString("x2");
dnbInstant.collectTime = Convert.ToDateTime(strDateTime);
break;
}
} while (byteBlock.Pos % bodyLength != 0);
dnbInstant.recordTime = DateTime.Now;
var serializeObject = JsonConvert.SerializeObject(dnbInstant);
_logger.Info($"第{i+1}个电表{dnbInstant.monitorId}解析完成:{serializeObject}");
DateTime? lastCollectTime = GetLastCollectTime(dnbInstant.monitorId);
if (lastCollectTime != null && DateTime.Now -lastCollectTime < TimeSpan.FromMinutes(_appConfig.electricTimeInterval))
{
//时间间隔小于采集间隔,不保存
continue;
}
// 如果字典中已有该键,则更新;否则新增
_lastCollectTimeDict[dnbInstant.monitorId] = DateTime.Now;
result.Add(dnbInstant);
}
if (result.Count > 0)
{
//是否开启 FF 异常值过滤
if (_appConfig.virtualFlag)
{
ParamVerification(ref result);
}
var inRes = _service.SplitInsert(result,out List<long> insertIds);
_logger.Info($"{result.Count}个电表数据解析处理完成,数据保存{(inRes ? "" : "")}");
}
else
{
_logger.Info($"{amount}个电表数据解析处理完成,没有需要保存的数据");
}
return FilterResult.Success;
}
catch (Exception e)
{
base._logger.Error($"电能数据解析异常:{e.Message}");
}
return FilterResult.Cache;
}
/// <summary>
/// FF FF参数过滤
/// </summary>
/// <param name="dnbInstants"></param>
/// <exception cref="ArgumentNullException"></exception>
private void ParamVerification(ref List<RecordDnbInstant> dnbInstants)
{
if (dnbInstants == null)
{
throw new ArgumentNullException($"过滤参数方法异常,传入参数为空");
}
for (int i = dnbInstants.Count - 1; i >= 0; i--)
{
var item = dnbInstants[i];
if (item.positiveActive == _appConfig.virtualValue)
{
_logger.Info($"MonitorId:{item.monitorId},正向有功为 FF FF FF FF已启用过滤不保存该表数据");
dnbInstants.RemoveAt(i);
continue;
}
}
}
private DateTime? GetLastCollectTime(string key)
{
// 检查键是否存在
if (_lastCollectTimeDict.TryGetValue(key, out DateTime collectTime))
{
return collectTime;
}
else
{
return null;
}
}
/// <summary>
/// 应答处理
/// </summary>
/// <param name="client"></param>
/// <param name="buffer"></param>
public override void ResponseHandle(ISocketClient client, byte[] buffer)
{
ResponsePack sendResponsePackInfo = new ResponsePack()
{
m_MessageType = 0xB3
};
base.GetMessagePack(ref sendResponsePackInfo, buffer);
base.SendMessageAsync(client,sendResponsePackInfo);
}
}
}

@ -1,276 +0,0 @@
#region << 版 本 注 释 >>
/*--------------------------------------------------------------------
* (c) 2025 WenJY
* CLR4.0.30319.42000
* Mr.Wen's MacBook Pro
* Sln.Iot.Business
* D5F7092D-7C5C-42B9-A373-1332CFD77169
*
* WenJY
*
* 2025-05-20 14:45:41
* V1.0.0
*
*
*--------------------------------------------------------------------
*
*
*
*
* V1.0.0
*--------------------------------------------------------------------*/
#endregion << 版 本 注 释 >>
using System;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
using Sln.Iot.Business.@base;
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 Sln.Iot.Socket.Adapter;
using TouchSocket.Core;
using TouchSocket.Sockets;
namespace Sln.Iot.Business
{
public class FluidBusiness:BaseBusiness
{
private Dictionary<string ,DateTime> _lastCollectTimeDict = new Dictionary<string, DateTime>();
private readonly IRecordFluidInstantService? _service;
public FluidBusiness(SerilogHelper logger, AppConfig appConfig, StringChange stringChange, IRecordFluidInstantService? service) : base(logger, appConfig, stringChange)
{
_service = service;
}
public override FilterResult BufferAnalysis(ISocketClient client, BufferRequestInfo requestInfo, int bodyLength)
{
ByteBlock byteBlock = new ByteBlock(requestInfo.Body);
if (byteBlock.CanReadLen < 1)
{
return FilterResult.Cache;
}
int pos = byteBlock.Pos;
try
{
List<RecordFluidInstant> result = new List<RecordFluidInstant>();
var amount = requestInfo.BufferLength / bodyLength;
_logger.Info($"收到{amount}个流体数据,开始循环解析......");
for (int i = 0; i < amount; i++)
{
RecordFluidInstant fluidInstant = new RecordFluidInstant();
#region 表号解析
byteBlock.Read(out byte[] b_MeterID, 2);
var decParts = b_MeterID.Select(b => $"{b:D2}").ToArray();
var equipId = $"{requestInfo.ColletEquipCode}_{decParts[0]}{decParts[1]}";
#endregion
fluidInstant.monitorId = equipId;
do
{
byteBlock.Read(out byte[] b_UA_flag, 2);
base._stringChange.ConvertBytesToUInt16(b_UA_flag, out uint flag);
switch (flag)
{
case CommParams.Press: //压力值
byteBlock.Read(out byte[] b_Press, 4);
base._stringChange.SwapBytes(ref b_Press);
float f_Press = BitConverter.ToSingle(b_Press, 0);
ValueIsNan(ref f_Press);
fluidInstant.press = (decimal)f_Press;
break;
case CommParams.STemperature: //温度值
byteBlock.Read(out byte[] b_Temperature, 4);
base._stringChange.SwapBytes(ref b_Temperature);
float f_Temperature = BitConverter.ToSingle(b_Temperature, 0);
ValueIsNan(ref f_Temperature);
fluidInstant.temperature = (decimal)f_Temperature;
break;
case CommParams.Frequency: //频率值
byteBlock.Read(out byte[] b_Frequency, 4);
base._stringChange.SwapBytes(ref b_Frequency);
float f_Frequency = BitConverter.ToSingle(b_Frequency, 0);
ValueIsNan(ref f_Frequency);
fluidInstant.frequency = (decimal)f_Frequency;
break;
case CommParams.Density: //密度值
byteBlock.Read(out byte[] b_Density, 4);
base._stringChange.SwapBytes(ref b_Density);
float f_Density = BitConverter.ToSingle(b_Density, 0);
ValueIsNan(ref f_Density);
fluidInstant.density = (decimal)f_Density;
break;
case CommParams.FluxInstantValue: //瞬时流值
byteBlock.Read(out byte[] b_FluxInstantValue, 4);
base._stringChange.SwapBytes(ref b_FluxInstantValue);
float f_FluxInstantValue = BitConverter.ToSingle(b_FluxInstantValue, 0);
ValueIsNan(ref f_FluxInstantValue);
fluidInstant.instantFlow = (decimal)f_FluxInstantValue;
break;
case CommParams.FluxEyeableTotalValue: //累计流量值
byteBlock.Read(out byte[] b_FluxEyeableTotalValue, 4);
base._stringChange.SwapBytes(ref b_FluxEyeableTotalValue);
float f_FluxEyeableTotalValue = BitConverter.ToSingle(b_FluxEyeableTotalValue, 0);
ValueIsNan(ref f_FluxEyeableTotalValue);
fluidInstant.totalFlow = (decimal)f_FluxEyeableTotalValue;
break;
case CommParams.HeatInstantValue: //瞬时热量
byteBlock.Read(out byte[] b_HeatInstantValue, 4);
base._stringChange.SwapBytes(ref b_HeatInstantValue);
float f_HeatInstantValue = BitConverter.ToSingle(b_HeatInstantValue, 0);
ValueIsNan(ref f_HeatInstantValue);
fluidInstant.instantHeat = (decimal)f_HeatInstantValue;
break;
case CommParams.HeatToftalValue: //累计热量值
byteBlock.Read(out byte[] b_HeatToftalValue, 4);
base._stringChange.SwapBytes(ref b_HeatToftalValue);
float f_HeatToftalValue = BitConverter.ToSingle(b_HeatToftalValue, 0);
ValueIsNan(ref f_HeatToftalValue);
fluidInstant.totalHeat = (decimal)f_HeatToftalValue;
break;
case CommParams.CJSJ: //采集时间
byteBlock.Read(out byte[] b_CJSJ, 6);
string strDateTime = "20" + b_CJSJ[5].ToString("x2")
+ "-" + b_CJSJ[4].ToString("x2")
+ "-" + b_CJSJ[3].ToString("x2")
+ " " + b_CJSJ[2].ToString("x2")
+ ":" + b_CJSJ[1].ToString("x2")
+ ":" + b_CJSJ[0].ToString("x2");
fluidInstant.collectTime = Convert.ToDateTime(strDateTime);
break;
}
} while (byteBlock.Pos % bodyLength != 0);
fluidInstant.recordTime = DateTime.Now;
var serializeObject = JsonConvert.SerializeObject(fluidInstant);
_logger.Info($"第{i+1}个流体仪表{fluidInstant.monitorId}解析完成:{serializeObject}");
DateTime? lastCollectTime = GetLastCollectTime(fluidInstant.monitorId);
if (lastCollectTime != null && DateTime.Now -lastCollectTime < TimeSpan.FromMinutes(_appConfig.fluidTimeInterval))
{
//时间间隔小于采集间隔,不保存
continue;
}
// 如果字典中已有该键,则更新;否则新增
_lastCollectTimeDict[fluidInstant.monitorId] = DateTime.Now;
result.Add(fluidInstant);
}
if (result.Count > 0)
{
//是否开启 FF 异常值过滤
if (_appConfig.virtualFlag)
{
ParamVerification(ref result);
}
var inRes = _service.SplitInsert(result,out List<long> insertIds);
_logger.Info($"{result.Count}个流体数据解析处理完成,数据保存{(inRes ? "" : "")}");
}
else
{
_logger.Info($"{amount}个流体数据解析处理完成,没有需要保存的数据");
}
return FilterResult.Success;
}
catch (Exception e)
{
base._logger.Error($"流体数据解析异常:{e.Message}");
}
return FilterResult.Cache;
}
/// <summary>
/// FF FF参数过滤
/// </summary>
/// <param name="dnbInstants"></param>
/// <exception cref="ArgumentNullException"></exception>
private void ParamVerification(ref List<RecordFluidInstant> fluidInstants)
{
if (fluidInstants == null)
{
throw new ArgumentNullException($"过滤参数方法异常,传入参数为空");
}
for (int i = fluidInstants.Count - 1; i >= 0; i--)
{
var item = fluidInstants[i];
if (item.totalFlow == _appConfig.virtualValue)
{
_logger.Info($"MonitorId:{item.monitorId},累计流量为 FF FF FF FF已启用过滤不保存该表数据");
fluidInstants.RemoveAt(i);
continue;
}
}
}
private DateTime? GetLastCollectTime(string key)
{
// 检查键是否存在
if (_lastCollectTimeDict.TryGetValue(key, out DateTime collectTime))
{
return collectTime;
}
else
{
return null;
}
}
/// <summary>
/// 应答处理
/// </summary>
/// <param name="client"></param>
/// <param name="buffer"></param>
public override void ResponseHandle(ISocketClient client, byte[] buffer)
{
ResponsePack sendResponsePackInfo = new ResponsePack()
{
m_MessageType = 0xB4
};
base.GetMessagePack(ref sendResponsePackInfo, buffer);
base.SendMessageAsync(client, sendResponsePackInfo);
}
}
}

@ -1,79 +0,0 @@
#region << 版 本 注 释 >>
/*--------------------------------------------------------------------
* (c) 2025 WenJY
* CLR4.0.30319.42000
* Mr.Wen's MacBook Pro
* Sln.Iot.Business
* AF7CD4B2-87AF-4F91-BECA-13779B05170C
*
* WenJY
*
* 2025-04-11 16:04:07
* V1.0.0
*
*
*--------------------------------------------------------------------
*
*
*
*
* V1.0.0
*--------------------------------------------------------------------*/
#endregion << 版 本 注 释 >>
using Sln.Iot.Business.@base;
using Sln.Iot.Common;
using Sln.Iot.Config;
using Sln.Iot.Model.dto;
using Sln.Iot.Serilog;
using Sln.Iot.Socket.Adapter;
using TouchSocket.Core;
using TouchSocket.Sockets;
namespace Sln.Iot.Business
{
/// <summary>
/// 心跳指令
/// </summary>
public class HeartBusiness:BaseBusiness
{
public HeartBusiness(SerilogHelper logger, AppConfig appConfig,StringChange stringChange) : base(logger, appConfig,stringChange)
{
}
public override FilterResult BufferAnalysis(ISocketClient client, BufferRequestInfo requestInfo, int bodyLength)
{
//心跳没有业务逻辑处理
return FilterResult.Success;
}
/// <summary>
/// 应答处理
/// </summary>
/// <param name="client"></param>
/// <param name="buffer"></param>
public override void ResponseHandle(ISocketClient client, byte[] buffer)
{
ResponsePack sendResponsePackInfo = new ResponsePack()
{
m_MessageType = 0xA4
};
base.GetMessagePack(ref sendResponsePackInfo,buffer);
//ByteBlock byteBlock = new ByteBlock(requestInfo.Body);
//byteBlock.Read(out byte[] b_MeterID, 2);
//var MeterID_1 = "00" + Convert.ToInt32(b_MeterID[0]).ToString();
//MeterID_1 = MeterID_1.Substring(MeterID_1.Length - 2, 2);
//var MeterID_2 = "00" + Convert.ToInt32(b_MeterID[1]).ToString();
//MeterID_2 = MeterID_2.Substring(MeterID_2.Length - 2, 2);
//var equipId = requestInfo.ColletEquipCOde + "_" + MeterID_1 + MeterID_2;
//Console.WriteLine($"心跳:::::{}");
base.SendMessageAsync(client, sendResponsePackInfo);
}
}
}

@ -1,478 +0,0 @@
#region << 版 本 注 释 >>
/*--------------------------------------------------------------------
* (c) 2025 WenJY
* CLR4.0.30319.42000
* Mr.Wen's MacBook Pro
* Sln.Iot.Business
* 7C26094C-5352-4997-866A-FA618F2E5D27
*
* WenJY
*
* 2025-04-11 15:47:06
* V1.0.0
*
*
*--------------------------------------------------------------------
*
*
*
*
* V1.0.0
*--------------------------------------------------------------------*/
#endregion << 版 本 注 释 >>
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;
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 Sln.Iot.Socket;
using Sln.Iot.Socket.Adapter;
using TouchSocket.Core;
using TouchSocket.Sockets;
namespace Sln.Iot.Business
{
/// <summary>
/// 物联网环境:温度、湿度、照度、噪音、振动
/// </summary>
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,
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)
{
ByteBlock byteBlock = new ByteBlock(requestInfo.Body);
if (byteBlock.CanReadLen < 1)
{
return FilterResult.Cache;
}
int pos = byteBlock.Pos;
try
{
List<RecordIotEnvInstant> result = new List<RecordIotEnvInstant>();
var amount = requestInfo.BufferLength / bodyLength;
_logger.Info($"收到{amount}个物联网环境数据,开始循环解析......");
for (int i = 0; i < amount; i++)
{
RecordIotEnvInstant iotEnvInstant = new RecordIotEnvInstant();
#region 表号解析 Add By Wenjy 2024-04-18
// byteBlock.Read(out byte[] b_MeterID, 2);
// var MeterID_1 = "00" + Convert.ToInt32(b_MeterID[0]).ToString();
// MeterID_1 = MeterID_1.Substring(MeterID_1.Length - 2, 2);
// var MeterID_2 = "00" + Convert.ToInt32(b_MeterID[1]).ToString();
// MeterID_2 = MeterID_2.Substring(MeterID_2.Length - 2, 2);
// var equipId = requestInfo.ColletEquipCode + "_" + MeterID_1 + MeterID_2;
#endregion
#region 表号解析
byteBlock.Read(out byte[] b_MeterID, 2);
var decParts = b_MeterID.Select(b => $"{b:D2}").ToArray();
var equipId = $"{requestInfo.ColletEquipCode}_{decParts[0]}{decParts[1]}";
#endregion
iotEnvInstant.monitorId = equipId;
#region 物联网参数解析 Edit By Wenjy 2025-05-07 修改 Nan 值过滤
do
{
byteBlock.Read(out byte[] b_UA_flag, 2);
base._stringChange.ConvertBytesToUInt16(b_UA_flag, out uint flag);
switch (flag)
{
case CommParams.TTempreture: //温度
byteBlock.Read(out byte[] tempreture, 4);
base._stringChange.SwapBytes(ref tempreture);
float f_tempreture = BitConverter.ToSingle(tempreture, 0);
ValueIsNan(ref f_tempreture);
iotEnvInstant.temperature = (decimal) f_tempreture;
break;
case CommParams.Humidity: //湿度
byteBlock.Read(out byte[] humidity, 4);
base._stringChange.SwapBytes(ref humidity);
float f_humidity = BitConverter.ToSingle(humidity, 0);
ValueIsNan(ref f_humidity);
iotEnvInstant.humidity = (decimal) f_humidity;
break;
case CommParams.Noise: //噪音
byteBlock.Read(out byte[] noise, 4);
base._stringChange.SwapBytes(ref noise);
float f_noise = BitConverter.ToSingle(noise, 0);
ValueIsNan(ref f_noise);
iotEnvInstant.noise = (decimal) f_noise;
break;
case CommParams.VibrationSpeed: //振动-速度
byteBlock.Read(out byte[] vibrationSpeed, 4);
base._stringChange.SwapBytes(ref vibrationSpeed);
float f_vibrationSpeed = BitConverter.ToSingle(vibrationSpeed, 0);
ValueIsNan(ref f_vibrationSpeed);
iotEnvInstant.vibrationSpeed = (decimal) f_vibrationSpeed;
break;
case CommParams.VibrationDisplacement: //振动-位移
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;
break;
case CommParams.VibrationAcceleration: //振动-加速度
byteBlock.Read(out byte[] vibrationAcceleration, 4);
base._stringChange.SwapBytes(ref vibrationAcceleration);
float f_vibrationAcceleration = BitConverter.ToSingle(vibrationAcceleration, 0);
ValueIsNan(ref f_vibrationAcceleration);
iotEnvInstant.vibrationAcceleration = (decimal)f_vibrationAcceleration;
break;
case CommParams.VibrationTemp: //振动-温度
byteBlock.Read(out byte[] vibrationTemp, 4);
base._stringChange.SwapBytes(ref vibrationTemp);
float f_vibrationTemp = BitConverter.ToSingle(vibrationTemp, 0);
ValueIsNan(ref f_vibrationTemp);
iotEnvInstant.vibrationTemp = (decimal)f_vibrationTemp;
break;
case CommParams.CJSJ:
byteBlock.Read(out byte[] b_CJSJ, 6);
string strDateTime = "20" + b_CJSJ[5].ToString("x2")
+ "-" + b_CJSJ[4].ToString("x2")
+ "-" + b_CJSJ[3].ToString("x2")
+ " " + b_CJSJ[2].ToString("x2")
+ ":" + b_CJSJ[1].ToString("x2")
+ ":" + b_CJSJ[0].ToString("x2");
iotEnvInstant.collectTime = Convert.ToDateTime(strDateTime);
break;
}
} while (byteBlock.Pos % bodyLength != 0);
#endregion
iotEnvInstant.recordTime = DateTime.Now;
var serializeObject = JsonConvert.SerializeObject(iotEnvInstant);
_logger.Info($"第{i+1}个物联网表{iotEnvInstant.monitorId}解析完成:{serializeObject}");
result.Add(iotEnvInstant);
}
if (result.Count > 0)
{
//是否开启 FF 异常值过滤
if (_appConfig.virtualFlag)
{
ParamVerification(ref result);
}
SendData(result);
var inRes = _service.SplitInsert(result,out List<long> insertIds);
_logger.Info($"{amount}个物联网数据解析处理完成,保存{result.Count}个物联网数据,保存{(inRes ? "" : "")}");
ParamAlarmFilter(result);
}
else
{
_logger.Info($"{amount}个物联网数据解析处理完成,没有需要保存的数据");
}
return FilterResult.Success;
}
catch (Exception e)
{
base._logger.Error($"物联网数据解析异常:{e.Message}");
}
return FilterResult.Cache;
}
/// <summary>
/// 回复指令
/// </summary>
/// <param name="client"></param>
/// <param name="buffer"></param>
public override void ResponseHandle(ISocketClient client, byte[] buffer)
{
ResponsePack sendResponsePackInfo = new ResponsePack()
{
m_MessageType = 0xB5
};
base.GetMessagePack(ref sendResponsePackInfo, buffer);
base.SendMessageAsync(client,sendResponsePackInfo);
}
/// <summary>
/// FF FF参数过滤
/// </summary>
/// <param name="iotEnvInstants"></param>
/// <exception cref="ArgumentNullException"></exception>
private void ParamVerification(ref List<RecordIotEnvInstant> iotEnvInstants)
{
if (iotEnvInstants == null)
{
throw new ArgumentNullException($"过滤参数方法异常,传入参数为空");
}
for (int i = iotEnvInstants.Count - 1; i >= 0; i--)
{
var item = iotEnvInstants[i];
if (item.temperature == _appConfig.virtualValue)
{
_logger.Info($"MonitorId:{item.monitorId},温度值为 FF FF FF FF已启用过滤不保存该表数据");
iotEnvInstants.RemoveAt(i);
continue;
}
if (item.humidity == _appConfig.virtualValue)
{
_logger.Info($"MonitorId:{item.monitorId},湿度值为 FF FF FF FF已启用过滤不保存该表数据");
iotEnvInstants.RemoveAt(i);
continue;
}
if (item.noise == _appConfig.virtualValue)
{
_logger.Info($"MonitorId:{item.monitorId},噪音值为 FF FF FF FF已启用过滤不保存该表数据");
iotEnvInstants.RemoveAt(i);
continue;
}
if (item.vibrationSpeed == _appConfig.virtualValue)
{
_logger.Info($"MonitorId:{item.monitorId},振动速度值为 FF FF FF FF已启用过滤不保存该表数据");
iotEnvInstants.RemoveAt(i);
continue;
}
if (item.vibrationDisplacement == _appConfig.virtualValue)
{
_logger.Info($"MonitorId:{item.monitorId},振动位移值为 FF FF FF FF已启用过滤不保存该表数据");
iotEnvInstants.RemoveAt(i);
continue;
}
if (item.vibrationAcceleration == _appConfig.virtualValue)
{
_logger.Info($"MonitorId:{item.monitorId},振动加速度值为 FF FF FF FF已启用过滤不保存该表数据");
iotEnvInstants.RemoveAt(i);
continue;
}
if (item.vibrationTemp == _appConfig.virtualValue)
{
_logger.Info($"MonitorId:{item.monitorId},振动温度值为 FF FF FF FF已启用过滤不保存该表数据");
iotEnvInstants.RemoveAt(i);
continue;
}
}
}
/// <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);
}
}
}
}

@ -1,98 +0,0 @@
#region << 版 本 注 释 >>
/*--------------------------------------------------------------------
* (c) 2025 WenJY
* CLR4.0.30319.42000
* Mr.Wen's MacBook Pro
* Sln.Iot.Business
* 71034873-2FF6-4081-AC87-DFCCCCCF51F2
*
* WenJY
*
* 2025-04-11 16:03:28
* V1.0.0
*
*
*--------------------------------------------------------------------
*
*
*
*
* V1.0.0
*--------------------------------------------------------------------*/
#endregion << 版 本 注 释 >>
using System;
using Microsoft.Extensions.Logging;
using Sln.Iot.Business.@base;
using Sln.Iot.Common;
using Sln.Iot.Config;
using Sln.Iot.Model.dto;
using Sln.Iot.Serilog;
using Sln.Iot.Socket.Adapter;
using TouchSocket.Core;
using TouchSocket.Sockets;
namespace Sln.Iot.Business
{
/// <summary>
/// 登录指令
/// </summary>
public class LoginBusiness:BaseBusiness
{
public LoginBusiness(SerilogHelper logger, AppConfig appConfig,StringChange stringChange) : base(logger, appConfig,stringChange)
{
}
/// <summary>
/// 指令解析
/// </summary>
/// <param name="client"></param>
/// <param name="requestInfo"></param>
/// <param name="bodyLength"></param>
/// <returns></returns>
public override FilterResult BufferAnalysis(ISocketClient client, BufferRequestInfo requestInfo, int bodyLength)
{
var flag = "";
byte[] bDeviceType = new byte[1];
byte[] bDeviceID = new byte[2];
Array.Copy(requestInfo.buffer, 1, bDeviceType, 0, 1);
Array.Copy(requestInfo.buffer, 2, bDeviceID, 0, 2);
flag = base._stringChange.ConverToString(bDeviceType);
flag += base._stringChange.ConverToString(bDeviceID);
string clientIdStr = flag.ToString();
if (clientIdStr.Contains("45"))
{
if (client.Id != clientIdStr)
{
client.ResetId(clientIdStr);
//更新客户端状态
}
}
return FilterResult.Success;
}
/// <summary>
/// 应答处理
/// </summary>
/// <param name="client"></param>
/// <param name="buffer"></param>
public override void ResponseHandle(ISocketClient client, byte[] buffer)
{
ResponsePack sendResponsePackInfo = new ResponsePack()
{
m_MessageType = 0xA1
};
base.GetMessagePack(ref sendResponsePackInfo,buffer);
base.SendMessageAsync(client, sendResponsePackInfo);
}
}
}

@ -12,7 +12,6 @@
<ItemGroup>
<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.Serilog\Sln.Iot.Serilog.csproj" />
<ProjectReference Include="..\Sln.Iot.Socket\Sln.Iot.Socket.csproj" />

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

@ -1,156 +0,0 @@
#region << 版 本 注 释 >>
/*--------------------------------------------------------------------
* (c) 2025 WenJY
* CLR4.0.30319.42000
* Mr.Wen's MacBook Pro
* Sln.Iot.Business.base
* AA8CCDD9-6D6B-47B7-8309-5C9D41FFC822
*
* WenJY
*
* 2025-04-11 15:04:43
* V1.0.0
*
*
*--------------------------------------------------------------------
*
*
*
*
* V1.0.0
*--------------------------------------------------------------------*/
#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;
namespace Sln.Iot.Business.@base
{
public abstract class BaseBusiness
{
public SerilogHelper _logger;
public AppConfig _appConfig;
public StringChange _stringChange;
public BaseBusiness(SerilogHelper logger,AppConfig appConfig,StringChange stringChange)
{
_logger = logger;
_appConfig = appConfig;
_stringChange = stringChange;
}
/// <summary>
/// 指令解析方法
/// </summary>
/// <param name="client"></param>
/// <param name="requestInfo"></param>
public abstract FilterResult BufferAnalysis(ISocketClient client,BufferRequestInfo requestInfo,int bodyLength);
/// <summary>
/// 应答响应
/// </summary>
/// <param name="client"></param>
/// <param name="messagePack"></param>
public abstract void ResponseHandle(ISocketClient client, byte[] buffer);
/// <summary>
/// 封装回复指令
/// </summary>
/// <param name="SendMessagePackInfo"></param>
/// <param name="buffer"></param>
public void GetMessagePack(ref ResponsePack SendMessagePackInfo,byte[] buffer)
{
SendMessagePackInfo.m_EnergyType = buffer[1];
Array.Copy(buffer, 2, SendMessagePackInfo.m_Meteraddr, 0, 2);
Array.Copy(buffer, 4, SendMessagePackInfo.m_Msta, 0, 2);
SendMessagePackInfo.m_StartFlag = buffer[6];
}
/// <summary>
/// 发送接收成功指令
/// </summary>
/// <param name="client"></param>
/// <param name="pMessagePack"></param>
/// <returns></returns>
public bool SendMessageAsync(ISocketClient client, ResponsePack pMessagePack,byte[] buffer = null)
{
ushort num = 0;
try
{
byte[] SendBuffer = new byte[12];
if (buffer != null)
{
SendBuffer = new byte[12 + buffer.Length];
}
SendBuffer[num] = pMessagePack.m_BeginChar;
num = (ushort)(num + 1);
SendBuffer[num] = pMessagePack.m_EnergyType;
num = (ushort)(num + 1);
Array.Copy(pMessagePack.m_Meteraddr, 0, SendBuffer, num, pMessagePack.m_Meteraddr.Length);
num = (ushort)(num + 2);
Array.Copy(pMessagePack.m_Msta, 0, SendBuffer, num, pMessagePack.m_Msta.Length);
num = (ushort)(num + 2);
SendBuffer[num] = pMessagePack.m_StartFlag;
num = (ushort)(num + 1);
SendBuffer[num] = pMessagePack.m_MessageType;
num = (ushort)(num + 1);
Array.Copy(pMessagePack.m_PackLen, 0, SendBuffer, num, pMessagePack.m_PackLen.Length);
num = (ushort)(num + 2);
if (buffer != null)
{
Array.Copy(buffer, 0, SendBuffer, num, buffer.Length);
num = (ushort)(num + buffer.Length);
}
pMessagePack.m_Verify = _stringChange.CalculateVerifyToArray(SendBuffer, SendBuffer.Length - 1)[0];
SendBuffer[num] = pMessagePack.m_Verify;
num = (ushort)(num + 1);
SendBuffer[num] = pMessagePack.m_EndChar;
_logger.Info($"向客户端:{client.Id};地址:{client.GetIPPort()};发送终端消息:{_stringChange.bytesToHexStr(SendBuffer, SendBuffer.Length)}");
client.SendAsync(SendBuffer);
return true;
}
catch (Exception ex)
{
_logger.Error($"SendMessageToClient异常{ex.Message}");
return false;
}
}
/// <summary>
/// Nan 值处理
/// </summary>
/// <param name="value"></param>
public void ValueIsNan(ref float value)
{
if (double.IsNaN(value))
{
if (_appConfig.virtualFlag)
{
value = _appConfig.virtualValue;
}
else
{
value = 0;
}
}
}
}
}

@ -0,0 +1,34 @@
using CFX;
using CFX.Transport;
namespace Sln.Iot.CFX
{
/// <summary>
/// CFX接口连接类
/// </summary>
public class CFXConnect
{
public AmqpCFXEndpoint Endpoint;
public CFXConnect()
{
OpenEndpoint();
}
public void OpenEndpoint()
{
try
{
Endpoint = new AmqpCFXEndpoint();
Endpoint.Open("CFX.S00.OT23022701", new Uri("amqp://"));
Endpoint.AddPublishChannel(new Uri("amqp://"), "eventAddress");
}
catch (Exception e)
{
}
}
}
}

@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="CFX.CFXSDK" Version="2.0.5" />
</ItemGroup>
</Project>

@ -35,45 +35,11 @@ namespace Sln.Iot.Config
/// </summary>
public string logPath { get; set; }
/// <summary>
/// 监听端口
/// </summary>
public int listernPort { get; set; }
/// <summary>
/// 虚拟值用于过滤FFFFFF
/// </summary>
public long virtualValue { get; set; }
/// <summary>
/// 是否启用虚拟值
/// </summary>
public bool virtualFlag { get; set; }
/// <summary>
/// 电力数据采集间隔
/// </summary>
public int electricTimeInterval { get; set; }
/// <summary>
/// 流体数据采集间隔
/// </summary>
public int fluidTimeInterval { get; set; }
/// <summary>
/// Sql连接配置
/// </summary>
public List<SqlConfig> sqlConfig { get; set; }
/// <summary>
/// Redis配置
/// </summary>
public string redisConfig { get; set; }
/// <summary>
/// 串口配置
/// </summary>
public SerialPortConfig serialPortConfig { get; set; }
public AppConfig Value => this;
}

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

@ -10,4 +10,8 @@
<PackageReference Include="SqlSugarCore" Version="5.1.4.193" />
</ItemGroup>
<ItemGroup>
<Folder Include="dto\" />
</ItemGroup>
</Project>

@ -1,5 +1,4 @@
using SqlSugar;
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
@ -7,61 +6,9 @@ using System.Threading.Tasks;
namespace Sln.Iot.Model.dao
{
[SugarTable("ems_record_alarm_rule"), TenantAttribute("tao_iot")]
public class BaseAlarmRule
public class TrayRfidBinding
{
/// <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; }
/// <summary>
/// 告警记录ID推送数据使用ORM不用
/// </summary>
[SugarColumn(IsIgnore = true)]
public long alarmId { get; set; }
[PrimaryKey, AutoIncrement]
public long ID { get; set; }
}
}

@ -1,209 +0,0 @@
#region << 版 本 注 释 >>
/*--------------------------------------------------------------------
* (c) 2025 WenJY
* CLR4.0.30319.42000
* Mr.Wen's MacBook Pro
* Sln.Iot.Model.dao
* 74702D18-55B3-4AA3-91EB-E02ADC9AEBC8
*
* WenJY
*
* 2025-04-11 13:23:39
* V1.0.0
*
*
*--------------------------------------------------------------------
*
*
*
*
* V1.0.0
*--------------------------------------------------------------------*/
#endregion << 版 本 注 释 >>
using System;
using SqlSugar;
namespace Sln.Iot.Model.dao
{
///<summary>
///计量设备信息
///</summary>
[SugarTable("ems_base_monitor_info"), TenantAttribute("tao_iot")]
public partial class BaseMonitorInfo
{
public BaseMonitorInfo(){
}
/// <summary>
/// Desc:自增标识
/// Default:
/// Nullable:False
/// </summary>
[SugarColumn(IsPrimaryKey=true,IsIdentity=true,ColumnName="obj_id")]
public int objid {get;set;}
/// <summary>
/// Desc:父级编号
/// Default:
/// Nullable:True
/// </summary>
[SugarColumn(ColumnName="parent_id")]
public int? parentId {get;set;}
/// <summary>
/// Desc:计量设备编号
/// Default:
/// Nullable:False
/// </summary>
[SugarColumn(IsPrimaryKey=true,ColumnName="monitor_code")]
public string monitorId {get;set;}
/// <summary>
/// Desc:计量设备名称
/// Default:
/// Nullable:True
/// </summary>
[SugarColumn(ColumnName="monitor_name")]
public string monitorName {get;set;}
/// <summary>
/// Desc:计量设备位置
/// Default:
/// Nullable:True
/// </summary>
[SugarColumn(ColumnName="monitor_addr")]
public string monitorAddr {get;set;}
/// <summary>
/// Desc:计量设备类型
/// Default:
/// Nullable:True
/// </summary>
[SugarColumn(ColumnName="monitor_type")]
public int? monitorType {get;set;}
/// <summary>
/// Desc:计量设备状态
/// Default:0
/// Nullable:True
/// </summary>
[SugarColumn(ColumnName="monitor_status")]
public int? monitorStatus {get;set;}
/// <summary>
/// Desc:采集设备编号
/// Default:
/// Nullable:True
/// </summary>
[SugarColumn(ColumnName="collect_device_id")]
public string collectDeviceId {get;set;}
/// <summary>
/// Desc:祖级列表
/// Default:
/// Nullable:True
/// </summary>
[SugarColumn(ColumnName="ancestors")]
public string ancestors {get;set;}
/// <summary>
/// Desc:等级
/// Default:
/// Nullable:True
/// </summary>
[SugarColumn(ColumnName="grade")]
public int? grade {get;set;}
/// <summary>
/// Desc:传感器仪表
/// Default:
/// Nullable:True
/// </summary>
[SugarColumn(ColumnName="meter_type_id")]
public string meterTypeId {get;set;}
/// <summary>
/// Desc:修正值
/// Default:
/// Nullable:True
/// </summary>
[SugarColumn(ColumnName="correct_value")]
public decimal? correctValue {get;set;}
/// <summary>
/// Desc:PT值
/// Default:
/// Nullable:True
/// </summary>
[SugarColumn(ColumnName="pt")]
public int? pt {get;set;}
/// <summary>
/// Desc:CT值
/// Default:
/// Nullable:True
/// </summary>
[SugarColumn(ColumnName="ct")]
public int? ct {get;set;}
/// <summary>
/// Desc:是否虚拟
/// Default:false
/// Nullable:True
/// </summary>
[SugarColumn(ColumnName="is_ammeter")]
public string isAmmeter {get;set;}
/// <summary>
/// Desc:通断复位
/// Default:
/// Nullable:True
/// </summary>
[SugarColumn(ColumnName="is_key_monitor")]
public int? isKeyMonitor {get;set;}
/// <summary>
/// Desc:是否断路
/// Default:
/// Nullable:True
/// </summary>
[SugarColumn(ColumnName="is_circuit")]
public int? isCircuit {get;set;}
/// <summary>
/// Desc:创建人
/// Default:
/// Nullable:True
/// </summary>
[SugarColumn(ColumnName="create_by")]
public string createBy {get;set;}
/// <summary>
/// Desc:创建时间
/// Default:CURRENT_TIMESTAMP
/// Nullable:True
/// </summary>
[SugarColumn(ColumnName="create_time")]
public DateTime? createTime {get;set;}
/// <summary>
/// Desc:更新人
/// Default:
/// Nullable:True
/// </summary>
[SugarColumn(ColumnName="update_by")]
public string updateBy {get;set;}
/// <summary>
/// Desc:更新时间
/// Default:
/// Nullable:True
/// </summary>
[SugarColumn(ColumnName="update_time")]
public DateTime? updateTime {get;set;}
}
}

@ -1,83 +0,0 @@
#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,132 +0,0 @@
#region << 版 本 注 释 >>
/*--------------------------------------------------------------------
* (c) 2025 WenJY
* CLR4.0.30319.42000
* Mr.Wen's MacBook Pro
* Sln.Iot.Model.dao
* B1423370-1BD2-4199-AEDC-80C06296A9BC
*
* WenJY
*
* 2025-05-20 10:57:48
* V1.0.0
*
*
*--------------------------------------------------------------------
*
*
*
*
* V1.0.0
*--------------------------------------------------------------------*/
#endregion << 版 本 注 释 >>
using System;
using SqlSugar;
namespace Sln.Iot.Model.dao
{
/// <summary>
/// 电实时数据
/// </summary>
[SplitTable(SplitType.Day)]
[SugarTable("record_dnb_instant_{year}{month}{day}"), TenantAttribute("tao_iot")]
public class RecordDnbInstant
{
/// <summary>
/// 编号
///</summary>
[SugarColumn(ColumnName="objid" ,IsPrimaryKey = true )]
public long objid { get; set; }
/// <summary>
/// 计量设备编号
///</summary>
[SugarColumn(ColumnName="monitor_id" )]
public string monitorId { get; set; }
/// <summary>
/// A项电压
///</summary>
[SugarColumn(ColumnName="va" )]
public decimal? vA { get; set; }
/// <summary>
/// B项电压
///</summary>
[SugarColumn(ColumnName="vb" )]
public decimal? vB { get; set; }
/// <summary>
/// C项电压
///</summary>
[SugarColumn(ColumnName="vc" )]
public decimal? vC { get; set; }
/// <summary>
/// A项电流
///</summary>
[SugarColumn(ColumnName="ia" )]
public decimal? iA { get; set; }
/// <summary>
/// B项电流
///</summary>
[SugarColumn(ColumnName="ib" )]
public decimal? iB { get; set; }
/// <summary>
/// C项电流
///</summary>
[SugarColumn(ColumnName="ic" )]
public decimal? iC { get; set; }
/// <summary>
/// 功率因数
///</summary>
[SugarColumn(ColumnName="glys" )]
public decimal? powerFactor { get; set; }
/// <summary>
/// 正向有功
///</summary>
[SugarColumn(ColumnName="zxyg" )]
public decimal? positiveActive { get; set; }
/// <summary>
/// 有功功率
///</summary>
[SugarColumn(ColumnName="active_power" )]
public decimal? activePower { get; set; }
/// <summary>
/// 无功功率
///</summary>
[SugarColumn(ColumnName="reactive_power" )]
public decimal? reactivePower { get; set; }
/// <summary>
/// 采集方式
/// 默认值: 0
///</summary>
[SugarColumn(ColumnName="collect_type" )]
public int collectType
{
get { return 1;}
}
/// <summary>
/// 采集时间
///</summary>
[SugarColumn(ColumnName="collect_time" )]
public DateTime? collectTime { get; set; }
/// <summary>
/// 记录时间
///</summary>
[SplitField]
[SugarColumn(ColumnName="record_time" )]
public DateTime? recordTime { get; set; }
}
}

@ -1,121 +0,0 @@
#region << 版 本 注 释 >>
/*--------------------------------------------------------------------
* (c) 2025 WenJY
* CLR4.0.30319.42000
* Mr.Wen's MacBook Pro
* Sln.Iot.Model.dao
* CB52EBBD-0D7F-498D-B2D0-B9926F06F5AF
*
* WenJY
*
* 2025-05-20 14:40:03
* V1.0.0
*
*
*--------------------------------------------------------------------
*
*
*
*
* V1.0.0
*--------------------------------------------------------------------*/
#endregion << 版 本 注 释 >>
using System;
using SqlSugar;
namespace Sln.Iot.Model.dao
{
/// <summary>
/// 流体实时数据
/// </summary>
[SplitTable(SplitType.Day)]
[SugarTable("record_fluid_instant_{year}{month}{day}"), Tenant("tao_iot")]
public class RecordFluidInstant
{
/// <summary>
/// 自增标识
///</summary>
[SugarColumn(ColumnName="objid" ,IsPrimaryKey = true )]
public long objid { get; set; }
/// <summary>
/// 计量设备编号
///</summary>
[SugarColumn(ColumnName="monitor_id" )]
public string monitorId { get; set; }
/// <summary>
/// 温度值
/// </summary>
[SugarColumn(ColumnName="temperature" )]
public decimal? temperature{get;set;}
/// <summary>
/// 压力值
/// </summary>
[SugarColumn(ColumnName="press" )]
public decimal? press{get;set;}
/// <summary>
/// 频率值
/// </summary>
[SugarColumn(ColumnName="frequency" )]
public decimal? frequency{get;set;}
/// <summary>
/// 密度值
/// </summary>
[SugarColumn(ColumnName="density" )]
public decimal? density{get;set;}
/// <summary>
/// 瞬时热量
///</summary>
[SugarColumn(ColumnName="instant_heat" )]
public decimal? instantHeat { get; set; }
/// <summary>
/// 累计热量
///</summary>
[SugarColumn(ColumnName="total_heat" )]
public decimal? totalHeat { get; set; }
/// <summary>
/// 瞬时流量
///</summary>
[SugarColumn(ColumnName="instant_flow" )]
public decimal? instantFlow { get; set; }
/// <summary>
/// 累计流量
///</summary>
[SugarColumn(ColumnName="total_flow" )]
public decimal? totalFlow { get; set; }
/// <summary>
/// 采集方式
/// 默认值: 0
///</summary>
[SugarColumn(ColumnName="collect_type" )]
public int collectType
{
get { return 1;}
}
/// <summary>
/// 采集时间
///</summary>
[SugarColumn(ColumnName="collect_time" )]
public DateTime? collectTime { get; set; }
/// <summary>
/// 记录时间
///</summary>
[SplitField]
[SugarColumn(ColumnName="record_time" )]
public DateTime? recordTime { get; set; }
}
}

@ -1,116 +0,0 @@
#region << 版 本 注 释 >>
/*--------------------------------------------------------------------
* (c) 2025 WenJY
* CLR4.0.30319.42000
* Mr.Wen's MacBook Pro
* Sln.Iot.Model.dao
* 2946BBED-E772-4BC4-953F-F4B9834C27F6
*
* WenJY
*
* 2025-04-11 15:20:56
* V1.0.0
*
*
*--------------------------------------------------------------------
*
*
*
*
* V1.0.0
*--------------------------------------------------------------------*/
#endregion << 版 本 注 释 >>
using System;
using SqlSugar;
namespace Sln.Iot.Model.dao
{
[SplitTable(SplitType.Day)]
[SugarTable("record_iotenv_instant_{year}{month}{day}"), TenantAttribute("tao_iot")]
public class RecordIotEnvInstant
{
/// <summary>
/// 编号 ,IsIdentity = true
///</summary>
[SugarColumn(ColumnName="objid" ,IsPrimaryKey = true )]
public long objid { get; set; }
/// <summary>
/// 计量设备编号
///</summary>
[SugarColumn(ColumnName="monitorId" )]
public string monitorId { get; set; }
/// <summary>
/// 温度
/// </summary>
[SugarColumn(ColumnName="temperature" )]
public decimal temperature { get; set; }
/// <summary>
/// 湿度
/// </summary>
[SugarColumn(ColumnName="humidity" )]
public decimal humidity { get; set; }
/// <summary>
/// 照度
/// </summary>
[SugarColumn(ColumnName="illuminance" )]
public decimal illuminance { get; set; }
/// <summary>
/// 噪音
/// </summary>
[SugarColumn(ColumnName="noise" )]
public decimal noise { get; set; }
/// <summary>
/// 气体浓度
/// </summary>
[SugarColumn(ColumnName="concentration" )]
public decimal concentration { get; set; }
/// <summary>
/// 振动-速度
/// </summary>
[SugarColumn(ColumnName = "vibration_speed")]
public decimal vibrationSpeed { get; set; }
/// <summary>
/// 振动-位移
/// </summary>
[SugarColumn(ColumnName = "vibration_displacement")]
public decimal vibrationDisplacement { get; set; }
/// <summary>
/// 振动-加速度
/// </summary>
[SugarColumn(ColumnName = "vibration_acceleration")]
public decimal vibrationAcceleration { get; set; }
/// <summary>
/// 振动-温度
/// </summary>
[SugarColumn(ColumnName = "vibration_temp")]
public decimal vibrationTemp { get; set; }
/// <summary>
/// 采集时间
///</summary>
[SugarColumn(ColumnName="collectTime" )]
public DateTime? collectTime { get; set; }
/// <summary>
/// 记录时间
///</summary>
[SplitField]
[SugarColumn(ColumnName="recodeTime" )]
public DateTime? recordTime { get; set; }
}
}

@ -1,101 +0,0 @@
#region << 版 本 注 释 >>
/*--------------------------------------------------------------------
* (c) 2025 WenJY
* CLR4.0.30319.42000
* Mr.Wen's MacBook Pro
* Sln.Iot.Model.dto
* CA8D9816-589C-4E15-96FD-CA864799054D
*
* WenJY
*
* 2025-04-11 15:10:04
* V1.0.0
*
*
*--------------------------------------------------------------------
*
*
*
*
* V1.0.0
*--------------------------------------------------------------------*/
#endregion << 版 本 注 释 >>
namespace Sln.Iot.Model.dto
{
public struct CommParams
{
/// <summary>
/// 温度
/// </summary>
public const uint TTempreture = 0x8E50;
/// <summary>
/// 湿度
/// </summary>
public const uint Humidity = 0x8E52;
/// <summary>
/// 噪音
/// </summary>
public const uint Noise = 0x8E53;
/// <summary>
/// 振动-速度
/// </summary>
public const uint VibrationSpeed = 0x8E55;
/// <summary>
/// 振动-位移
/// </summary>
public const uint VibrationDisplacement = 0x8E56;
/// <summary>
/// 振动-加速度
/// </summary>
public const uint VibrationAcceleration = 0x8E57;
/// <summary>
/// 振动-温度
/// </summary>
public const uint VibrationTemp = 0x8E54;
/// <summary>
/// 采集时间
/// </summary>
public const uint CJSJ = 0x8030;
#region 电能数据结构体
public const uint AI = 0x8E21;
public const uint BI = 0x8E22;
public const uint CI = 0x8E23;
public const uint AU = 0x8E11;
public const uint BU = 0x8E12;
public const uint CU = 0x8E13;
public const uint GLYS = 0xB650;
public const uint ZXYGZ = 0x9010;
public const uint ZXWG = 0x9030;
public const uint YGGL = 0xB651;
public const uint WGGL = 0xB652;
#endregion
#region 流体数据结构体
public const uint Press = 0x9B00;
public const uint STemperature = 0x9B01;
public const uint Frequency = 0x9B02;
public const uint FluxInstantValue = 0x9B03;
public const uint FluxEyeableTotalValue = 0x9B05;
public const uint HeatInstantValue = 0x9B06;
public const uint HeatToftalValue = 0x9B07;
public const uint Density = 0x9B0E;
#endregion
}
}

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

@ -1,40 +0,0 @@
#region << 版 本 注 释 >>
/*--------------------------------------------------------------------
* (c) 2025 WenJY
* CLR4.0.30319.42000
* Mr.Wen's MacBook Pro
* Sln.Iot.Model.dto
* CE889E7E-08A9-4043-A157-32CB2773E568
*
* WenJY
*
* 2025-04-11 15:08:47
* V1.0.0
*
*
*--------------------------------------------------------------------
*
*
*
*
* V1.0.0
*--------------------------------------------------------------------*/
#endregion << 版 本 注 释 >>
namespace Sln.Iot.Model.dto
{
public class ResponsePack
{
public byte m_BeginChar = 0x68; //帧头
public byte m_EnergyType; //能源类型
public byte[] m_Meteraddr = new byte[2];//地址
public byte[] m_Msta = new byte[2]; //命令序列号
public byte m_StartFlag; //起始符
public byte m_MessageType; //控制码
public byte[] m_PackLen = new byte[2]; //数据长度
public byte m_Verify;
public byte m_EndChar = 0x16; //尾盘
}
}

@ -1,42 +0,0 @@
#region << 版 本 注 释 >>
/*--------------------------------------------------------------------
* (c) 2025 WenJY
* CLR4.0.30319.42000
* Mr.Wen's MacBook Pro
* Sln.Iot.Model.dto
* CF7EE865-8FD7-4B6E-BD69-B86E09886CB6
*
* WenJY
*
* 2025-04-11 15:10:36
* V1.0.0
*
*
*--------------------------------------------------------------------
*
*
*
*
* V1.0.0
*--------------------------------------------------------------------*/
#endregion << 版 本 注 释 >>
using System;
namespace Sln.Iot.Model.dto
{
public class TagInfo
{
public byte[] PC = new byte[2];
public int Count { get; set; }
public int RSSI{ get; set; }
public int Antana{ get; set; }
public byte[] EPC{ get; set; }
public byte[] Data{ get; set; }
public string PCstring = (string) null;
public string EPCstring = (string) null;
public DateTime Time{ get; set; }
}
}

@ -0,0 +1,76 @@
using System.ComponentModel;
namespace Sln.Iot.PLC
{
/// <summary>
/// 数据类型
/// </summary>
public enum DataTypeEnum
{
/// <summary>
/// 未定义
/// </summary>
[Description("未定义")]
None = 0,
/// <summary>
/// Bool
/// </summary>
[Description("Bool")]
Bool = 1,
/// <summary>
/// Byte
/// </summary>
[Description("Byte")]
Byte = 2,
/// <summary>
/// Int16
/// </summary>
[Description("Int16")]
Int16 = 3,
/// <summary>
/// UInt16
/// </summary>
[Description("UInt16")]
UInt16 = 4,
/// <summary>
/// Int32
/// </summary>
[Description("Int32")]
Int32 = 5,
/// <summary>
/// UInt32
/// </summary>
[Description("UInt32")]
UInt32 = 6,
/// <summary>
/// Int64
/// </summary>
[Description("Int64")]
Int64 = 7,
/// <summary>
/// UInt64
/// </summary>
[Description("UInt64")]
UInt64 = 8,
/// <summary>
/// Float
/// </summary>
[Description("Float")]
Float = 9,
/// <summary>
/// Double
/// </summary>
[Description("Double")]
Double = 10,
/// <summary>
/// String
/// </summary>
[Description("String")]
String = 11,
/// <summary>
/// Bytes
/// </summary>
[Description("Bytes")]
Bytes = 12,
}
}

@ -0,0 +1,190 @@
using HslCommunication;
using HslCommunication.Profinet.Delta;
using Microsoft.Extensions.DependencyInjection;
using Serilog;
using Sln.Iot.Serilog;
namespace Sln.Iot.PLC
{
public class PLCConnect
{
private SerilogHelper? LogHelper;
public static DeltaSerialOverTcp DeltaInstance1;
/// <summary>
/// 锁对象1
/// </summary>
private static readonly object locker1 = new object();
public PLCConnect(SerilogHelper serilogHelper)
{
LogHelper = serilogHelper;
DeltaInstance1 = CreateDeltaConnect("127.0.0.1", 502, 1, serilogHelper);
}
/// <summary>
/// 创建台达PLC连接
/// </summary>
/// <param name="ip"></param>
/// <param name="port"></param>
/// <param name="stationNo"></param>
/// <param name="log"></param>
/// <returns></returns>
public static DeltaSerialOverTcp CreateDeltaConnect(string ip, int port, byte stationNo, SerilogHelper log)
{
DeltaSerialOverTcp plc = new DeltaSerialOverTcp(ip, port, stationNo);
try
{
var res = plc.ConnectServer();
}
catch (Exception ex)
{
log.Error($"连接PLC[{ip}]失败", ex);
}
return plc;
}
/// <summary>
/// PLC2写入数据
/// </summary>
/// <param name="address">地址</param>
/// <param name="value">值</param>
/// <param name="type">数据类型</param>
/// <returns></returns>
public static OperateResult PlcWrite(string address, object value, DataTypeEnum type)
{
var result = new OperateResult() { IsSuccess = false };
lock (locker1)
{
switch (type)
{
case DataTypeEnum.Bool:
result = DeltaInstance1.Write(address, Convert.ToBoolean(value));
break;
case DataTypeEnum.Byte:
result = DeltaInstance1.Write(address, Convert.ToByte(value));
break;
case DataTypeEnum.Int16:
result = DeltaInstance1.Write(address, Convert.ToInt16(value));
break;
case DataTypeEnum.UInt16:
result = DeltaInstance1.Write(address, Convert.ToUInt16(value));
break;
case DataTypeEnum.Int32:
result = DeltaInstance1.Write(address, Convert.ToInt32(value));
break;
case DataTypeEnum.UInt32:
result = DeltaInstance1.Write(address, Convert.ToUInt32(value));
break;
case DataTypeEnum.Int64:
result = DeltaInstance1.Write(address, Convert.ToInt64(value));
break;
case DataTypeEnum.UInt64:
result = DeltaInstance1.Write(address, Convert.ToUInt64(value));
break;
case DataTypeEnum.Float:
result = DeltaInstance1.Write(address, Convert.ToSingle(value));
break;
case DataTypeEnum.Double:
result = DeltaInstance1.Write(address, Convert.ToDouble(value));
break;
case DataTypeEnum.String:
result = DeltaInstance1.Write(address, Convert.ToString(value));
break;
default:
throw new ArgumentException($"Unsupported data type: {type}");
}
}
return result;
}
/// <summary>
/// 写入byte数组
/// </summary>
/// <param name="address"></param>
/// <param name="data"></param>
/// <returns></returns>
public static OperateResult PlcWriteBytes(string address, byte[] data)
{
lock (locker1)
{
var res = DeltaInstance1.Write(address, data);
return res;
}
}
/// <summary>
/// 读取int32
/// </summary>
/// <returns></returns>
public OperateResult<int> ReadInt32(string address)
{
lock (locker1)
{
var res = DeltaInstance1.ReadInt32(address);
return res;
}
}
/// <summary>
/// 读取int16
/// </summary>
/// <returns></returns>
public OperateResult<short> ReadInt16(string address)
{
lock (locker1)
{
var res = DeltaInstance1.ReadInt16(address);
return res;
}
}
/// <summary>
/// 读取float
/// </summary>
/// <param name="address"></param>
/// <returns></returns>
public OperateResult<float> ReadFloat(string address)
{
lock (locker1)
{
var res = DeltaInstance1.ReadFloat(address);
return res;
}
}
/// <summary>
/// 读取Bool
/// </summary>
/// <param name="address"></param>
/// <returns></returns>
public OperateResult<bool> ReadBool(string address)
{
lock (locker1)
{
var res = DeltaInstance1.ReadBool(address);
return res;
}
}
/// <summary>
/// 读取字节数组
/// </summary>
/// <param name="address"></param>
/// <param name="length"></param>
/// <returns></returns>
public static OperateResult<byte[]> ReadByte2(string address, ushort length)
{
lock (locker1)
{
var res = DeltaInstance1.Read(address, length);
return res;
}
}
}
}

@ -0,0 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Sln.Iot.Serilog\Sln.Iot.Serilog.csproj" />
</ItemGroup>
<ItemGroup>
<Reference Include="HslCommunication">
<HintPath>..\DLL\HslCommunication.dll</HintPath>
</Reference>
</ItemGroup>
</Project>

@ -1,44 +0,0 @@
#region << 版 本 注 释 >>
/*--------------------------------------------------------------------
* (c) 2025 WenJY
* CLR4.0.30319.42000
* Mr.Wen's MacBook Pro
* Sln.Iot.Repository
* 130152CF-25A2-4CF6-BF55-FF62811E139D
*
* WenJY
*
* 2025-04-11 13:24:59
* V1.0.0
*
*
*--------------------------------------------------------------------
*
*
*
*
* V1.0.0
*--------------------------------------------------------------------*/
#endregion << 版 本 注 释 >>
using SqlSugar;
namespace Sln.Iot.Repository
{
public class Repository<T> : SimpleClient<T> where T : class, new()
{
public ITenant itenant = null;//多租户事务、GetConnection、IsAnyConnection等功能
public Repository(ISqlSugarClient db)
{
itenant = db.AsTenant();//用来处理事务
base.Context = db.AsTenant().GetConnectionScopeWithAttr<T>();//获取子Db
//如果不想通过注入多个仓储
//用到ChangeRepository或者Db.GetMyRepository需要看标题4写法
}
}
}

@ -7,12 +7,11 @@
</PropertyGroup>
<ItemGroup>
<Content Include="service\.DS_Store" />
<PackageReference Include="sqlite-net-pcl" Version="1.9.172" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Sln.Iot.Config\Sln.Iot.Config.csproj" />
<ProjectReference Include="..\Sln.Iot.Model\Sln.Iot.Model.csproj" />
</ItemGroup>
</Project>

@ -0,0 +1,99 @@
using SQLite;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
namespace Sln.Iot.Repository
{
/// <summary>
/// SQLite异步方法帮助类
/// </summary>
/// <typeparam name="T"></typeparam>
public class SQLiteAsyncHelper<T> where T : new()
{
private static readonly Lazy<SQLiteAsyncHelper<T>> lazy = new Lazy<SQLiteAsyncHelper<T>>(() => new SQLiteAsyncHelper<T>());
public static SQLiteAsyncHelper<T> Instance
{
get
{
return lazy.Value;
}
}
private readonly string _databasePath = Path.Combine(Environment.CurrentDirectory, "DeltaDatabase.db");
private readonly SQLiteAsyncConnection _connectionAsync; // SQLite连接对象
/// <summary>
/// 构造函数
/// </summary>
public SQLiteAsyncHelper()
{
// 创建SQLite连接对象并打开连接
_connectionAsync = new SQLiteAsyncConnection(_databasePath);
_connectionAsync.CreateTableAsync<T>(); // 如果表不存在,则创建该表[不会创建重复的表]
}
/// <summary>
/// 数据插入
/// </summary>
/// <param name="item">要插入的数据项</param>
/// <returns></returns>
public async Task<int> InsertAsync(T item)
{
return await _connectionAsync.InsertAsync(item);
}
/// <summary>
/// 数据删除
/// </summary>
/// <param name="id">要删除的数据的主键ID</param>
/// <returns></returns>
public async Task<int> DeleteAsync(int id)
{
return await _connectionAsync.DeleteAsync<T>(id);
}
/// <summary>
/// 数据更新
/// </summary>
/// <param name="item">要更新的数据项</param>
/// <returns></returns>
public async Task<int> UpdateAsync(T item)
{
return await _connectionAsync.UpdateAsync(item);
}
/// <summary>
/// 根据条件查询记录
/// </summary>
/// <param name="predExpr">查询条件</param>
/// <returns></returns>
public async Task<List<T>> QueryAsync(Expression<Func<T, bool>> predExpr)
{
return await _connectionAsync.Table<T>().Where(predExpr).ToListAsync();
}
/// <summary>
/// 查询所有数据
/// </summary>
/// <returns></returns>
public async Task<List<T>> QueryAllAsync()
{
return await _connectionAsync.Table<T>().ToListAsync();
}
/// <summary>
/// 根据条件查询单条记录
/// </summary>
/// <param name="predExpr">查询条件</param>
/// <returns></returns>
public async Task<T> QuerySingleAsync(Expression<Func<T, bool>> predExpr)
{
return await _connectionAsync.Table<T>().Where(predExpr).FirstOrDefaultAsync();
}
}
}

@ -0,0 +1,122 @@
using SQLite;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
namespace Sln.Iot.Repository
{
/// <summary>
/// SQLite同步方法帮助类
/// 作者:追逐时光者
/// 创建时间2023年11月30日
/// </summary>
/// <typeparam name="T"></typeparam>
public class SQLiteHelper<T> where T : new()
{
private static readonly Lazy<SQLiteHelper<T>> lazy = new Lazy<SQLiteHelper<T>>(() => new SQLiteHelper<T>());
public static SQLiteHelper<T> Instance
{
get
{
return lazy.Value;
}
}
private readonly string _databasePath = Path.Combine(Environment.CurrentDirectory, "DeltaDatabase.db");
private readonly SQLiteConnection _connection; // SQLite连接对象
/// <summary>
/// 构造函数
/// </summary>
public SQLiteHelper()
{
// 创建SQLite连接对象并打开连接
_connection = new SQLiteConnection(_databasePath);
_connection.CreateTable<T>(); // 如果表不存在,则创建该表[不会创建重复的表]
}
/// <summary>
/// 数据插入
/// </summary>
/// <param name="item">要插入的数据项</param>
/// <returns></returns>
public int Insert(T item)
{
return _connection.Insert(item);
}
/// <summary>
/// 批量数据插入
/// </summary>
/// <param name="item"></param>
/// <returns></returns>
public int InsertRange(List<T> items)
{
return _connection.InsertAll(items);
}
/// <summary>
/// 数据删除
/// </summary>
/// <param name="id">要删除的数据的主键ID</param>
/// <returns></returns>
public int Delete(string id)
{
return _connection.Delete<T>(id);
}
/// <summary>
/// 根据托盘码批量删除记录
/// </summary>
/// <param name="trayCode"></param>
/// <returns></returns>
public List<T> DeleteRange(string trayCode)
{
return _connection.Query<T>($"DELETE FROM {typeof(T).Name} WHERE TrayCode = '{trayCode}'");
}
/// <summary>
/// 数据更新
/// </summary>
/// <param name="item">要更新的数据项</param>
/// <returns></returns>
public int Update(T item)
{
return _connection.Update(item);
}
/// <summary>
/// 根据条件查询记录
/// </summary>
/// <param name="predExpr">查询条件</param>
/// <returns></returns>
public List<T> Query(Expression<Func<T, bool>> predExpr)
{
return _connection.Table<T>().Where(predExpr).ToList();
}
/// <summary>
/// 查询所有数据
/// </summary>
/// <returns></returns>
public List<T> QueryAll()
{
return _connection.Table<T>().ToList();
}
/// <summary>
/// 根据条件查询单条记录
/// </summary>
/// <param name="predExpr">查询条件</param>
/// <returns></returns>
public T QuerySingle(Expression<Func<T, bool>> predExpr)
{
return _connection.Table<T>().Where(predExpr).FirstOrDefault();
}
}
}

@ -1,73 +0,0 @@
#region << 版 本 注 释 >>
/*--------------------------------------------------------------------
* (c) 2025 WenJY
* CLR4.0.30319.42000
* Mr.Wen's MacBook Pro
* Sln.Iot.Repository
* EBCC8183-D907-4049-B036-0C5BA2284E22
*
* WenJY
*
* 2025-04-11 13:39:23
* V1.0.0
*
*
*--------------------------------------------------------------------
*
*
*
*
* V1.0.0
*--------------------------------------------------------------------*/
#endregion << 版 本 注 释 >>
using System.Collections.Generic;
using Microsoft.Extensions.DependencyInjection;
using Sln.Iot.Config;
using SqlSugar;
namespace Sln.Iot.Repository
{
public static class SqlsugarSetup
{
/// <summary>
/// 注册SqlSugar
/// </summary>
/// <param name="services"></param>
public static void AddSqlSugarSetup(this IServiceCollection services)
{
services.AddSingleton<ISqlSugarClient>(x =>
{
var appConfig = x.GetService<AppConfig>();
var connectConfigList = new List<ConnectionConfig>();
if (appConfig.sqlConfig != null)
{
foreach (var item in appConfig.sqlConfig)
{
if (item.isFlag)
{
var config = new ConnectionConfig()
{
ConfigId = item.configId,
DbType = (DbType)item.dbType,
ConnectionString = item.connStr,
InitKeyType = InitKeyType.Attribute,
IsAutoCloseConnection = true,
};
connectConfigList.Add(config);
}
}
}
SqlSugarScope Db = new SqlSugarScope(connectConfigList, db =>
{
db.Aop.OnLogExecuting = (sql, pars) => { };
});
return Db;
});
}
}
}

@ -0,0 +1,28 @@
using SQLite;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Sln.Iot.Repository.dao
{
/// <summary>
/// 数据中转表
/// </summary>
public class TrayRfidBinding
{
[PrimaryKey]
public string GUID { get; set; }
/// <summary>
/// 托盘码
/// </summary>
public string TrayCode { get; set; }
/// <summary>
/// 产品编码
/// </summary>
public string ProductionCode { get; set; }
}
}

Binary file not shown.

@ -1,35 +0,0 @@
#region << 版 本 注 释 >>
/*--------------------------------------------------------------------
* (c) 2025 WenJY
* CLR4.0.30319.42000
* Mr.Wen's MacBook Pro
* Sln.Iot.Repository.service
* 9B119436-8BE4-4693-9D28-F971874E03CB
*
* WenJY
*
* 2025-04-11 13:27:35
* V1.0.0
*
*
*--------------------------------------------------------------------
*
*
*
*
* V1.0.0
*--------------------------------------------------------------------*/
#endregion << 版 本 注 释 >>
using Sln.Iot.Model.dao;
using Sln.Iot.Repository.service.@base;
namespace Sln.Iot.Repository.service
{
public interface IBaseMonitorInfoService : IBaseService<BaseMonitorInfo>
{
}
}

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

@ -1,42 +0,0 @@
#region << 版 本 注 释 >>
/*--------------------------------------------------------------------
* (c) 2025 WenJY
* CLR4.0.30319.42000
* Mr.Wen's MacBook Pro
* Sln.Iot.Repository.service
* D397E4B7-48E1-4BF3-8906-B11F96EE8B42
*
* WenJY
*
* 2025-05-20 11:26:07
* V1.0.0
*
*
*--------------------------------------------------------------------
*
*
*
*
* V1.0.0
*--------------------------------------------------------------------*/
#endregion << 版 本 注 释 >>
using System.Collections.Generic;
using Sln.Iot.Model.dao;
using Sln.Iot.Repository.service.@base;
namespace Sln.Iot.Repository.service
{
public interface IRecordDnbInstantService:IBaseService<RecordDnbInstant>
{
/// <summary>
/// 分表保存
/// </summary>
/// <param name="list"></param>
/// <param name="insertIds"></param>
/// <returns></returns>
bool SplitInsert(List<RecordDnbInstant> list,out List<long> insertIds);
}
}

@ -1,42 +0,0 @@
#region << 版 本 注 释 >>
/*--------------------------------------------------------------------
* (c) 2025 WenJY
* CLR4.0.30319.42000
* Mr.Wen's MacBook Pro
* Sln.Iot.Repository.service
* 6403A242-FF9C-4942-B02B-8680BBD7ACBD
*
* WenJY
*
* 2025-05-20 14:46:25
* V1.0.0
*
*
*--------------------------------------------------------------------
*
*
*
*
* V1.0.0
*--------------------------------------------------------------------*/
#endregion << 版 本 注 释 >>
using System.Collections.Generic;
using Sln.Iot.Model.dao;
using Sln.Iot.Repository.service.@base;
namespace Sln.Iot.Repository.service
{
public interface IRecordFluidInstantService:IBaseService<RecordFluidInstant>
{
/// <summary>
/// 分表保存
/// </summary>
/// <param name="list"></param>
/// <param name="insertIds"></param>
/// <returns></returns>
bool SplitInsert(List<RecordFluidInstant> list,out List<long> insertIds);
}
}

@ -1,42 +0,0 @@
#region << 版 本 注 释 >>
/*--------------------------------------------------------------------
* (c) 2025 WenJY
* CLR4.0.30319.42000
* Mr.Wen's MacBook Pro
* Sln.Iot.Repository.service
* 44931288-195F-4560-B9D8-9EA8A511FE8A
*
* WenJY
*
* 2025-04-11 15:44:29
* V1.0.0
*
*
*--------------------------------------------------------------------
*
*
*
*
* V1.0.0
*--------------------------------------------------------------------*/
#endregion << 版 本 注 释 >>
using System.Collections.Generic;
using Sln.Iot.Model.dao;
using Sln.Iot.Repository.service.@base;
namespace Sln.Iot.Repository.service
{
public interface IRecordIotEnvInstantService:IBaseService<RecordIotEnvInstant>
{
/// <summary>
/// 分表保存
/// </summary>
/// <param name="list"></param>
/// <param name="insertIds"></param>
/// <returns></returns>
bool SplitInsert(List<RecordIotEnvInstant> list,out List<long> insertIds);
}
}

@ -1,17 +0,0 @@
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)
{
}
}
}

@ -1,37 +0,0 @@
#region << 版 本 注 释 >>
/*--------------------------------------------------------------------
* (c) 2025 WenJY
* CLR4.0.30319.42000
* Mr.Wen's MacBook Pro
* Sln.Iot.Repository.service.Impl
* 625A971B-5BA8-4E05-9AE1-DC6D8E3D6051
*
* WenJY
*
* 2025-04-11 13:28:02
* 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 BaseMonitorInfoServiceImpl : BaseServiceImpl<BaseMonitorInfo>, IBaseMonitorInfoService
{
public BaseMonitorInfoServiceImpl(Repository<BaseMonitorInfo> repository):base(repository)
{
}
}
}

@ -1,36 +0,0 @@
#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,73 +0,0 @@
#region << 版 本 注 释 >>
/*--------------------------------------------------------------------
* (c) 2025 WenJY
* CLR4.0.30319.42000
* Mr.Wen's MacBook Pro
* Sln.Iot.Repository.service.Impl
* EF060FA7-6D52-478C-84FF-F26EEC206685
*
* WenJY
*
* 2025-05-20 11:26:53
* V1.0.0
*
*
*--------------------------------------------------------------------
*
*
*
*
* V1.0.0
*--------------------------------------------------------------------*/
#endregion << 版 本 注 释 >>
using System;
using System.Collections.Generic;
using Sln.Iot.Model.dao;
using Sln.Iot.Repository.service.@base;
namespace Sln.Iot.Repository.service.Impl
{
public class RecordDnbInstantServiceImpl: BaseServiceImpl<RecordDnbInstant>, IRecordDnbInstantService
{
public RecordDnbInstantServiceImpl(Repository<RecordDnbInstant> rep) : base(rep)
{
}
/// <summary>
/// 分表保存
/// </summary>
/// <param name="list"></param>
/// <param name="insertIds"></param>
/// <returns></returns>
/// <exception cref="ArgumentNullException"></exception>
/// <exception cref="InvalidOperationException"></exception>
public bool SplitInsert(List<RecordDnbInstant> list,out List<long> insertIds)
{
if (list == null)
{
throw new ArgumentNullException($"参数为空");
}
try
{
// _rep.AsTenant().BeginTran();
var sqlSugarClient = _rep.Context;
//加载指定分表策略
//sqlSugarClient.CurrentConnectionConfig.ConfigureExternalServices.SplitTableService = new MonitorIdToSplitService();
insertIds = sqlSugarClient.Insertable(list).SplitTable().ExecuteReturnSnowflakeIdList();
// _rep.AsTenant().CommitTran();
return true;
}
catch (Exception ex)
{
// _rep.AsTenant().RollbackTran();
throw new InvalidOperationException($"电能数据分表保存异常:{ex.Message}");
}
}
}
}

@ -1,73 +0,0 @@
#region << 版 本 注 释 >>
/*--------------------------------------------------------------------
* (c) 2025 WenJY
* CLR4.0.30319.42000
* Mr.Wen's MacBook Pro
* Sln.Iot.Repository.service.Impl
* 72B88660-5410-4016-9E12-B1E11841AB4B
*
* WenJY
*
* 2025-05-20 14:47:03
* V1.0.0
*
*
*--------------------------------------------------------------------
*
*
*
*
* V1.0.0
*--------------------------------------------------------------------*/
#endregion << 版 本 注 释 >>
using System;
using System.Collections.Generic;
using Sln.Iot.Model.dao;
using Sln.Iot.Repository.service.@base;
namespace Sln.Iot.Repository.service.Impl
{
public class RecordFluidInstantServiceImpl: BaseServiceImpl<RecordFluidInstant>, IRecordFluidInstantService
{
public RecordFluidInstantServiceImpl(Repository<RecordFluidInstant> rep) : base(rep)
{
}
/// <summary>
/// 分表保存
/// </summary>
/// <param name="list"></param>
/// <param name="insertIds"></param>
/// <returns></returns>
/// <exception cref="ArgumentNullException"></exception>
/// <exception cref="InvalidOperationException"></exception>
public bool SplitInsert(List<RecordFluidInstant> list,out List<long> insertIds)
{
if (list == null)
{
throw new ArgumentNullException($"参数为空");
}
try
{
// _rep.AsTenant().BeginTran();
var sqlSugarClient = _rep.Context;
//加载指定分表策略
//sqlSugarClient.CurrentConnectionConfig.ConfigureExternalServices.SplitTableService = new MonitorIdToSplitService();
insertIds = sqlSugarClient.Insertable(list).SplitTable().ExecuteReturnSnowflakeIdList();
// _rep.AsTenant().CommitTran();
return true;
}
catch (Exception ex)
{
// _rep.AsTenant().RollbackTran();
throw new InvalidOperationException($"流体数据分表保存异常:{ex.Message}");
}
}
}
}

@ -1,74 +0,0 @@
#region << 版 本 注 释 >>
/*--------------------------------------------------------------------
* (c) 2025 WenJY
* CLR4.0.30319.42000
* Mr.Wen's MacBook Pro
* Sln.Iot.Repository.service.Impl
* C914F6F6-C7CC-4DDC-B061-C89A15419EF0
*
* WenJY
*
* 2025-04-11 15:44:49
* V1.0.0
*
*
*--------------------------------------------------------------------
*
*
*
*
* V1.0.0
*--------------------------------------------------------------------*/
#endregion << 版 本 注 释 >>
using System;
using System.Collections.Generic;
using Sln.Iot.Model.dao;
using Sln.Iot.Repository.service.@base;
using Sln.Iot.Repository.service.split;
namespace Sln.Iot.Repository.service.Impl
{
public class RecordIotEnvInstantServiceImpl: BaseServiceImpl<RecordIotEnvInstant>, IRecordIotEnvInstantService
{
public RecordIotEnvInstantServiceImpl(Repository<RecordIotEnvInstant> rep) : base(rep)
{
}
/// <summary>
/// 分表保存
/// </summary>
/// <param name="list"></param>
/// <param name="insertIds"></param>
/// <returns></returns>
/// <exception cref="ArgumentNullException"></exception>
/// <exception cref="InvalidOperationException"></exception>
public bool SplitInsert(List<RecordIotEnvInstant> list,out List<long> insertIds)
{
if (list == null)
{
throw new ArgumentNullException($"参数为空");
}
try
{
// _rep.AsTenant().BeginTran();
var sqlSugarClient = _rep.Context;
//加载指定分表策略
//sqlSugarClient.CurrentConnectionConfig.ConfigureExternalServices.SplitTableService = new MonitorIdToSplitService();
insertIds = sqlSugarClient.Insertable(list).SplitTable().ExecuteReturnSnowflakeIdList();
// _rep.AsTenant().CommitTran();
return true;
}
catch (Exception ex)
{
// _rep.AsTenant().RollbackTran();
throw new InvalidOperationException($"物联网数据分表保存异常:{ex.Message}");
}
}
}
}

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

@ -1,359 +0,0 @@
#region << 版 本 注 释 >>
/*--------------------------------------------------------------------
* (c) 2025 WenJY
* CLR4.0.30319.42000
* Mr.Wen's MacBook Pro
* Sln.Iot.Repository.service.base
* AAD164C5-C115-422B-B57B-E9669385D083
*
* WenJY
*
* 2025-04-11 13:26:34
* V1.0.0
*
*
*--------------------------------------------------------------------
*
*
*
*
* V1.0.0
*--------------------------------------------------------------------*/
#endregion << 版 本 注 释 >>
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using SqlSugar;
namespace Sln.Iot.Repository.service.@base
{
public class BaseServiceImpl<T> : IBaseService<T> where T : class, new()
{
public readonly Repository<T> _rep;
public BaseServiceImpl(Repository<T> rep)
{
_rep = rep;
}
/// <summary>
/// 添加实体信息
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
/// <exception cref="ArgumentNullException"></exception>
/// <exception cref="InvalidOperationException"></exception>
public bool Insert(T model)
{
if (model == null)
{
throw new ArgumentNullException($"添加实体信息异常:实体参数为空");
}
try
{
return _rep.CopyNew().Insert(model);
}
catch (Exception ex)
{
throw new InvalidOperationException($"添加实体信息异常:{ex.Message}");
}
}
/// <summary>
/// 批量添加实体集合
/// </summary>
/// <param name="lisT"></param>
/// <returns></returns>
/// <exception cref="ArgumentNullException"></exception>
/// <exception cref="InvalidOperationException"></exception>
public bool Insert(List<T> lisT)
{
if (lisT == null)
{
throw new ArgumentNullException($"批量添加实体集合异常:实体集合参数为空");
}
try
{
// _rep.AsTenant().BeginTran();
var info = _rep.CopyNew().InsertRange(lisT);
// _rep.AsTenant().CommitTran();
return true;
}
catch (Exception ex)
{
// _rep.AsTenant().RollbackTran();
throw new InvalidOperationException($"批量添加实体集合异常:{ex.Message}");
}
}
/// <summary>
/// 根据id 删除信息
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public bool DeleteById(object id)
{
if (id == null)
{
throw new ArgumentNullException($"根据id删除信息异常:Id参数为空");
}
try
{
return _rep.DeleteById(id);
}
catch (Exception ex)
{
throw new InvalidOperationException($"根据id删除信息异常:{ex.Message}");
}
}
/// <summary>
/// 根据实体删除信息
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
/// <exception cref="ArgumentNullException"></exception>
/// <exception cref="InvalidOperationException"></exception>
public bool Delete(T model)
{
if (model == null)
{
throw new ArgumentNullException($"根据实体删除信息异常:实体参数为空");
}
try
{
return _rep.DeleteById(model);
}
catch (Exception ex)
{
throw new InvalidOperationException($"根据实体删除信息异常:{ex.Message}");
}
}
/// <summary>
/// 根据实体集合批量删除信息
/// </summary>
/// <param name="entitys"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public bool Deletes(List<T> entitys)
{
if (entitys == null)
{
throw new ArgumentNullException($"根据实体集合批量删除信息异常:实体集合参数为空");
}
try
{
return _rep.Delete(entitys);
}
catch (Exception ex)
{
throw new InvalidOperationException($"根据实体集合批量删除信息异常:{ex.Message}");
}
}
/// <summary>
/// 根据实体更新信息
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public bool Update(T model)
{
if (model == null)
{
throw new ArgumentNullException($"根据实体更新信息异常:实体参数为空");
}
try
{
return _rep.Update(model);
}
catch (Exception ex)
{
throw new InvalidOperationException($"根据实体更新信息异常:{ex.Message}");
}
}
/// <summary>
/// 批量更新实体集合信息
/// </summary>
/// <param name="entitys"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public bool Update(List<T> entitys)
{
if (entitys == null)
{
throw new ArgumentNullException($"批量更新实体集合信息异常:实体集合参数为空");
}
try
{
return _rep.UpdateRange(entitys);
}
catch (Exception ex)
{
throw new InvalidOperationException($"批量更新实体集合信息异常:{ex.Message}");
}
}
/// <summary>
/// 根据Where条件更新实体信息
/// </summary>
/// <param name="entity"></param>
/// <param name="strWhere"></param>
/// <returns></returns>
public bool Update(T entity, string strWhere)
{
if (entity == null)
{
throw new ArgumentNullException($"根据Where条件更新实体信息异常:实体参数为空");
}
if (string.IsNullOrEmpty(strWhere))
{
throw new ArgumentNullException($"根据Where条件更新实体信息异常:Where参数为空");
}
try
{
return _rep.AsUpdateable(entity).Where(strWhere).ExecuteCommandHasChange();
}
catch (Exception ex)
{
throw new InvalidOperationException($"根据Where条件更新实体信息异常:{ex.Message}");
}
}
/// <summary>
/// 根据实体更新指定列
/// </summary>
/// <param name="entity"></param>
/// <param name="lstColumns"></param>
/// <param name="lstIgnoreColumns"></param>
/// <param name="strWhere"></param>
/// <returns></returns>
public bool Update(T entity, List<string> lstColumns = null, List<string> lstIgnoreColumns = null, string strWhere = "")
{
try
{
IUpdateable<T> up = _rep.AsUpdateable(entity);
if (lstIgnoreColumns != null && lstIgnoreColumns.Count > 0)
{
up = up.IgnoreColumns(lstIgnoreColumns.ToArray());
}
if (lstColumns != null && lstColumns.Count > 0)
{
up = up.UpdateColumns(lstColumns.ToArray());
}
if (!string.IsNullOrEmpty(strWhere))
{
up = up.Where(strWhere);
}
return up.ExecuteCommandHasChange();
}
catch (Exception ex)
{
throw new InvalidOperationException($"根据实体更新指定列异常:{ex.Message}");
}
}
/// <summary>
/// 查询所有信息
/// </summary>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public List<T> Query()
{
try
{
return _rep.GetList();
}
catch (Exception ex)
{
throw new InvalidOperationException($"查询所有信息异常:{ex.Message}");
}
}
/// <summary>
/// 根据Id查询实体
/// </summary>
/// <param name="objId"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public T Query(object objId)
{
if (objId == null)
{
throw new ArgumentNullException($"根据Id查询实体信息异常:Id参数为空");
}
try
{
return _rep.GetById(objId);
}
catch (Exception ex)
{
throw new InvalidOperationException($"根据Id查询实体信息异常:{ex.Message}");
}
}
/// <summary>
/// 根据表达式查询
/// </summary>
/// <param name="whereExpression"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public List<T> Query(Expression<Func<T, bool>> whereExpression)
{
if (whereExpression == null)
{
throw new ArgumentNullException($"根据表达式查询实体信息异常:表达式参数为空");
}
try
{
return _rep.GetList(whereExpression);
}
catch (Exception ex)
{
throw new InvalidOperationException($"根据表达式查询实体信息异常:{ex.Message}");
}
}
/// <summary>
/// 根据表达式排序查询
/// </summary>
/// <param name="whereExpression"></param>
/// <param name="orderByExpression"></param>
/// <param name="isAsc"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public List<T> Query(Expression<Func<T, bool>> whereExpression, Expression<Func<T, object>> orderByExpression, bool isAsc = true)
{
if (whereExpression == null)
{
throw new ArgumentNullException($"根据表达式排序查询信息异常:条件表达式参数为空");
}
if (orderByExpression == null)
{
throw new ArgumentNullException($"根据表达式排序查询信息异常:排序表达式参数为空");
}
try
{
return _rep.AsQueryable().OrderByIF(orderByExpression != null, orderByExpression, isAsc ? OrderByType.Asc : OrderByType.Desc).WhereIF(whereExpression != null, whereExpression).ToList();
}
catch (Exception ex)
{
throw new InvalidOperationException($"根据表达式排序查询信息异常:{ex.Message}");
}
}
}
}

@ -1,130 +0,0 @@
#region << 版 本 注 释 >>
/*--------------------------------------------------------------------
* (c) 2025 WenJY
* CLR4.0.30319.42000
* Mr.Wen's MacBook Pro
* Sln.Iot.Repository.service.base
* 4F2637EA-9206-45C6-92B8-E2CDBA5A1B22
*
* WenJY
*
* 2025-04-11 13:26:02
* V1.0.0
*
*
*--------------------------------------------------------------------
*
*
*
*
* V1.0.0
*--------------------------------------------------------------------*/
#endregion << 版 本 注 释 >>
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
namespace Sln.Iot.Repository.service.@base
{
public interface IBaseService<T> where T : class
{
/// <summary>
/// 添加实体信息
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
bool Insert(T model);
/// <summary>
/// 批量添加实体集合
/// </summary>
/// <param name="lisT"></param>
/// <returns></returns>
bool Insert(List<T> lisT);
/// <summary>
/// 根据id 删除信息
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
bool DeleteById(object id);
/// <summary>
/// 根据实体删除信息
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
bool Delete(T model);
/// <summary>
/// 根据实体集合批量删除信息
/// </summary>
/// <param name="ids"></param>
/// <returns></returns>
bool Deletes(List<T> entitys);
/// <summary>
/// 根据实体更新信息
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
bool Update(T model);
/// <summary>
/// 批量更新实体集合信息
/// </summary>
/// <param name="entitys"></param>
/// <returns></returns>
bool Update(List<T> entitys);
/// <summary>
/// 根据Where条件更新实体信息
/// </summary>
/// <param name="entity"></param>
/// <param name="strWhere"></param>
/// <returns></returns>
bool Update(T entity, string strWhere);
/// <summary>
/// 根据实体更新指定列
/// </summary>
/// <param name="entity"></param>
/// <param name="lstColumns"></param>
/// <param name="lstIgnoreColumns"></param>
/// <param name="strWhere"></param>
/// <returns></returns>
bool Update(T entity, List<string> lstColumns = null, List<string> lstIgnoreColumns = null, string strWhere = "");
/// <summary>
/// 查询所有信息
/// </summary>
/// <returns></returns>
List<T> Query();
/// <summary>
/// 根据Id查询实体
/// </summary>
/// <param name="objId"></param>
/// <returns></returns>
T Query(object objId);
/// <summary>
/// 根据表达式查询
/// </summary>
/// <param name="whereExpression"></param>
/// <returns></returns>
List<T> Query(Expression<Func<T, bool>> whereExpression);
/// <summary>
/// 根据表达式排序查询
/// </summary>
/// <param name="whereExpression">查询条件</param>
/// <param name="orderByExpression">排序条件</param>
/// <param name="isAsc">是否正序</param>
/// <returns></returns>
List<T> Query(Expression<Func<T, bool>> whereExpression, Expression<Func<T, object>> orderByExpression, bool isAsc = true);
}
}

@ -1,97 +0,0 @@
#region << 版 本 注 释 >>
/*--------------------------------------------------------------------
* (c) 2025 WenJY
* CLR4.0.30319.42000
* Mr.Wen's MacBook Pro
* Sln.Iot.Repository.service.split
* 2D1DE17A-79B9-48D8-BB98-60E89BEC711A
*
* WenJY
*
* 2025-04-27 10:10:14
* V1.0.0
*
*
*--------------------------------------------------------------------
*
*
*
*
* V1.0.0
*--------------------------------------------------------------------*/
#endregion << 版 本 注 释 >>
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using SqlSugar;
namespace Sln.Iot.Repository.service.split
{
/// <summary>
/// 自定义分表策略:根据传感器 ID 进行分表
/// </summary>
public class MonitorIdToSplitService:ISplitTableService
{
/// <summary>
/// 返回数据库中所有分表
/// </summary>
/// <param name="db"></param>
/// <param name="EntityInfo"></param>
/// <param name="tableInfos"></param>
/// <returns></returns>
public List<SplitTableInfo> GetAllTables(ISqlSugarClient db, EntityInfo EntityInfo, List<DbTableInfo> tableInfos)
{
List<SplitTableInfo> result = new List<SplitTableInfo>();
foreach (var item in tableInfos)
{
if (item.Name.Contains("record_iotenv_instant")) //区分标识如果不用正则符复杂一些,防止找错表
{
SplitTableInfo data = new SplitTableInfo()
{
TableName = item.Name //要用item.name不要写错了
};
result.Add(data);
}
}
return result.OrderBy(it=>it.TableName).ToList();//打断点看一下有没有查出所有分表
}
/// <summary>
/// 获取分表字段的值
/// </summary>
/// <param name="db"></param>
/// <param name="entityInfo"></param>
/// <param name="splitType"></param>
/// <param name="entityValue"></param>
/// <returns></returns>
public object GetFieldValue(ISqlSugarClient db, EntityInfo entityInfo, SplitType splitType, object entityValue)
{
var splitColumn = entityInfo.Columns.FirstOrDefault(it => it.PropertyInfo.GetCustomAttribute<SplitFieldAttribute>() != null);
var value = splitColumn.PropertyInfo.GetValue(entityValue, null);
return value;
}
/// <summary>
/// 默认表名
/// </summary>
/// <param name="db"></param>
/// <param name="EntityInfo"></param>
/// <returns></returns>
public string GetTableName(ISqlSugarClient db, EntityInfo entityInfo)
{
return entityInfo.DbTableName;
}
public string GetTableName(ISqlSugarClient db, EntityInfo entityInfo, SplitType type)
{
return entityInfo.DbTableName;//目前模式少不需要分类(自带的有 日、周、月、季、年等进行区分)
}
public string GetTableName(ISqlSugarClient db, EntityInfo entityInfo, SplitType splitType, object fieldValue)
{
return entityInfo.DbTableName + "_"+fieldValue; //根据值按首字母
}
}
}

@ -1,72 +0,0 @@
#region << 版 本 注 释 >>
/*--------------------------------------------------------------------
* (c) 2025 WenJY
* CLR4.0.30319.42000
* Mr.Wen's MacBook Pro
* Sln.Iot.Socket.Adapter
* 8A1D4D97-E419-4A49-B921-7FF76B190F45
*
* WenJY
*
* 2025-04-11 13:55:38
* V1.0.0
*
*
*--------------------------------------------------------------------
*
*
*
*
* V1.0.0
*--------------------------------------------------------------------*/
#endregion << 版 本 注 释 >>
using TouchSocket.Core;
namespace Sln.Iot.Socket.Adapter
{
public class BufferRequestInfo: IRequestInfo
{
/// <summary>
/// 帧头 0x68 1个字
/// </summary>
public byte[] header { get; internal set; }
/// <summary>
/// 采集设备编号,由采集器类型(1个字)、采集器地址(2个字)组成
/// </summary>
public string ColletEquipCode { get; internal set; }
/// <summary>
/// 自定义属性,DataType
/// </summary>
public byte DataType { get; internal set; }
/// <summary>
/// Buffer长度
/// </summary>
public int BufferLength { get; internal set; }
/// <summary>
/// 内容体
/// </summary>
public byte[] Body { get; internal set; }
/// <summary>
/// 校验位 1个字从帧头到数据累加CS校验
/// </summary>
public byte CheckBit { get; internal set; }
/// <summary>
/// 帧尾 0x16 1个字
/// </summary>
public byte[] Tail { get; internal set; }
/// <summary>
/// 原始Buffer
/// </summary>
public ByteBlock buffer { get; internal set; }
}
}

@ -1,117 +0,0 @@
#region << 版 本 注 释 >>
/*--------------------------------------------------------------------
* (c) 2025 WenJY
* CLR4.0.30319.42000
* Mr.Wen's MacBook Pro
* Sln.Iot.Socket.Adapter
* 50003A25-42CE-44A7-9940-FFDE3BD0A52A
*
* WenJY
*
* 2025-04-11 13:56:24
* V1.0.0
*
*
*--------------------------------------------------------------------
*
*
*
*
* V1.0.0
*--------------------------------------------------------------------*/
#endregion << 版 本 注 释 >>
using System;
using System.Text;
using TouchSocket.Core;
namespace Sln.Iot.Socket.Adapter
{
public class CustomDataHandlingAdapter:CustomDataHandlingAdapter<BufferRequestInfo>
{
protected override FilterResult Filter(in ByteBlock byteBlock, bool beCached, ref BufferRequestInfo request, ref int tempCapacity)
{
CacheTimeoutEnable = true;
CacheTimeout = new TimeSpan(0, 0, 0, 0, 5000);
int pos = byteBlock.Pos;
try
{
if (byteBlock.CanReadLen < 5)
{
return FilterResult.Cache;
}
byteBlock.Read(out byte[] header, 1);
byteBlock.Read(out byte[] deviceType, 1);
byteBlock.Read(out byte[] deviceId, 2);
string DeviceType = Encoding.ASCII.GetString(deviceType);
string collectEquipCode = DeviceType + this.ConverToString(deviceId);
byteBlock.Pos += 3;
byteBlock.Read(out byte[] dataType, 1);
byteBlock.Read(out byte[] lengthByte, 2);
string hexString = BitConverter.ToString(lengthByte).Replace("-", "");
int bodyLength = Convert.ToInt32(hexString, 16);
if (bodyLength > byteBlock.CanReadLen)
{
byteBlock.Pos = pos; //body数据不足。回退游标
return FilterResult.Cache;
}
else
{
byteBlock.Read(out byte[] body, bodyLength);
byteBlock.Read(out byte[] check, 1);
byteBlock.Read(out byte[] tail, 1);
request = new BufferRequestInfo()
{
header = header,
ColletEquipCode = collectEquipCode,
DataType = dataType[0],
BufferLength = bodyLength,
Body = body,
CheckBit = check[0],
Tail = tail,
buffer = byteBlock
};
return FilterResult.Success;
}
}catch (Exception ex)
{
Logger.Error("FilterResult"+ex.Message);
byteBlock.Pos = pos; //body数据不足。回退游标
return FilterResult.Cache;
}
}
private string ConverToString(byte[] data)
{
string str;
StringBuilder stb = new StringBuilder();
for (int i = 0; i < data.Length; i++)
{
if ((int)data[i] > 15)
{
stb.Append(Convert.ToString(data[i], 16).ToUpper()); //添加字符串
}
else //如果是小于0F需要加个零
{
stb.Append("0" + Convert.ToString(data[i], 16).ToUpper());
}
}
str = stb.ToString();
return str;
}
}
}

@ -1,149 +0,0 @@
#region << 版 本 注 释 >>
/*--------------------------------------------------------------------
* (c) 2025 WenJY
* CLR4.0.30319.42000
* Mr.Wen's MacBook Pro
* Sln.Iot.Socket
* 6D821766-EAFA-4C51-A757-8786E77645AC
*
* WenJY
*
* 2025-04-11 13:51:11
* V1.0.0
*
*
*--------------------------------------------------------------------
*
*
*
*
* V1.0.0
*--------------------------------------------------------------------*/
#endregion << 版 本 注 释 >>
using System;
using System.Text;
using Sln.Iot.Common;
using Sln.Iot.Serilog;
using Sln.Iot.Socket.Adapter;
using TouchSocket.Core;
using TouchSocket.Sockets;
namespace Sln.Iot.Socket
{
public class TcpServer
{
private readonly SerilogHelper _logger;
private readonly TcpService _service;
private readonly StringChange _stringChange;
public TcpServer(SerilogHelper logger, TcpService service, StringChange stringChange)
{
_logger = logger;
_service = service;
_stringChange = stringChange;
}
/// <summary>
/// 接收客户端指令委托
/// </summary>
public delegate void ReceivedClientBuffer(byte[] buffer);
public event ReceivedClientBuffer? ReceivedClientBufferEvent;
public delegate void RefreshClientInfo(TcpService tcpService);
public event RefreshClientInfo? RefreshClientInfoEvent;
[Obsolete("Obsolete")]
public delegate void ReceivedBufferRequestInfo(SocketClient client,BufferRequestInfo requestInfo);
public event ReceivedBufferRequestInfo ReceivedBufferRequestInfoEvent;
public void Init(int serverPort)
{
try
{
_service.Connecting = (client, e) => {
_logger.Info($"客户端{client.IP}正在接入服务");
return EasyTask.CompletedTask;
};
_service.Connected = (client, e) => {
_logger.Info($"客户端{client.IP}接入服务成功");
RefreshClientInfoEvent?.Invoke(_service);
return EasyTask.CompletedTask;
};
_service.Disconnected = (client, e) => {
_logger.Info($"客户端{client.IP}断开连接");
RefreshClientInfoEvent?.Invoke(_service);
return EasyTask.CompletedTask;
};
_service.Received = (client, e) =>
{
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;
};
_service.Setup(new TouchSocketConfig()//载入配置
.SetListenIPHosts(new IPHost[] { new IPHost($"0.0.0.0:{serverPort}") })
.SetTcpDataHandlingAdapter(() => new CustomDataHandlingAdapter())
.ConfigureContainer(a =>//容器的配置顺序应该在最前面
{
a.AddConsoleLogger();
})
.ConfigurePlugins(a =>
{
//自定义插件
}));
_service.Start();
_logger.Info($"TcpServer启动成功监听端口{serverPort}");
}
catch (Exception ex)
{
//throw new InvalidOperationException($"TcpServer启动异常{ex.Message}");
_logger.Error($"TcpServer启动异常{ex.Message}");
}
}
/// <summary>
/// 向所有客户端发送心跳
/// </summary>
public void SendHeartBeat()
{
var clients = _service.SocketClients.GetClients();
foreach (var item in clients)
{
_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)}");
}
}
}
}
}

@ -0,0 +1,36 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.1.0" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="coverlet.collector" Version="3.1.2">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Sln.Iot.Business\Sln.Iot.Business.csproj" />
<ProjectReference Include="..\Sln.Iot.CFX\Sln.Iot.CFX.csproj" />
<ProjectReference Include="..\Sln.Iot.Common\Sln.Iot.Common.csproj" />
<ProjectReference Include="..\Sln.Iot.Config\Sln.Iot.Config.csproj" />
<ProjectReference Include="..\Sln.Iot.PLC\Sln.Iot.PLC.csproj" />
<ProjectReference Include="..\Sln.Iot.Repository\Sln.Iot.Repository.csproj" />
<ProjectReference Include="..\Sln.Iot.Serilog\Sln.Iot.Serilog.csproj" />
<ProjectReference Include="..\Sln.Iot.Socket\Sln.Iot.Socket.csproj" />
<ProjectReference Include="..\Sln.Iot\Sln.Iot.csproj" />
</ItemGroup>
</Project>

@ -0,0 +1,59 @@
global using Xunit;
global using Sln.Iot.Repository.dao;
using Sln.Iot.Repository;
namespace Sln.Iot.Test
{
public class UnitTest1
{
[Fact]
public void Test1()
{
}
[Fact]
public void Test2()
{
List<TrayRfidBinding> testDatas = new List<TrayRfidBinding>()
{
new TrayRfidBinding()
{
GUID = Guid.NewGuid().ToString(),
TrayCode = "Tray001",
ProductionCode = "ProdA",
},
new TrayRfidBinding()
{
GUID = Guid.NewGuid().ToString(),
TrayCode = "Tray002",
ProductionCode = "ProdB",
},
new TrayRfidBinding()
{
GUID = Guid.NewGuid().ToString(),
TrayCode = "Tray002",
ProductionCode = "ProdC",
},
new TrayRfidBinding()
{
GUID = Guid.NewGuid().ToString(),
TrayCode = "Tray002",
ProductionCode = "ProdD",
},
new TrayRfidBinding()
{
GUID = Guid.NewGuid().ToString(),
TrayCode = "Tray003",
ProductionCode = "ProdE",
},
};
var res = SQLiteHelper<TrayRfidBinding>.Instance.DeleteRange("Tray001");
Assert.Equal(5, res.Count);
}
}
}

@ -11,14 +11,18 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sln.Iot.Config", "Sln.Iot.C
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sln.Iot.Common", "Sln.Iot.Common\Sln.Iot.Common.csproj", "{899D8A81-D3E3-4599-8A8C-D60280A777F3}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sln.Iot.Model", "Sln.Iot.Model\Sln.Iot.Model.csproj", "{503E7EAE-6323-4CE2-AAE4-C6A7CBDFC4B2}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sln.Iot.Repository", "Sln.Iot.Repository\Sln.Iot.Repository.csproj", "{DA193E49-8B4A-4C8D-B44E-844E22983DA8}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sln.Iot.Serilog", "Sln.Iot.Serilog\Sln.Iot.Serilog.csproj", "{A9CCC9F6-BE1C-4B73-AFBF-83D363D7F64F}"
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.Test", "Sln.Iot.Test\Sln.Iot.Test.csproj", "{20DC4DD8-67E0-46AC-8262-C2D4E60847B7}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sln.Iot.PLC", "Sln.Iot.PLC\Sln.Iot.PLC.csproj", "{E084583C-005D-4AB3-A634-8FA638AE6BBF}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sln.Iot.CFX", "Sln.Iot.CFX\Sln.Iot.CFX.csproj", "{596CB524-48E5-4287-B3F1-E53C4A1A1A93}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -41,10 +45,6 @@ Global
{899D8A81-D3E3-4599-8A8C-D60280A777F3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{899D8A81-D3E3-4599-8A8C-D60280A777F3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{899D8A81-D3E3-4599-8A8C-D60280A777F3}.Release|Any CPU.Build.0 = Release|Any CPU
{503E7EAE-6323-4CE2-AAE4-C6A7CBDFC4B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{503E7EAE-6323-4CE2-AAE4-C6A7CBDFC4B2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{503E7EAE-6323-4CE2-AAE4-C6A7CBDFC4B2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{503E7EAE-6323-4CE2-AAE4-C6A7CBDFC4B2}.Release|Any CPU.Build.0 = Release|Any CPU
{DA193E49-8B4A-4C8D-B44E-844E22983DA8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DA193E49-8B4A-4C8D-B44E-844E22983DA8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DA193E49-8B4A-4C8D-B44E-844E22983DA8}.Release|Any CPU.ActiveCfg = Release|Any CPU
@ -57,6 +57,18 @@ 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
{20DC4DD8-67E0-46AC-8262-C2D4E60847B7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{20DC4DD8-67E0-46AC-8262-C2D4E60847B7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{20DC4DD8-67E0-46AC-8262-C2D4E60847B7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{20DC4DD8-67E0-46AC-8262-C2D4E60847B7}.Release|Any CPU.Build.0 = Release|Any CPU
{E084583C-005D-4AB3-A634-8FA638AE6BBF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E084583C-005D-4AB3-A634-8FA638AE6BBF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E084583C-005D-4AB3-A634-8FA638AE6BBF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E084583C-005D-4AB3-A634-8FA638AE6BBF}.Release|Any CPU.Build.0 = Release|Any CPU
{596CB524-48E5-4287-B3F1-E53C4A1A1A93}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{596CB524-48E5-4287-B3F1-E53C4A1A1A93}.Debug|Any CPU.Build.0 = Debug|Any CPU
{596CB524-48E5-4287-B3F1-E53C4A1A1A93}.Release|Any CPU.ActiveCfg = Release|Any CPU
{596CB524-48E5-4287-B3F1-E53C4A1A1A93}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

@ -1,12 +1,9 @@
using System.Reflection;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Sln.Iot.Business;
using Sln.Iot.Business.@base;
using Sln.Iot.Config;
using Sln.Iot.Repository;
using Sln.Iot.Serilog;
using Sln.Iot.Socket;
using TouchSocket.Sockets;
namespace Sln.Iot
@ -29,52 +26,6 @@ namespace Sln.Iot
var log = ServiceProvider.GetService<SerilogHelper>();
log.Info($"系统启动成功,日志存放位置:{appConfig.logPath}");
var _server = ServiceProvider.GetService<TcpServer>();
_server.Init(appConfig.listernPort);
var _webSocket = ServiceProvider.GetService<WebSocketBusiness>();
_webSocket.Init();
_server.ReceivedBufferRequestInfoEvent += (client, info) =>
{
bool isRet = false;
BaseBusiness _business = null;
int bodyLength = 0;
switch (info.DataType)
{
case 0x08: //校时指令
_business = ServiceProvider.GetService<CheckTimeBusiness>();
break;
case 0x21: //登录指令
_business = ServiceProvider.GetService<LoginBusiness>();
break;
case 0x24: //心跳指令
_business = ServiceProvider.GetService<HeartBusiness>();
break;
case 0x83: //电能指令
bodyLength = 70;
_business = ServiceProvider.GetService<ElectricBusiness>();
break;
case 0x84: //水
bodyLength = 58;
_business = ServiceProvider.GetService<FluidBusiness>();
break;
case 0x85: //物联网环境
bodyLength = info.BufferLength;
_business = ServiceProvider.GetService<IotEnvBusiness>();
break;
default:
break;
}
if (_business != null)
{
Parallel.Invoke(
//() => _business.ResponseHandle(client, info.buffer),
() => _business.BufferAnalysis(client, info, bodyLength)
);
}
};
await Task.Delay(-1);
}
@ -118,9 +69,6 @@ namespace Sln.Iot
.WithSingletonLifetime());
services.AddSingleton(typeof(SerilogHelper));
services.AddSingleton(typeof(TcpService));
services.AddSqlSugarSetup();
}
}
}

@ -12,7 +12,6 @@
<ProjectReference Include="..\Sln.Iot.Business\Sln.Iot.Business.csproj" />
<ProjectReference Include="..\Sln.Iot.Common\Sln.Iot.Common.csproj" />
<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.Serilog\Sln.Iot.Serilog.csproj" />
<ProjectReference Include="..\Sln.Iot.Socket\Sln.Iot.Socket.csproj" />

Loading…
Cancel
Save