234 lines
9.2 KiB
C#
234 lines
9.2 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using System.Linq;
|
||
using System.Text;
|
||
using System.Threading.Tasks;
|
||
using HTCoreServiceApp.Common;
|
||
using HTCoreServiceApp.Models;
|
||
using HTCoreServiceApp.Communicate.ModbusTcp;
|
||
using System.Collections;
|
||
using System.Text.RegularExpressions;
|
||
using System.Diagnostics;
|
||
using System.Reflection;
|
||
using HTCoreServiceApp.WebApi;
|
||
|
||
namespace HTCoreServiceApp.DataHandle
|
||
{
|
||
public class DataExtractMB
|
||
{
|
||
public static async void DataExtractCAsync(List<MetaTag> metaTags, string systenName, string groupName, string driverName, int[] bytes, AddressArg addressArg)
|
||
{
|
||
string res = await DataExtractConsecutive(metaTags, systenName, groupName, driverName, bytes, addressArg);
|
||
}
|
||
|
||
public static async void DataExtractCAsync(List<MetaTag> metaTags, string systenName, string groupName, string driverName, int[] bytes, AddressArg addressArg, ScanTagsPara scanTagsPara)
|
||
{
|
||
string res = await DataExtractConsecutive(metaTags, systenName, groupName, driverName, bytes, addressArg, scanTagsPara);
|
||
}
|
||
|
||
public static Task<string> DataExtractConsecutive(List<MetaTag> metaTags, string systenName, string groupName, string driverName, int[] bytes, AddressArg addressArg)
|
||
{
|
||
return DataExtractConsecutive(metaTags, systenName, groupName, driverName, bytes, addressArg, null);
|
||
}
|
||
|
||
public static Task<string> DataExtractConsecutive(List<MetaTag> metaTags, string systenName, string groupName, string driverName, int[] bytes, AddressArg addressArg, ScanTagsPara scanTagsPara)
|
||
{
|
||
return Task.Run(() =>
|
||
{
|
||
long hdatetime = new DateTimeOffset(DateTime.UtcNow).ToUnixTimeMilliseconds();
|
||
List<MetaTagValue> listMetaTagValue = new List<MetaTagValue>();
|
||
try
|
||
{
|
||
//CodingTools.StartTime = DateTime.Now.Millisecond;//de
|
||
foreach (MetaTag metaTag in metaTags)
|
||
{
|
||
short datatype = metaTag.DataType;
|
||
MetaTagValue metaTagValue = PCAutoCopy(metaTag);
|
||
switch (datatype)
|
||
{
|
||
case (short)DataType.FLOAT:
|
||
metaTagValue.TagValue = GetVlaue(datatype, metaTag.Address, bytes, addressArg);
|
||
break;
|
||
case (short)DataType.BOOL:
|
||
metaTagValue.TagValue = GetVlaue(datatype, metaTag.Address, bytes, addressArg);
|
||
break;
|
||
case (short)DataType.INT:
|
||
metaTagValue.TagValue = GetVlaue(datatype, metaTag.Address, bytes, addressArg);
|
||
break;
|
||
case (short)DataType.WORD:
|
||
metaTagValue.TagValue = GetVlaue(datatype, metaTag.Address, bytes, addressArg);
|
||
break;
|
||
}
|
||
listMetaTagValue.Add(metaTagValue);
|
||
}
|
||
//CodingTools.EndTime = DateTime.Now.Millisecond;//de
|
||
//var timess = (CodingTools.EndTime - CodingTools.StartTime).ToString();
|
||
//Console.WriteLine($"转换耗时:{timess}");
|
||
//Console.WriteLine(string.Join(",", (Array)listMetaTagValue.ToArray()) + "字节数据转换完成" + ",数据量:" + listMetaTagValue.Count.ToString());
|
||
|
||
//异步缓存 - 始终执行,用于实时数据更新
|
||
Task.Run(()=>
|
||
DataLiving.DataLive2CaChe(listMetaTagValue, driverName, groupName)
|
||
);
|
||
|
||
//异步储存 - 根据存储周期控制是否执行
|
||
bool shouldStore = true;
|
||
if (scanTagsPara != null)
|
||
{
|
||
shouldStore = CheckStorageTiming(scanTagsPara, hdatetime);
|
||
}
|
||
|
||
if (shouldStore)
|
||
{
|
||
Task.Run(() =>
|
||
DataStorage.DataSave2DB(listMetaTagValue, systenName, driverName, groupName, hdatetime)
|
||
);
|
||
Console.WriteLine($"{driverName}_{groupName}执行数据存储");
|
||
}
|
||
else
|
||
{
|
||
Console.WriteLine($"{driverName}_{groupName}跳过数据存储(未到存储周期)");
|
||
}
|
||
|
||
return "0";
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
return "1";
|
||
}
|
||
});
|
||
}
|
||
|
||
/// <summary>
|
||
/// 检查是否到达存储周期
|
||
/// 每一秒(unix时间戳的每一秒内)必须触发一次存储
|
||
/// </summary>
|
||
/// <param name="scanTagsPara">扫描参数</param>
|
||
/// <param name="currentTime">当前时间戳</param>
|
||
/// <returns>是否应该执行存储</returns>
|
||
private static bool CheckStorageTiming(ScanTagsPara scanTagsPara, long currentTime)
|
||
{
|
||
// 获取当前时间戳的秒数(去掉毫秒部分)
|
||
long currentSecond = currentTime / 1000;
|
||
|
||
// 如果是第一次执行,直接存储
|
||
if (scanTagsPara.LastStorageTime == 0)
|
||
{
|
||
scanTagsPara.LastStorageTime = currentTime;
|
||
return true;
|
||
}
|
||
|
||
// 获取上次存储时间的秒数(去掉毫秒部分)
|
||
long lastStorageSecond = scanTagsPara.LastStorageTime / 1000;
|
||
|
||
// 如果当前秒数大于上次存储的秒数,说明已经进入新的一秒,需要执行存储
|
||
if (currentSecond > lastStorageSecond)
|
||
{
|
||
scanTagsPara.LastStorageTime = currentTime;
|
||
return true;
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 父类的value赋值给子类
|
||
/// </summary>
|
||
/// <param name="parent"></param>
|
||
/// <returns></returns>
|
||
private static MetaTagValue PCAutoCopy(MetaTag parent)
|
||
{
|
||
MetaTagValue child = new MetaTagValue();
|
||
|
||
|
||
var ParentType = typeof(MetaTag);
|
||
|
||
|
||
var Properties = ParentType.GetProperties();
|
||
|
||
|
||
foreach (var Propertie in Properties)
|
||
{
|
||
if (Propertie.CanRead && Propertie.CanWrite)
|
||
{
|
||
Propertie.SetValue(child, Propertie.GetValue(parent, null), null);
|
||
}
|
||
}
|
||
|
||
|
||
return child;
|
||
|
||
//listMetaTagValue.Add(new MetaTagValue()
|
||
//{
|
||
// TagId = metaTag.TagId,
|
||
|
||
// TagName = metaTag.TagName,
|
||
|
||
// DataType = metaTag.DataType,
|
||
|
||
// DataSize = metaTag.DataSize,
|
||
|
||
// Address = metaTag.Address,
|
||
|
||
// GroupId = metaTag.GroupId,
|
||
|
||
// IsActive = metaTag.IsActive,
|
||
|
||
// Archive = metaTag.Archive,
|
||
|
||
// DefaultValue = metaTag.DefaultValue,
|
||
|
||
// Description = metaTag.Description,
|
||
|
||
// Maximum = metaTag.Maximum,
|
||
|
||
// Minimum = metaTag.Minimum,
|
||
|
||
// Cycle = metaTag.Cycle,
|
||
//});
|
||
}
|
||
|
||
private static string GetVlaue(short dataType, string address, int[] bytes, AddressArg addressArg)
|
||
{
|
||
string val = "";
|
||
|
||
string startaddress = Regex.Replace(address, "[a-z]", "", RegexOptions.IgnoreCase);
|
||
int address_dem = 0;
|
||
int address_int = 0;
|
||
if (startaddress.Contains(".") && startaddress.Length > 2)
|
||
{
|
||
try
|
||
{
|
||
string[] address_arr = startaddress.Split('.');
|
||
address_int = int.Parse(address_arr[0]) - addressArg.AddressOffset;
|
||
address_dem = int.Parse(address_arr[1]);
|
||
}
|
||
catch (Exception exp)
|
||
{
|
||
//logger
|
||
}
|
||
}
|
||
else
|
||
{
|
||
address_int = int.Parse(startaddress) - addressArg.AddressOffset;
|
||
}
|
||
|
||
switch (dataType)
|
||
{
|
||
case (short)DataType.FLOAT:
|
||
return ModbusClient.ConvertRegistersToFloat(new int[] { bytes[address_int] , bytes[address_int + 1] }).ToString("0.########");
|
||
case (short)DataType.BOOL:
|
||
int[] Mask = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x100, 0x200,0x400,0x800,0x1000,0x2000,0x4000,0x8000};
|
||
if (address_dem < 0) address_dem = 0;
|
||
if (address_dem > 15) address_dem = 15;
|
||
return ((bytes[address_int] & Mask[address_dem]) != 0).ToString();
|
||
case (short)DataType.INT:
|
||
return ModbusClient.ConvertRegistersToInt(new int[] { bytes[address_int]}).ToString();
|
||
//case (short)DataType.WORD:
|
||
// return ModbusClient.ConvertRegistersToInt(bytes, address_int).ToString();
|
||
}
|
||
return val;
|
||
}
|
||
}
|
||
}
|