V1版本
This commit is contained in:
771
CapMachine.Wpf/Services/DataRecordService.cs
Normal file
771
CapMachine.Wpf/Services/DataRecordService.cs
Normal file
@@ -0,0 +1,771 @@
|
||||
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="EVAP出口温度[℃]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||||
new Columns(){ Name="冷媒流量[L/min]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||||
new Columns(){ Name="润滑油流量[L/min]",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="腔内压力[BarA]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||||
new Columns(){ Name="压缩机表面温度[℃]",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();
|
||||
|
||||
var models = ConvertToCsvRecordModel(recordChannelData.Data);
|
||||
|
||||
//数据库保存
|
||||
//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.EngValue);
|
||||
DataInfo.Add("创建时间", DateTime.Now);
|
||||
|
||||
var RecordData = new RecordChannelData()
|
||||
{
|
||||
CreateTime = DateTime.Now,
|
||||
TableName = "",
|
||||
Data = DataInfo
|
||||
|
||||
//new Dictionary<string, object>()
|
||||
//{
|
||||
// {"转速[rpm]",Random.Next(0,10)+10 +Add},
|
||||
// {"排气压力[BarA]",Random.Next(0,10)+20 +Add},
|
||||
// {"吸气压力[BarA]",Random.Next(0,10)+30 +Add},
|
||||
// {"吸气温度[℃]",Random.Next(0,10)+40 +Add},
|
||||
// {"COND1温度[℃]",Random.Next(0,10)+50 +Add},
|
||||
// {"润滑油压力[BarA]",Random.Next(0,10)+60 +Add},
|
||||
// {"COND2压力[BarA]",Random.Next(0,10)+70 +Add},
|
||||
// {"OCR[%]",Random.Next(0,10)+80 +Add},
|
||||
// {"HV[V]",Random.Next(0,10)+90 +Add},
|
||||
// {"HV[A]",Random.Next(0,10)+5 +Add},
|
||||
// {"HV[W]",Random.Next(0,10)+15 +Add},
|
||||
// {"LV[V]",Random.Next(0,10)+25 +Add},
|
||||
// {"LV[A]",Random.Next(0,10)+25 +Add},
|
||||
// {"环境温度[℃]",Random.Next(0,10)+35 +Add},
|
||||
// {"环境湿度[%]",Random.Next(0,10)+45 +Add},
|
||||
// {"OS1温度[℃]",Random.Next(0,10)+55 +Add},
|
||||
// {"OS2温度[℃]",Random.Next(0,10)+65 +Add},
|
||||
// {"COND2温度[℃]",Random.Next(0,10)+75 +Add},
|
||||
// {"EVAP出口温度[℃]",Random.Next(0,10) +85+Add},
|
||||
// {"冷媒流量[L/min]",Random.Next(0,10) +10+Add},
|
||||
// {"润滑油流量[L/min]",Random.Next(0,10)+1 +Add},
|
||||
// {"排气温度[℃]",Random.Next(0,10)+13 +Add},
|
||||
// {"膨胀阀前压力[BarA]",Random.Next(0,10)+23 +Add},
|
||||
// {"膨胀阀前温度[℃]",Random.Next(0,10) +33+Add},
|
||||
// {"EVAP出口压力[BarA]",Random.Next(0,10)+43 +Add},
|
||||
// {"腔内压力[BarA]",Random.Next(0,10) +53+Add},
|
||||
// {"压缩机表面温度[℃]",Random.Next(0,10)+63 +Add},
|
||||
// {"PTC流量[L/min]",Random.Next(0,10)+73 +Add},
|
||||
// {"PTC入水温度[℃]",Random.Next(0,10)+83 +Add},
|
||||
// {"PTC出水温度[℃]",Random.Next(0,10)+7 +Add},
|
||||
// {"通讯Cmp母线电流[A]",Random.Next(0,10)+17 +Add},
|
||||
// {"通讯Cmp母线电压[V]",Random.Next(0,10)+27 +Add},
|
||||
// {"通讯Cmp逆变器温度[℃]",Random.Next(0,10)+37 +Add},
|
||||
// {"通讯Cmp相电流[A]",Random.Next(0,10)+47 +Add},
|
||||
// {"通讯Cmp功率[W]",Random.Next(0,10)+57 +Add},
|
||||
// {"通讯Cmp芯片温度[℃]",Random.Next(0,10) +67+Add},
|
||||
// {"通讯PTC入水温度[℃]",Random.Next(0,10)+77 +Add},
|
||||
// {"通讯PTC出水温度[℃]",Random.Next(0,10) +87+Add},
|
||||
// {"通讯PTC峰值电流[A]",Random.Next(0,10)+1 +Add},
|
||||
// {"通讯PTC母线电流[A]",Random.Next(0,10)+16 +Add},
|
||||
// {"通讯PTC膜温[℃]",Random.Next(0,10)+26 +Add},
|
||||
// {"通讯PTC模块温度[℃]",Random.Next(0,10)+39 +Add},
|
||||
// {"创建时间",DateTime.Now},
|
||||
//},
|
||||
};
|
||||
|
||||
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
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user