742 lines
36 KiB
C#
742 lines
36 KiB
C#
using CapMachine.Core;
|
||
using CapMachine.Model;
|
||
using CapMachine.Model.ModelMapConfig;
|
||
using CapMachine.Wpf.ChannelModel;
|
||
using CapMachine.Wpf.Models;
|
||
using CapMachine.Wpf.PrismEvent;
|
||
using CsvHelper;
|
||
using CsvHelper.Configuration;
|
||
using CsvHelper.Configuration.Attributes;
|
||
using FreeSql.Extensions.ZeroEntity;
|
||
using Masuit.Tools;
|
||
using Newtonsoft.Json;
|
||
using NPOI.Util;
|
||
using Prism.Events;
|
||
using Prism.Mvvm;
|
||
using System;
|
||
using System.Collections.Concurrent;
|
||
using System.Collections.Generic;
|
||
using System.Diagnostics;
|
||
using System.Globalization;
|
||
using System.IO;
|
||
using System.Linq;
|
||
using System.Reflection;
|
||
using System.Text;
|
||
using System.Threading.Channels;
|
||
using System.Threading.Tasks;
|
||
using System.Timers;
|
||
using System.Windows;
|
||
|
||
namespace CapMachine.Wpf.Services
|
||
{
|
||
/// <summary>
|
||
/// 数据记录服务功能
|
||
/// </summary>
|
||
public class DataRecordService : BindableBase
|
||
{
|
||
/// <summary>
|
||
/// 实例化函数
|
||
/// </summary>
|
||
public DataRecordService(MachineRtDataService machineRtDataService, IEventAggregator eventAggregator, ConfigService configService, ILogService logService, IFreeSql FreeSql)
|
||
{
|
||
MachineRtDataService = machineRtDataService;
|
||
ConfigService = configService;
|
||
LogService = logService;
|
||
this.FreeSql = FreeSql;
|
||
//事件服务
|
||
_EventAggregator = eventAggregator;
|
||
|
||
ListRecordModelMap = new List<ModelMap>()
|
||
{
|
||
////测试用TestTable
|
||
//new ModelMap(){
|
||
// Name="TestTable",
|
||
// Comment="测试Table",
|
||
// Columns=new List<Columns>(){
|
||
// new Columns(){ Name="Id",MapType="System.Int32",IsIdentity=true,IsPrimary=true},
|
||
// new Columns(){ Name="Name",MapType="System.String",IsIdentity=false,IsPrimary=false,StringLength=20},
|
||
// new Columns(){ Name="Value",MapType=typeof(decimal).ToString(),IsIdentity=false,IsPrimary=false,Precision=8,Scale=2},
|
||
// new Columns(){ Name="IntValue",MapType=typeof(Int16).ToString(),IsIdentity=false,IsPrimary=false},
|
||
// new Columns(){ Name="FloatValue",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||
// new Columns(){ Name="Content",MapType="System.String",IsIdentity=false,IsPrimary=false,StringLength=20},
|
||
// new Columns(){ Name="CreateTime",MapType="System.DateTime",IsIdentity=false,IsPrimary=false},
|
||
// }
|
||
//},
|
||
|
||
//new ModelMap(){
|
||
// Name="Record",
|
||
// Comment="工况数据记录",
|
||
// Columns=new List<Columns>(){
|
||
// new Columns(){ Name="Id",MapType="System.Int32",IsIdentity=true,IsPrimary=true},
|
||
// new Columns(){ Name="WorkCondName",MapType="System.String",IsIdentity=false,IsPrimary=false,StringLength=20},
|
||
// new Columns(){ Name="Speed",MapType=typeof(Int16).ToString(),IsIdentity=false,IsPrimary=false},
|
||
// new Columns(){ Name="Cond1Temp",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||
// new Columns(){ Name="Cond2Temp",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||
// new Columns(){ Name="Cond2Press",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||
// new Columns(){ Name="EVAPExpTemp",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||
// new Columns(){ Name="ExPress",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||
// new Columns(){ Name="HVVol",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||
// new Columns(){ Name="InhPress",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||
// new Columns(){ Name="InhTemp",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||
// new Columns(){ Name="LubePress",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||
// new Columns(){ Name="LVVol",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||
// new Columns(){ Name="OCR",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||
// new Columns(){ Name="OS1Temp",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||
// new Columns(){ Name="OS2Temp",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||
// new Columns(){ Name="PTCEntTemp",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||
// new Columns(){ Name="PTCFlow",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||
// new Columns(){ Name="PTCPw",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||
// new Columns(){ Name="EnvRH",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||
// new Columns(){ Name="EnvTemp",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||
// new Columns(){ Name="OutLock",MapType=typeof(bool).ToString(),IsIdentity=false,IsPrimary=false},
|
||
// new Columns(){ Name="ParNo",MapType=typeof(Int16).ToString(),IsIdentity=false,IsPrimary=false},
|
||
// new Columns(){ Name="Ev",MapType=typeof(Int16).ToString(),IsIdentity=false,IsPrimary=false},
|
||
// new Columns(){ Name="CapEnable",MapType=typeof(bool).ToString(),IsIdentity=false,IsPrimary=false},
|
||
// new Columns(){ Name="InhExhValve",MapType=typeof(Int16).ToString(),IsIdentity=false,IsPrimary=false},
|
||
// new Columns(){ Name="PTCEnable",MapType=typeof(bool).ToString(),IsIdentity=false,IsPrimary=false},
|
||
// new Columns(){ Name="CreateTime",MapType="System.DateTime",IsIdentity=false,IsPrimary=false},
|
||
// }
|
||
//}
|
||
|
||
new ModelMap(){
|
||
Name="Record",
|
||
Comment="工况数据记录",
|
||
Columns=new List<Columns>(){
|
||
new Columns(){ Name="Id",MapType="System.Int64",IsIdentity=true,IsPrimary=true},
|
||
new Columns(){ Name="工况",MapType="System.String",IsIdentity=false,IsPrimary=false,StringLength=100},
|
||
new Columns(){ Name="转速[rpm]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||
new Columns(){ Name="排气压力[BarA]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||
new Columns(){ Name="吸气压力[BarA]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||
new Columns(){ Name="吸气温度[℃]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||
new Columns(){ Name="COND1温度[℃]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||
new Columns(){ Name="润滑油压力[BarA]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||
new Columns(){ Name="COND2压力[BarA]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||
new Columns(){ Name="OCR[%]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||
new Columns(){ Name="HV[V]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||
new Columns(){ Name="HV[A]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||
new Columns(){ Name="HV[W]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||
new Columns(){ Name="LV[V]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||
new Columns(){ Name="LV[A]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||
new Columns(){ Name="环境温度[℃]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||
new Columns(){ Name="环境湿度[%]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||
new Columns(){ Name="OS1温度[℃]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||
new Columns(){ Name="OS2温度[℃]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||
new Columns(){ Name="COND2温度[℃]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||
new Columns(){ Name="吸气电加热温度[℃]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||
new Columns(){ Name="冷媒流量[kg/h]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||
new Columns(){ Name="润滑油流量[kg/h]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||
new Columns(){ Name="排气温度[℃]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||
new Columns(){ Name="膨胀阀前压力[BarA]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||
new Columns(){ Name="膨胀阀前温度[℃]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||
new Columns(){ Name="EVAP出口压力[BarA]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||
new Columns(){ Name="EVAP出口温度[℃]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||
new Columns(){ Name="背压压力[BarA]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||
new Columns(){ Name="压缩机表面温度[℃]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||
|
||
new Columns(){ Name="液冷媒流量[kg/h]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||
new Columns(){ Name="绝缘电阻[KΩ]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||
new Columns(){ Name="过热度[K]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||
new Columns(){ Name="过冷度[K]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||
|
||
new Columns(){ Name="制热量Qh[W]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||
new Columns(){ Name="压缩机性能系数(制热)",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||
new Columns(){ Name="等熵效率ns[%]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||
new Columns(){ Name="制冷量Qc[W]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||
new Columns(){ Name="压缩机性能系数(制冷)",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||
new Columns(){ Name="容积效率nv[%]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||
|
||
//new Columns(){ Name="PTC流量[L/min]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||
//new Columns(){ Name="PTC入水温度[℃]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||
//new Columns(){ Name="PTC出水温度[℃]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||
new Columns(){ Name="通讯Cmp母线电流[A]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||
new Columns(){ Name="通讯Cmp母线电压[V]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||
new Columns(){ Name="通讯Cmp逆变器温度[℃]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||
new Columns(){ Name="通讯Cmp相电流[A]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||
new Columns(){ Name="通讯Cmp功率[W]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||
new Columns(){ Name="通讯Cmp芯片温度[℃]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||
//new Columns(){ Name="通讯PTC入水温度[℃]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||
//new Columns(){ Name="通讯PTC出水温度[℃]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||
//new Columns(){ Name="通讯PTC峰值电流[A]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||
//new Columns(){ Name="通讯PTC母线电流[A]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||
//new Columns(){ Name="通讯PTC膜温[℃]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||
//new Columns(){ Name="通讯PTC模块温度[℃]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||
|
||
|
||
new Columns(){ Name="创建时间",MapType="System.DateTime",IsIdentity=false,IsPrimary=false},
|
||
}
|
||
}
|
||
};
|
||
|
||
ListRecordKeyValue = new List<RecordKeyValue>()
|
||
{
|
||
new RecordKeyValue(){
|
||
TableName="TestTable",
|
||
KeyValuePairs=new Dictionary<string, object>(){
|
||
{ "Name", "testName" },
|
||
{ "Content", "user1deContentss" },
|
||
{ "Value", 3.4 },
|
||
{ "IntValue", 23 },
|
||
{ "FloatValue", 3.569 },
|
||
{ "CreateTime", DateTime.Now.ToString() },
|
||
}
|
||
},
|
||
};
|
||
|
||
var JsonModelMap = JsonConvert.SerializeObject(ListRecordModelMap);
|
||
|
||
//秒触发一次
|
||
CycleTimer = new System.Timers.Timer(ConfigService.RecordCycle);
|
||
CycleTimer.Elapsed += RecoredCycleAction;
|
||
CycleTimer.AutoReset = true;
|
||
CycleTimer.Enabled = true;
|
||
|
||
|
||
//var json = "[\r\n {\r\n \"Name\":\"User\",\r\n \"Comment\":\"用户表\",\r\n \"Columns\": [\r\n {\"Name\":\"Id\",\"IsPrimary\":true,\"IsIdentity\":true,\"MapType\":\"System.Int32\"},\r\n {\"Name\":\"Name\",\"MapType\":\"System.String\"}\r\n ],\r\n \"Navigates\":[\r\n {\"Name\":\"Ext\",\"Type\":\"OneToOne\",\"RelTable\":\"UserExt\"},\r\n {\"Name\":\"Claims\",\"Type\":\"OneToMany\",\"RelTable\":\"UserClaim\",\"Bind\":\"UserId\"},\r\n {\"Name\":\"Roles\",\"Type\":\"ManyToMany\",\"RelTable\":\"Role\",\"ManyToMany\":\"UserRole\"}\r\n ],\r\n \"Indexes\":[]\r\n },\r\n {\r\n \"Name\":\"UserExt\",\r\n \"Comment\":\"用户扩展信息表\",\r\n \"Columns\":[\r\n {\"Name\":\"UserId\",\"IsPrimary\":true,\"MapType\":\"System.Int32\"},\r\n ],\r\n \"Navigates\":[\r\n {\"Name\":\"Remarks\",\"Type\":\"OneToMany\",\"RelTable\":\"UserExtRemarks\",\"Bind\":\"UserId\"},\r\n ],\r\n },\r\n {\r\n \"Name\":\"UserExtRemarks\",\r\n \"Comment\":\"用户扩展信息表-子表\",\r\n \"Columns\":[\r\n {\"Name\":\"RemarkId\",\"IsPrimary\":true,\"MapType\":\"System.Guid\"},\r\n {\"Name\":\"UserId\",\"MapType\":\"System.Int32\"},\r\n {\"Name\":\"Remark\",\"MapType\":\"System.String\"},\r\n ],\r\n },\r\n {\r\n \"Name\":\"UserClaim\",\r\n \"Comment\":\"一对多测试表\",\r\n \"Columns\":[\r\n {\"Name\":\"Id\",\"IsPrimary\":true,\"IsIdentity\":true,\"MapType\":\"System.Int32\"},\r\n {\"Name\":\"UserId\",\"MapType\":\"System.Int32\"},\r\n {\"Name\":\"ClaimName\",\"MapType\":\"System.String\"},\r\n ],\r\n },\r\n {\r\n \"Name\":\"Role\",\r\n \"Comment\":\"权限表\",\r\n \"Columns\":[\r\n {\"Name\":\"Id\",\"IsPrimary\":true,\"IsIdentity\":true,\"MapType\":\"System.Int32\"},\r\n {\"Name\":\"Name\",\"MapType\":\"System.String\"}\r\n ],\r\n \"Navigates\":[\r\n {\"Name\":\"Users\",\"Type\":\"ManyToMany\",\"RelTable\":\"User\",\"ManyToMany\":\"UserRole\"}\r\n ],\r\n \"Indexes\":[]\r\n },\r\n {\r\n \"Name\":\"UserRole\",\r\n \"Comment\":\"多对多中间表\",\r\n \"Columns\":[\r\n {\"Name\":\"UserId\",\"IsPrimary\":true,\"MapType\":\"System.Int32\"},\r\n {\"Name\":\"RoleId\",\"IsPrimary\":true,\"MapType\":\"System.Int32\"}\r\n ],\r\n \"Navigates\":[\r\n {\"Name\":\"User\",\"Type\":\"ManyToOne\",\"RelTable\":\"User\",\"Bind\":\"UserId\"},\r\n {\"Name\":\"Role\",\"Type\":\"ManyToOne\",\"RelTable\":\"Role\",\"Bind\":\"RoleId\"}\r\n ]\r\n }\r\n]\r\n";
|
||
//zeroDbContext = new ZeroDbContext(this.FreeSql, JsonConvert.DeserializeObject<TableDescriptor[]>(JsonModelMap)); //在文档后面
|
||
|
||
//var item = JsonConvert.DeserializeObject<Dictionary<string, object>>(@"
|
||
// {
|
||
// //""Id"":1,
|
||
// ""Name"":""user1"",
|
||
// ""Content"":""user1deContent"",
|
||
// ""Value"":3.4,
|
||
// ""IntValue"":23,
|
||
// ""FloatValue"":3.569,
|
||
// ""CreateTime"":""2024-09-30 11:47"",
|
||
|
||
// }");
|
||
|
||
//插入数据
|
||
//zeroDbContext.Insert(ListRecordKeyValue.Find(a => a.TableName == "TestTable")!.KeyValuePairs);
|
||
|
||
//var dd = FreeSql.InsertDict(new Dictionary<string, object>()
|
||
//{
|
||
// { "Name", "PC" },
|
||
// { "Mark", "dds" },
|
||
// { "Price", 1000 },
|
||
// { "CreateTime", DateTime.Now },
|
||
|
||
//}).AsTable("RecordData").ExecuteAffrows();
|
||
|
||
//实时数据记录管道数据监听
|
||
Task.Run(() => ListenRecoredChannelAction());
|
||
|
||
}
|
||
|
||
/// <summary>
|
||
/// 事件聚合器
|
||
/// </summary>
|
||
private IEventAggregator _EventAggregator { get; set; }
|
||
|
||
/// <summary>
|
||
/// DbContext信息
|
||
/// </summary>
|
||
private ZeroDbContext zeroDbContext { get; set; }
|
||
|
||
/// <summary>
|
||
/// 数据记录字段模型
|
||
/// 定义表名称
|
||
/// 定义表字段的信息
|
||
/// 定义主外键的表的关系
|
||
/// </summary>
|
||
public List<ModelMap> ListRecordModelMap { get; set; }
|
||
|
||
/// <summary>
|
||
/// 要记录的每个表格的键值对数据
|
||
/// </summary>
|
||
public List<RecordKeyValue> ListRecordKeyValue { get; set; }
|
||
|
||
/// <summary>
|
||
/// 周期定时器
|
||
/// </summary>
|
||
private System.Timers.Timer CycleTimer { get; set; }
|
||
|
||
private bool _IsRecord;
|
||
/// <summary>
|
||
/// 是否记录
|
||
/// </summary>
|
||
public bool IsRecord
|
||
{
|
||
get { return _IsRecord; }
|
||
set { _IsRecord = value; RaisePropertyChanged(); }
|
||
}
|
||
|
||
/// <summary>
|
||
/// 设备实时数据功能服务
|
||
/// </summary>
|
||
public MachineRtDataService MachineRtDataService { get; }
|
||
|
||
/// <summary>
|
||
/// 配置功能服务
|
||
/// </summary>
|
||
public ConfigService ConfigService { get; }
|
||
public ILogService LogService { get; }
|
||
public IFreeSql FreeSql { get; }
|
||
|
||
#region 队列的操作
|
||
|
||
/// <summary>
|
||
/// 队列通道
|
||
/// 当前队列消费周期触发的数据记录
|
||
/// </summary>
|
||
public Channel<RecordChannelData> RecoredChannelInfo = Channel.CreateUnbounded<RecordChannelData>(new UnboundedChannelOptions()
|
||
{
|
||
SingleWriter = false,//允许一次写入多条数据
|
||
SingleReader = true //一次只能读取一条消息
|
||
});
|
||
|
||
/// <summary>
|
||
/// 缓存的集合数据
|
||
/// </summary>
|
||
public List<RecordChannelData> CacheRecordData { get; set; } = new List<RecordChannelData>();
|
||
|
||
/// <summary>
|
||
/// 当前缓存的队列信息
|
||
/// 高效的队列数据
|
||
/// </summary>
|
||
public ConcurrentQueue<RecordChannelData> ConcurrentQueueData { get; set; } = new ConcurrentQueue<RecordChannelData>();
|
||
|
||
|
||
/// <summary>
|
||
/// 最大的缓存单元数据
|
||
/// 存储超过规定60个缓存数据后进行判断后删除
|
||
/// </summary>
|
||
private int MaxCacheCellCount { get; set; } = 0;
|
||
|
||
/// <summary>
|
||
/// 数据记录管道监听方法
|
||
/// </summary>
|
||
/// <exception cref="NotImplementedException"></exception>
|
||
private async void ListenRecoredChannelAction()
|
||
{
|
||
while (await RecoredChannelInfo.Reader.WaitToReadAsync())
|
||
{
|
||
if (RecoredChannelInfo.Reader.TryRead(out var recordChannelData))
|
||
{
|
||
////第一次计时
|
||
//stopwatch.Start(); //启动Stopwatch
|
||
|
||
//新增数据
|
||
CacheRecordData.Add(recordChannelData);
|
||
MaxCacheCellCount++;
|
||
|
||
//先判断缓存的单元大小,防止每次都检查删除,数据达到时间范围外的话,则删除,即是600次后进行一次判断删除
|
||
if (MaxCacheCellCount >= 600)
|
||
{
|
||
//不在缓存的时间范围内的话,则删除数据
|
||
if (CacheRecordData.Where(a => a.CreateTime <= DateTime.Now.AddSeconds(-ConfigService.ChartRtDataCacheTimeSec)).Any())
|
||
{
|
||
CacheRecordData.RemoveAll(a => a.CreateTime <= DateTime.Now.AddSeconds(-ConfigService.ChartRtDataCacheTimeSec));
|
||
}
|
||
MaxCacheCellCount = 0;
|
||
}
|
||
|
||
//ConcurrentQueueData.
|
||
|
||
//Prism发布数据
|
||
_EventAggregator.GetEvent<RecordDataEvent>().Publish(recordChannelData.DeepClone());
|
||
|
||
//判断集合的数据是否达到要求
|
||
//if (CacheRecordData.Count >= MaxCacheCount)
|
||
//{
|
||
//CacheRecordData可能存在多个表格数据,依据表名进行分类
|
||
|
||
//考虑多个表结构
|
||
//var GroupTableData = CacheRecordData.GroupBy(a => a.TableName).ToList();
|
||
|
||
//foreach (var ItemData in GroupTableData)
|
||
//{
|
||
//表名称
|
||
//var TableName = ItemData.Key;
|
||
//当前表格的数据
|
||
//var Datas = ItemData.Select(item => item.Data).ToList();
|
||
|
||
//var Datas = recordChannelData.Select(item => item.Data).ToList();
|
||
|
||
//List<CsvRecordModel> models = Datas.Select(dict => ConvertToCsvRecordModel(dict)).ToList();
|
||
|
||
//转换到CSV的数据
|
||
var models = ConvertToCsvRecordModel(recordChannelData.Data);
|
||
//填充工况名称
|
||
models.WorkCond = ConfigService.CurExpInfo.Name;
|
||
|
||
//数据库保存
|
||
//zeroDbContext.Insert(Datas);
|
||
|
||
//CSV文件保存
|
||
SaveToCsv(new List<CsvRecordModel>() { models });
|
||
//}
|
||
|
||
//CacheRecordData.Clear();
|
||
|
||
//Console.WriteLine($"{DateTime.Now.ToString("HH:mm:ss:fff")}-{LineName}-保存成功!");
|
||
//}
|
||
|
||
|
||
//stopwatch.Stop(); //停止Stopwatch
|
||
//Console.WriteLine("保存数据耗时::{0}", stopwatch.Elapsed.TotalSeconds.ToString());
|
||
//stopwatch.Reset();
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 转换到CsvRecordModel
|
||
/// </summary>
|
||
/// <param name="dict"></param>
|
||
/// <returns></returns>
|
||
public static CsvRecordModel ConvertToCsvRecordModel(Dictionary<string, object> dict)
|
||
{
|
||
CsvRecordModel model = new CsvRecordModel();
|
||
|
||
foreach (var kvp in dict)
|
||
{
|
||
//var property = typeof(CsvRecordModel).GetProperty(kvp.Key);
|
||
var property = GetPropertyByName(kvp.Key);
|
||
if (property != null && kvp.Value != null)
|
||
{
|
||
property.SetValue(model, Convert.ChangeType(kvp.Value, property.PropertyType));
|
||
}
|
||
}
|
||
|
||
//增加日期和时间两个列
|
||
model.WorkDay = model.CreateTime.ToString("yyyy-MM-dd");
|
||
model.Time = model.CreateTime.ToString("HH:mm:ss");
|
||
|
||
|
||
|
||
return model;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取属性的名称
|
||
/// [Name("通讯PTC出水温度")] 获取其名称
|
||
/// </summary>
|
||
/// <param name="name"></param>
|
||
/// <returns></returns>
|
||
private static PropertyInfo GetPropertyByName(string name)
|
||
{
|
||
var properties = typeof(CsvRecordModel).GetProperties();
|
||
foreach (var property in properties)
|
||
{
|
||
var attr = property.GetCustomAttribute<Models.NameAttribute>();
|
||
if (attr != null && attr.Name == name)
|
||
{
|
||
return property;
|
||
}
|
||
}
|
||
return null;
|
||
}
|
||
|
||
#endregion
|
||
|
||
|
||
|
||
|
||
|
||
private Random Random = new Random();
|
||
private int Add = 1;
|
||
Stopwatch stopwatch = new Stopwatch();
|
||
|
||
/// <summary>
|
||
/// 记录周期内容
|
||
/// </summary>
|
||
/// <param name="sender"></param>
|
||
/// <param name="e"></param>
|
||
/// <exception cref="NotImplementedException"></exception>
|
||
private void RecoredCycleAction(object? sender, ElapsedEventArgs e)
|
||
{
|
||
try
|
||
{
|
||
//如果Execute执行的是一个很耗时的方法,会导致方法未执行完毕,定时器又启动了一个线程来执行Execute方法
|
||
//CycleTimer.Stop(); //先关闭定时器
|
||
|
||
var DataInfo = MachineRtDataService.TagManger.DicTags
|
||
.ToDictionary(kvp => kvp.Key, kvp => (object)kvp.Value.EngPvValue);
|
||
DataInfo.Add("创建时间", DateTime.Now);
|
||
|
||
var RecordData = new RecordChannelData()
|
||
{
|
||
CreateTime = DateTime.Now,
|
||
TableName = "",
|
||
Data = DataInfo
|
||
};
|
||
|
||
if (IsRecord)
|
||
{
|
||
//本体数据记录
|
||
RecoredChannelInfo.Writer.WriteAsync(RecordData);
|
||
}
|
||
|
||
|
||
|
||
|
||
//CycleTimer.Start(); //执行完毕后再开启器
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
//CycleTimer.Start(); //执行完毕后再开启器
|
||
LogService.Info($"时间:{DateTime.Now.ToString()}-【PwAnalyze-CycleAction】-{ex.Message}");
|
||
}
|
||
}
|
||
|
||
|
||
#region 数据记录模型操作
|
||
|
||
/// <summary>
|
||
/// 创建 ModelMappTable
|
||
/// </summary>
|
||
/// <param name="TableName"></param>
|
||
/// <returns></returns>
|
||
private ModelMap CreateModelMappTable(string TableName)
|
||
{
|
||
var NewTable = new ModelMap()
|
||
{
|
||
Name = TableName,
|
||
Comment = TableName,
|
||
Columns = new List<Columns>(),
|
||
};
|
||
|
||
//新增到数据库中
|
||
var NewModelMap = FreeSql.Insert<ModelMap>(NewTable).ExecuteInserted();
|
||
|
||
return NewModelMap.FirstOrDefault()!;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 增加字符串列
|
||
/// </summary>
|
||
/// <param name="Name"></param>
|
||
/// <param name="MapType"></param>
|
||
/// <param name="IsPrimary"></param>
|
||
/// <param name="IsIdentity"></param>
|
||
/// <returns></returns>
|
||
private Columns CreateStringColumn(string Name, string MapType, short StringLength, bool IsPrimary, bool IsIdentity)
|
||
{
|
||
return new Columns()
|
||
{
|
||
Name = Name,
|
||
MapType = MapType,
|
||
IsIdentity = IsIdentity,
|
||
StringLength = StringLength,
|
||
IsPrimary = IsPrimary,
|
||
};
|
||
}
|
||
|
||
/// <summary>
|
||
/// 增加IntFloatBool列
|
||
/// </summary>
|
||
/// <param name="Name"></param>
|
||
/// <param name="MapType"></param>
|
||
/// <param name="IsPrimary"></param>
|
||
/// <param name="IsIdentity"></param>
|
||
/// <returns></returns>
|
||
private Columns CreateIntFloatBoolColumn(string Name, string MapType, bool IsPrimary, bool IsIdentity)
|
||
{
|
||
return new Columns()
|
||
{
|
||
Name = Name,
|
||
MapType = MapType,
|
||
IsIdentity = IsIdentity,
|
||
IsPrimary = IsPrimary,
|
||
};
|
||
}
|
||
|
||
/// <summary>
|
||
/// 增加DateTime列
|
||
/// </summary>
|
||
/// <param name="Name"></param>
|
||
/// <param name="MapType"></param>
|
||
/// <param name="IsPrimary"></param>
|
||
/// <param name="IsIdentity"></param>
|
||
/// <returns></returns>
|
||
private Columns CreateDateTimeColumn(string Name, string MapType, bool IsPrimary, bool IsIdentity)
|
||
{
|
||
return new Columns()
|
||
{
|
||
Name = Name,
|
||
MapType = MapType,
|
||
IsIdentity = IsIdentity,
|
||
IsPrimary = IsPrimary,
|
||
};
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 增加Decimal列
|
||
/// </summary>
|
||
/// <param name="Name"></param>
|
||
/// <param name="MapType"></param>
|
||
/// <param name="IsPrimary"></param>
|
||
/// <param name="IsIdentity"></param>
|
||
/// <returns></returns>
|
||
private Columns CreateDecimalColumn(string Name, string MapType, short Precision, short Scale, bool IsPrimary, bool IsIdentity)
|
||
{
|
||
return new Columns()
|
||
{
|
||
Name = Name,
|
||
MapType = MapType,
|
||
IsIdentity = IsIdentity,
|
||
IsPrimary = IsPrimary,
|
||
Precision = Precision,
|
||
Scale = Scale,
|
||
};
|
||
}
|
||
|
||
|
||
#endregion
|
||
|
||
/// <summary>
|
||
/// 开始运行或者开始记录
|
||
/// </summary>
|
||
public void StartRecord()
|
||
{
|
||
|
||
|
||
//首先清除清除本地试验工况缓存的数据
|
||
CacheRecordData.Clear();
|
||
|
||
if (ConfigService.CurExpInfo != null)
|
||
{
|
||
|
||
|
||
//判断是否已经有了当前的试验工况信息
|
||
var ExisData = FreeSql.Select<HistoryExp>().Where(a => a.Name == ConfigService.CurExpInfo.Name).IncludeMany(a => a.HistoryWorkCondFiles);
|
||
if (ExisData.Count() > 0)
|
||
{
|
||
ConfigService.CurExpInfo = ExisData.First()!;
|
||
|
||
}
|
||
|
||
IsRecord = true;
|
||
|
||
//var RecordHistoryExp = FreeSql.Insert<HistoryExp>(new HistoryExp()
|
||
//{
|
||
// Name = "试验测试工况",
|
||
// WorkCond = "测试工况",
|
||
//}).ExecuteInserted();
|
||
|
||
//if (RecordHistoryExp != null)
|
||
//{
|
||
// ConfigService.CurExpInfo = RecordHistoryExp.FirstOrDefault()!;
|
||
//}
|
||
}
|
||
else
|
||
{
|
||
IsRecord = false;
|
||
MessageBox.Show("当前试验信息未填写,无法开始记录数据", "提示", MessageBoxButton.OK, MessageBoxImage.Hand);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 结束记录数据
|
||
/// </summary>
|
||
public void EndRecord()
|
||
{
|
||
IsRecord = false;
|
||
|
||
//不可以清除清除本地试验工况缓存的数据,因为可能实时数据会分析使用 //CacheRecordData.Clear();
|
||
|
||
if (ConfigService.CurExpInfo != null)
|
||
{
|
||
var ListUpdate = FreeSql.Update<HistoryExp>()
|
||
.Set(a => a.IsComplete, true)
|
||
.Where(a => a.Id == ConfigService.CurExpInfo.Id)
|
||
.ExecuteUpdated();
|
||
|
||
ConfigService.CurExpInfo = ListUpdate.FirstOrDefault()!;
|
||
}
|
||
|
||
}
|
||
|
||
/// <summary>
|
||
/// 更新当前的试验信息
|
||
/// </summary>
|
||
private void CreateUpdateCurHistoryExp(string Name, string FileFullInfo)
|
||
{
|
||
var RecordHistoryExp = FreeSql.Insert<HistoryWorkCondFile>(new HistoryWorkCondFile()
|
||
{
|
||
WorkDay = DateTime.Now.ToString("yyyy-MM-dd"),
|
||
FilePath = FileFullInfo,
|
||
HistoryExpId = ConfigService.CurExpInfo.Id,
|
||
}).ExecuteInserted();
|
||
//更新数据
|
||
ConfigService.CurExpInfo = FreeSql.Select<HistoryExp>().Where(a => a.Name == Name).IncludeMany(a => a.HistoryWorkCondFiles).First();
|
||
}
|
||
|
||
#region CSV Helper 数据保存CSV
|
||
|
||
|
||
|
||
/// <summary>
|
||
/// CSV文件保存根路径
|
||
/// </summary>
|
||
private string SaveCsvRootPath { get; set; }
|
||
|
||
/// <summary>
|
||
/// Append to the file.
|
||
/// </summary>
|
||
CsvConfiguration CSVconfig { get; set; } = new CsvConfiguration(CultureInfo.CurrentCulture)
|
||
{
|
||
// Don't write the header again.
|
||
HasHeaderRecord = false,
|
||
};
|
||
|
||
/// <summary>
|
||
/// 保存到CSV文件
|
||
/// </summary>
|
||
private void SaveToCsv(List<CsvRecordModel> csvRecordModels)
|
||
{
|
||
//年份的文件是否存在
|
||
var FilePath = FileHelper.GetExpFilePath(ConfigService.SaveCsvRootPath, ConfigService.CurExpInfo.Name);
|
||
if (!Directory.Exists(FilePath))
|
||
{
|
||
Directory.CreateDirectory(FilePath);
|
||
}
|
||
|
||
//文件全部路径信息
|
||
var FileFullInfo = FileHelper.GetCSVPath(FilePath);
|
||
if (!File.Exists(FileFullInfo))//是否存在文件
|
||
{
|
||
lock (ConfigService.CsvFileLock)
|
||
{
|
||
//新增的文件
|
||
using (var writer = new StreamWriter(FileFullInfo, false, Encoding.UTF8))
|
||
using (var csv = new CsvWriter(writer, CultureInfo.CurrentCulture))
|
||
{
|
||
var Result = csv.Context.RegisterClassMap<CsvRecordModelMap>();
|
||
|
||
csv.WriteRecords(csvRecordModels);
|
||
}
|
||
}
|
||
|
||
//创建和更新当前试验信息
|
||
CreateUpdateCurHistoryExp(ConfigService.CurExpInfo.Name, FileFullInfo);
|
||
|
||
}
|
||
else//存在文件的话则新增数据
|
||
{
|
||
lock (ConfigService.CsvFileLock)
|
||
{
|
||
//往已有的文件增加数据
|
||
using (var stream = File.Open(FileFullInfo, FileMode.Append, FileAccess.Write, FileShare.ReadWrite))
|
||
//using (var stream = new FileStream(FileFullInfo, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite))
|
||
using (var writer = new StreamWriter(stream))
|
||
using (var csv = new CsvWriter(writer, CSVconfig))
|
||
{
|
||
csv.Context.RegisterClassMap<CsvRecordModelMap>();
|
||
csv.WriteRecords(csvRecordModels);
|
||
}
|
||
}
|
||
|
||
}
|
||
}
|
||
|
||
|
||
#endregion
|
||
|
||
}
|
||
|
||
|
||
}
|