添加项目文件。
This commit is contained in:
@@ -0,0 +1,122 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace JinYuan.Helper
|
||||
{
|
||||
public class ArrayHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// 判断两个数组的元素是否相等
|
||||
/// </summary>
|
||||
/// <param name="arr1"></param>
|
||||
/// <param name="arr2"></param>
|
||||
/// <returns></returns>
|
||||
public static bool Equal<T>(T[] arr1, T[] arr2)
|
||||
{
|
||||
bool res = false;
|
||||
if (arr1 == null || arr2 == null)
|
||||
{
|
||||
return res;
|
||||
}
|
||||
if (arr1.Length == arr2.Length)
|
||||
{
|
||||
res = true;
|
||||
for (int index = 0; index < arr1.Length; ++index)
|
||||
{
|
||||
if (!arr1[index].Equals(arr2[index]))
|
||||
{
|
||||
res = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取数组的子数组
|
||||
/// </summary>
|
||||
/// <typeparam name="T">类型</typeparam>
|
||||
/// <param name="arr">数组</param>
|
||||
/// <param name="startIndex">起始索引</param>
|
||||
/// <param name="length">长度</param>
|
||||
/// <returns></returns>
|
||||
public static T[] GetSubArray<T>(T[] arr, int startIndex, int length)
|
||||
{
|
||||
T[] res = new T[length];
|
||||
for (int index = 0; index < length; ++index)
|
||||
{
|
||||
res[index] = arr[startIndex + index];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 数组合并
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="t1"></param>
|
||||
/// <param name="t2"></param>
|
||||
/// <returns></returns>
|
||||
public static byte[] Combine(IEnumerable<byte[]> tList)
|
||||
{
|
||||
int allLength = 0;
|
||||
foreach (byte[] t in tList)
|
||||
{
|
||||
allLength += t.Length;
|
||||
}
|
||||
byte[] res = new byte[allLength];
|
||||
int lenIndex = 0;
|
||||
foreach (byte[] t in tList)
|
||||
{
|
||||
Array.Copy(t, 0, res, lenIndex, t.Length);
|
||||
lenIndex += t.Length;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 数组格式化输出字符串
|
||||
/// </summary>
|
||||
/// <param name="arr">待处理数据</param>
|
||||
/// <returns></returns>
|
||||
public static string ArrayFormatOutput<T>(T[] arr)
|
||||
{
|
||||
StringBuilder res = new StringBuilder();
|
||||
for (int index = 0; index < arr.Count() - 1; ++index)
|
||||
{
|
||||
res.Append(string.Format("{0}-", arr[index].ToString()));
|
||||
}
|
||||
if (arr.Count() - 1 > 0)
|
||||
{
|
||||
res.Append(arr[arr.Count() - 1]);
|
||||
}
|
||||
return res.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 数组格式化输出字符串
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="arr">待处理数据</param>
|
||||
/// <param name="offset">buffer 参数中开始发送数据的位置,该位置从零开始计数。</param>
|
||||
/// <param name="size">要发送的字节数。</param>
|
||||
/// <returns></returns>
|
||||
public static string ArrayFormatOutput<T>(T[] arr, int offset, int size)
|
||||
{
|
||||
StringBuilder res = new StringBuilder();
|
||||
for (int index = offset; index < size; ++index)
|
||||
{
|
||||
res.Append(string.Format("{0}-", arr[index].ToString()));
|
||||
}
|
||||
if (size - 1 > 0)
|
||||
{
|
||||
res.Append(arr[size]);
|
||||
}
|
||||
return res.ToString();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,346 @@
|
||||
using CsvHelper;
|
||||
using CsvHelper.Configuration;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace JinYuan.Helper
|
||||
{
|
||||
public class CSVHelper<T>
|
||||
{
|
||||
/// <summary>
|
||||
/// 读取CSV文件
|
||||
/// </summary>
|
||||
/// <param name="fileName">csv文件名</param>
|
||||
/// <returns></returns>
|
||||
public static List<T> ReadCSV<T>(string fileName, string strSeparator = "\t")
|
||||
{
|
||||
if (!File.Exists(fileName)) return null;
|
||||
|
||||
using (var reader = new StreamReader(fileName, Encoding.Default))
|
||||
{
|
||||
var cfg = new CsvConfiguration(CultureInfo.InvariantCulture)
|
||||
{
|
||||
Mode = CsvMode.Escape,
|
||||
Escape = '\\',
|
||||
Delimiter = strSeparator, // 设置分隔符号
|
||||
HeaderValidated = null, // 跳过表头验证
|
||||
MissingFieldFound = null // 忽略缺失字段
|
||||
};
|
||||
|
||||
using (var csv = new CsvReader(reader, cfg))
|
||||
{
|
||||
var list = csv.GetRecords<T>().ToList();
|
||||
return list;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 写入CSV文件
|
||||
/// </summary>
|
||||
/// <param name="fileName">csv文件名</param>
|
||||
/// <returns></returns>
|
||||
public static bool WriterCSV(string fileName, List<T> records)
|
||||
{
|
||||
try
|
||||
{
|
||||
FileStream Log = null;
|
||||
if (!Directory.Exists(fileName))
|
||||
Directory.CreateDirectory(fileName);
|
||||
string file = (fileName + DateTime.Now.ToString("yyyyMMdd")) + ".csv";
|
||||
var cfg = new CsvHelper.Configuration.CsvConfiguration(CultureInfo.InvariantCulture);
|
||||
if (!File.Exists(file))
|
||||
{
|
||||
Log = new FileStream(file, FileMode.Create);
|
||||
}
|
||||
else
|
||||
{
|
||||
cfg.HasHeaderRecord = false;//是否将第一行作为标题
|
||||
}
|
||||
if (Log != null)
|
||||
{
|
||||
Log.Close();
|
||||
}
|
||||
//Nuget获取CsvHelper
|
||||
using (var writer = new StreamWriter(file, true, Encoding.Default))
|
||||
{
|
||||
using (var csv = new CsvWriter(writer, cfg))
|
||||
{
|
||||
csv.WriteRecords(records);
|
||||
writer.Flush();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 写入指定列表CSV文件
|
||||
/// </summary>
|
||||
/// <param name="directory"></param>
|
||||
/// <param name="fileName"></param>
|
||||
/// <param name="title"></param>
|
||||
/// <param name="content"></param>
|
||||
/// <returns></returns>
|
||||
public static bool WriterCSV(string directory, string fileName, string title, string content)
|
||||
{
|
||||
FileStream fs = null;
|
||||
StreamWriter sw = null;
|
||||
|
||||
try
|
||||
{
|
||||
if (!Directory.Exists(directory))
|
||||
{
|
||||
Directory.CreateDirectory(directory);
|
||||
}
|
||||
|
||||
string fullFileName = $@"{directory}\{fileName}";
|
||||
if (!File.Exists(fullFileName))
|
||||
{
|
||||
fs = new FileStream(fullFileName, FileMode.Create, FileAccess.Write);
|
||||
sw = new StreamWriter(fs, Encoding.UTF8);
|
||||
sw.WriteLine(title);
|
||||
}
|
||||
else
|
||||
{
|
||||
fs = new FileStream(fullFileName, FileMode.Append, FileAccess.Write);
|
||||
sw = new StreamWriter(fs, Encoding.UTF8);
|
||||
}
|
||||
|
||||
sw.WriteLine(content);
|
||||
|
||||
sw.Close();
|
||||
fs.Close();
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
sw?.Close();
|
||||
fs?.Close();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 获取当天的日期的文件
|
||||
/// </summary>
|
||||
/// <param name="CurrPath"></param>
|
||||
/// <returns></returns>
|
||||
public static List<string> FindTodayFile(string CurrPath)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!Directory.Exists(CurrPath))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
DirectoryInfo di = new DirectoryInfo(CurrPath);
|
||||
FileInfo[] ffis = di.GetFiles();
|
||||
string today = DateTime.Now.Year.ToString().Substring(0, 4) + DateTime.Now.Month.ToString("0#") + DateTime.Now.Day.ToString("0#");
|
||||
List<string> listFilePath = new List<string>();
|
||||
|
||||
for (int i = 0; i < ffis.Length; i++)
|
||||
{
|
||||
FileInfo tmp = ffis[i];
|
||||
if (tmp.Name.Substring(0, 8) == today)
|
||||
{
|
||||
listFilePath.Add(tmp.FullName);
|
||||
}
|
||||
}
|
||||
return (listFilePath.Count > 0) ? listFilePath : null;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
throw ex;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="CurrPath"></param>
|
||||
/// <returns></returns>
|
||||
public static List<string> FindHostFile(string CurrPath, DateTime date)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!Directory.Exists(CurrPath))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
DirectoryInfo di = new DirectoryInfo(CurrPath);
|
||||
FileInfo[] ffis = di.GetFiles();
|
||||
string today = date.ToString().Substring(0, 4) + date.Month.ToString("0#") + date.Day.ToString("0#");
|
||||
//var result1 = Regex.Replace(date, @"[^0-9]+", "");
|
||||
//string today = result1.Substring(0,8);
|
||||
List<string> listFilePath = new List<string>();
|
||||
|
||||
for (int i = 0; i < ffis.Length; i++)
|
||||
{
|
||||
FileInfo tmp = ffis[i];
|
||||
if (tmp.Name.Substring(0, 8) == today)
|
||||
{
|
||||
listFilePath.Add(tmp.FullName);
|
||||
}
|
||||
}
|
||||
return (listFilePath.Count > 0) ? listFilePath : null;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
throw ex;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 导出到CSV文件
|
||||
/// </summary>
|
||||
/// <param name="table">报表DataTable</param>
|
||||
/// <param name="filePath">导出路径</param>
|
||||
/// <param name="msg">输出信息</param>
|
||||
/// <param name="columnName">自定义的列名称,以','英文逗号分隔</param>
|
||||
/// <param name="tableHeader">表名,一般为空</param>
|
||||
/// <returns>是否导出成功</returns>
|
||||
public static bool ExportDataTableToCSV(DataTable table, string filePath, out string msg, string columnName = null, string tableHeader = null)
|
||||
{
|
||||
try
|
||||
{
|
||||
string dirPath = Path.GetDirectoryName(filePath);
|
||||
if (!Directory.Exists(dirPath))
|
||||
{
|
||||
Directory.CreateDirectory(dirPath);//文件的父目录不存在就创建新目录
|
||||
}
|
||||
bool IsAppend = false; //false为创建 true为追加
|
||||
if (File.Exists(filePath))
|
||||
{
|
||||
IsAppend = true;//如果文件存在就不写入表头
|
||||
}
|
||||
using (FileStream _stream = new FileStream(filePath, FileMode.Create | FileMode.Append, FileAccess.Write))
|
||||
{
|
||||
StreamWriter _writer = new StreamWriter(_stream, Encoding.UTF8);
|
||||
if (tableHeader != null)
|
||||
{
|
||||
_writer.WriteLine(tableHeader);
|
||||
}
|
||||
|
||||
if (columnName != null && !IsAppend)
|
||||
{
|
||||
_writer.WriteLine(columnName);
|
||||
}
|
||||
else if (columnName == null && !IsAppend)
|
||||
{
|
||||
List<string> columnNameList = new List<string>();
|
||||
foreach (DataColumn dc in table.Columns)
|
||||
{
|
||||
columnNameList.Add(dc.ColumnName);
|
||||
}
|
||||
_writer.WriteLine(string.Join(",", columnNameList));
|
||||
}
|
||||
|
||||
for (int i = 0; i < table.Rows.Count; i++)
|
||||
{
|
||||
for (int j = 0; j < table.Columns.Count; j++)
|
||||
{
|
||||
_writer.Write(table.Rows[i][j].ToString());
|
||||
_writer.Write(",");
|
||||
}
|
||||
_writer.WriteLine();
|
||||
}
|
||||
_writer.Close();
|
||||
msg = "导出CSV文件成功";
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
msg = string.Format("导出CSV文件失败,原因:{0}", ex.Message);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 导出报表为Csv
|
||||
/// </summary>
|
||||
/// <param name="dt">DataTable</param>
|
||||
/// <param name="strFilePath">物理路径</param>
|
||||
/// <param name="tableheader">表头</param>
|
||||
/// <param name="columname">字段标题,逗号分隔</param>
|
||||
public static bool dt2csv(DataTable dt, string strFilePath, string tableheader, string columname)
|
||||
{
|
||||
try
|
||||
{
|
||||
string strBufferLine = "";
|
||||
StreamWriter strmWriterObj = new StreamWriter(strFilePath, false, System.Text.Encoding.UTF8);
|
||||
strmWriterObj.WriteLine(tableheader);
|
||||
strmWriterObj.WriteLine(columname);
|
||||
for (int i = 0; i < dt.Rows.Count; i++)
|
||||
{
|
||||
strBufferLine = "";
|
||||
for (int j = 0; j < dt.Columns.Count; j++)
|
||||
{
|
||||
if (j > 0)
|
||||
strBufferLine += ",";
|
||||
strBufferLine += dt.Rows[i][j].ToString();
|
||||
}
|
||||
strmWriterObj.WriteLine(strBufferLine);
|
||||
}
|
||||
strmWriterObj.Close();
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将Csv读入DataTable
|
||||
/// </summary>
|
||||
/// <param name="filePath">csv文件路径</param>
|
||||
/// <param name="n">表示第n行是字段title,第n+1行是记录开始</param>
|
||||
public static DataTable csv2dt(string filePath, int n, DataTable dt)
|
||||
{
|
||||
StreamReader reader = new StreamReader(filePath, System.Text.Encoding.UTF8, false);
|
||||
int i = 0, m = 0;
|
||||
reader.Peek();
|
||||
while (reader.Peek() > 0)
|
||||
{
|
||||
m = m + 1;
|
||||
string str = reader.ReadLine();
|
||||
if (m >= n + 1)
|
||||
{
|
||||
string[] split = str.Split(',');
|
||||
|
||||
System.Data.DataRow dr = dt.NewRow();
|
||||
for (i = 0; i < split.Length; i++)
|
||||
{
|
||||
dr[i] = split[i];
|
||||
}
|
||||
dt.Rows.Add(dr);
|
||||
}
|
||||
}
|
||||
return dt;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,213 @@
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Text;
|
||||
using System.Windows.Forms.DataVisualization.Charting;
|
||||
|
||||
namespace JinYuan.Helper
|
||||
{
|
||||
public class ChartHelper
|
||||
{
|
||||
static PrivateFontCollection font = new PrivateFontCollection();
|
||||
/// <summary>
|
||||
/// Name:添加序列
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="chart">图表对象</param>
|
||||
/// <param name="seriesName">序列名称</param>
|
||||
/// <param name="chartType">图表类型</param>
|
||||
/// <param name="seriesColor">颜色</param>
|
||||
/// <param name="markColor">标记点颜色</param>
|
||||
/// <param name="showValue">是否显示数值</param>
|
||||
public static void AddSeries(Chart chart, string seriesName, SeriesChartType chartType, ChartValueType chartValueType, MarkerStyle markerStyle, int markerSize, Color seriesColor, Color markColor, string LabelStyle, bool isShowBFH, bool showValue = false)
|
||||
{
|
||||
// 加载字体文件 Zen圓体-Regular
|
||||
font.AddFontFile(Environment.CurrentDirectory + "\\Assts\\Fonts\\Zen圓体-Regular.ttf");
|
||||
//定义成新的字体对象
|
||||
FontFamily myFontFamily = new FontFamily(font.Families[0].Name, font);
|
||||
Font myFont = new Font(myFontFamily, 9.0f, FontStyle.Bold);
|
||||
|
||||
chart.Series.Add(seriesName);
|
||||
chart.Series[seriesName].ChartType = chartType;
|
||||
chart.Series[seriesName].Color = seriesColor;
|
||||
if (showValue)
|
||||
{
|
||||
chart.Series[seriesName].IsValueShownAsLabel = showValue;
|
||||
chart.Series[seriesName].XValueType = chartValueType;
|
||||
chart.Series[seriesName].Label = LabelStyle;
|
||||
chart.Series[seriesName].Font = myFont;
|
||||
chart.Series[seriesName].MarkerStyle = markerStyle;
|
||||
chart.Series[seriesName].MarkerColor = markColor;
|
||||
chart.Series[seriesName].MarkerStyle = MarkerStyle.Circle; //线条上的数据点标志类型
|
||||
chart.Series[seriesName].MarkerSize = markerSize; //标志大小
|
||||
chart.Series[seriesName].LabelToolTip = "#VALX: #VALY";
|
||||
chart.Series[seriesName].LabelForeColor = markColor;
|
||||
chart.Series[seriesName].LabelAngle = -75;
|
||||
chart.Series[seriesName].BorderWidth = 3;
|
||||
chart.Series[seriesName].LabelBorderWidth = 5;
|
||||
|
||||
if (isShowBFH)
|
||||
{
|
||||
chart.Series[seriesName].YAxisType = AxisType.Secondary;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Name:设置标题
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="chart">图表对象</param>
|
||||
/// <param name="chartName">图表名称</param>
|
||||
public static void SetTitle(Chart chart, string chartName, Font font, Docking docking, Color foreColor)
|
||||
{
|
||||
chart.Titles.Add(chartName);
|
||||
chart.Titles[0].Font = font;
|
||||
chart.Titles[0].Docking = docking;
|
||||
chart.Titles[0].ForeColor = foreColor;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Name:设置样式
|
||||
/// 2019-04-23 14:04
|
||||
/// </summary>
|
||||
/// <param name="chart">图表对象</param>
|
||||
/// <param name="backColor">背景颜色</param>
|
||||
/// <param name="foreColor">字体颜色</param>
|
||||
public static void SetStyle(Chart chart, Color backColor, Color foreColor)
|
||||
{
|
||||
chart.BackColor = backColor;
|
||||
chart.ChartAreas[0].BackColor = backColor;
|
||||
chart.ForeColor = Color.Red;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Name:设置图例
|
||||
/// Author:
|
||||
/// </summary>
|
||||
/// <param name="chart">图表对象</param>
|
||||
/// <param name="docking">停靠位置</param>
|
||||
/// <param name="align">对齐方式</param>
|
||||
/// <param name="backColor">背景颜色</param>
|
||||
/// <param name="foreColor">字体颜色</param>
|
||||
public static void SetLegend(Chart chart, Docking docking, StringAlignment align, Color backColor, Color foreColor)
|
||||
{
|
||||
// 加载字体文件
|
||||
font.AddFontFile(Environment.CurrentDirectory + "\\Assts\\Fonts\\Zen圓体-Regular.ttf");
|
||||
//定义成新的字体对象
|
||||
FontFamily myFontFamily = new FontFamily(font.Families[0].Name, font);
|
||||
Font myFont = new Font(myFontFamily, 9.0f, FontStyle.Regular);
|
||||
|
||||
chart.Legends[0].Docking = docking;
|
||||
chart.Legends[0].Alignment = align;
|
||||
chart.Legends[0].BackColor = backColor;
|
||||
chart.Legends[0].ForeColor = foreColor;
|
||||
chart.Legends[0].Font = myFont;
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Name:设置XY轴
|
||||
/// Author:
|
||||
/// </summary>
|
||||
/// <param name="chart">图表对象</param>
|
||||
/// <param name="xTitle">X轴标题</param>
|
||||
/// <param name="yTitle">Y轴标题</param>
|
||||
/// <param name="align">坐标轴标题对齐方式</param>
|
||||
/// <param name="foreColor">坐标轴字体颜色</param>
|
||||
/// <param name="lineColor">坐标轴颜色</param>
|
||||
/// <param name="arrowStyle">坐标轴箭头样式</param>
|
||||
/// <param name="xInterval">X轴的间距</param>
|
||||
/// <param name="yInterval">Y轴的间距</param>
|
||||
public static void SetXY(Chart chart, string xTitle, string yTitle, int Angle, StringAlignment align, Color foreColor, Color lineColor, AxisArrowStyle arrowStyle, double xInterval, bool isShowBFH, bool isShowTime = false)
|
||||
{
|
||||
// 加载字体文件
|
||||
font.AddFontFile(Environment.CurrentDirectory + "\\Assts\\Fonts\\Zen圓体-Regular.ttf");
|
||||
//定义成新的字体对象
|
||||
FontFamily myFontFamily = new FontFamily(font.Families[0].Name, font);
|
||||
Font myFont = new Font(myFontFamily, 15f, FontStyle.Regular);
|
||||
|
||||
|
||||
chart.ChartAreas[0].AxisX.TitleForeColor = foreColor;
|
||||
chart.ChartAreas[0].AxisX.LabelStyle = new LabelStyle() { ForeColor = foreColor };
|
||||
chart.ChartAreas[0].AxisX.LabelStyle.Angle = Angle;
|
||||
chart.ChartAreas[0].AxisX.LineColor = lineColor;
|
||||
chart.ChartAreas[0].AxisX.LabelStyle.ForeColor = lineColor;
|
||||
chart.ChartAreas[0].AxisX.ArrowStyle = arrowStyle;
|
||||
chart.ChartAreas[0].AxisX.Interval = xInterval;
|
||||
chart.ChartAreas[0].AxisX.Title = xTitle;
|
||||
chart.ChartAreas[0].AxisX.TitleAlignment = align;
|
||||
|
||||
chart.ChartAreas[0].AxisY.TitleForeColor = foreColor;
|
||||
chart.ChartAreas[0].AxisY.LabelStyle = new LabelStyle() { ForeColor = foreColor };
|
||||
chart.ChartAreas[0].AxisY.LineColor = lineColor;
|
||||
chart.ChartAreas[0].AxisY.LabelStyle.ForeColor = lineColor;
|
||||
chart.ChartAreas[0].AxisY.ArrowStyle = arrowStyle;
|
||||
chart.ChartAreas[0].AxisY.Title = yTitle;
|
||||
chart.ChartAreas[0].AxisY.TitleAlignment = align;
|
||||
|
||||
if (isShowBFH)
|
||||
{
|
||||
chart.ChartAreas[0].AxisY2.Minimum = 0;
|
||||
chart.ChartAreas[0].AxisY2.Maximum = 1.2;
|
||||
chart.ChartAreas[0].AxisY2.Interval = 0.2;
|
||||
chart.ChartAreas[0].AxisY2.LabelStyle = new LabelStyle() { ForeColor = foreColor };
|
||||
chart.ChartAreas[0].AxisY2.LineColor = lineColor;
|
||||
chart.ChartAreas[0].AxisY2.LabelStyle.ForeColor = lineColor;
|
||||
chart.ChartAreas[0].AxisY2.LabelStyle.Format = "0.00%";
|
||||
}
|
||||
|
||||
////设置图表显示样式
|
||||
if (isShowTime)
|
||||
{
|
||||
chart.ChartAreas[0].AxisX.LabelStyle.Format = "HH:mm:ss"; //毫秒格式: hh:mm:ss.fff ,后面几个f则保留几位毫秒小数,此时要注意轴的最大值和最小值不要差太大
|
||||
chart.ChartAreas[0].AxisX.LabelStyle.IntervalType = DateTimeIntervalType.Seconds;
|
||||
chart.ChartAreas[0].AxisX.Interval = xInterval; //坐标值间隔1S
|
||||
chart.ChartAreas[0].AxisX.LabelStyle.IsEndLabelVisible = false; //防止X轴坐标跳跃
|
||||
chart.ChartAreas[0].AxisX.MajorGrid.IntervalType = DateTimeIntervalType.Seconds;
|
||||
|
||||
//chart.ChartAreas[0].AxisY.L = 1; //网格间隔
|
||||
|
||||
chart.ChartAreas[0].AxisX.Minimum = DateTime.Now.ToOADate(); //当前时间
|
||||
chart.ChartAreas[0].AxisX.Maximum = DateTime.Now.ToOADate();
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Name:设置网格
|
||||
/// Author:
|
||||
/// </summary>
|
||||
/// <param name="chart">图表对象</param>
|
||||
/// <param name="lineColor">网格线颜色</param>
|
||||
/// <param name="xInterval">X轴网格的间距</param>
|
||||
/// <param name="yInterval">Y轴网格的间距</param>
|
||||
public static void SetMajorGrid(Chart chart, Color lineColor, double xInterval, double yInterval, bool isMajorGridX = false, bool isMajorGridY = false)
|
||||
{
|
||||
chart.ChartAreas[0].AxisX.MajorGrid.Enabled = isMajorGridX;
|
||||
chart.ChartAreas[0].AxisY.MajorGrid.Enabled = isMajorGridY;
|
||||
chart.ChartAreas[0].AxisY2.MajorGrid.Enabled = isMajorGridY;
|
||||
if (isMajorGridX)
|
||||
{
|
||||
chart.ChartAreas[0].AxisX.MajorGrid.LineColor = lineColor;
|
||||
|
||||
chart.ChartAreas[0].AxisX.MajorGrid.Interval = xInterval;
|
||||
|
||||
chart.ChartAreas[0].AxisX.MajorGrid.LineDashStyle = ChartDashStyle.Dash;
|
||||
|
||||
}
|
||||
|
||||
if (isMajorGridY)
|
||||
{
|
||||
chart.ChartAreas[0].AxisY.MajorGrid.LineColor = lineColor;
|
||||
chart.ChartAreas[0].AxisY.MajorGrid.Interval = yInterval;
|
||||
chart.ChartAreas[0].AxisY.MajorGrid.LineDashStyle = ChartDashStyle.Dash;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace JinYuan.Helper
|
||||
{
|
||||
public class ClearMemoryHelper
|
||||
{
|
||||
[DllImport("kernel32.dll")]
|
||||
private static extern bool SetProcessWorkingSetSize(IntPtr proc, int min, int max);
|
||||
/// <summary>
|
||||
/// 释放内存
|
||||
/// </summary>
|
||||
public static void ClearMemory()
|
||||
{
|
||||
Task.Run(async () =>
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
await Task.Delay(4000);
|
||||
GC.Collect();
|
||||
GC.WaitForPendingFinalizers();
|
||||
if (Environment.OSVersion.Platform == PlatformID.Win32NT)
|
||||
{
|
||||
SetProcessWorkingSetSize(System.Diagnostics.Process.GetCurrentProcess().Handle, -1, -1);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using System.Linq;
|
||||
|
||||
namespace JinYuan.Helper
|
||||
{
|
||||
public static class ConvertHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// 字节数组高低位转换
|
||||
/// </summary>
|
||||
/// <param name="Arrbyte"></param>
|
||||
/// <returns></returns>
|
||||
public static byte[] ByteReverse(this byte[] Arrbyte)
|
||||
{
|
||||
byte[] ArrByte = Arrbyte.Select((x, i) => new { x, i }).GroupBy(x => x.i / 2).SelectMany(x => new byte[] { x.Last().x, x.First().x }).ToArray();
|
||||
return ArrByte;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Reflection;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace JinYuan.Helper
|
||||
{
|
||||
public static class DataGridViewHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// 给DataGridView添加行号
|
||||
/// </summary>
|
||||
/// <param name="dgv">dgv控件</param>
|
||||
/// <param name="e">dgv参数</param>
|
||||
public static void DgvRowPostPaint(DataGridView dgv, DataGridViewRowPostPaintEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
//添加行号
|
||||
SolidBrush solidBrush = new SolidBrush(dgv.RowHeadersDefaultCellStyle.ForeColor);
|
||||
string lineNo = (e.RowIndex + 1).ToString();
|
||||
e.Graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;
|
||||
|
||||
StringFormat sf = new StringFormat();
|
||||
sf.LineAlignment = StringAlignment.Center;
|
||||
sf.Alignment = StringAlignment.Center;
|
||||
e.Graphics.DrawString(lineNo, e.InheritedRowStyle.Font, solidBrush, new Rectangle(e.RowBounds.Location.X, e.RowBounds.Location.Y, dgv.RowHeadersWidth, dgv.RowTemplate.Height), sf);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show("添加行号时发生错误,错误信息:" + ex.Message, "操作失败");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 给DataGridView指定列改变前景色
|
||||
/// </summary>
|
||||
/// <param name="dgv"></param>
|
||||
/// <param name="e"></param>
|
||||
public static void DgvRowPrePaint(DataGridView dgv, string Column, object sender, DataGridViewRowPrePaintEventArgs e)
|
||||
{
|
||||
|
||||
if (e.RowIndex >= dgv.Rows.Count - 1)
|
||||
return;
|
||||
DataGridViewRow dr = (sender as DataGridView).Rows[e.RowIndex];
|
||||
|
||||
try
|
||||
{
|
||||
if (dr.Cells[Column].Value != null && dr.Cells[Column].Value.Equals("OK"))
|
||||
{
|
||||
// 设置单元格的背景色
|
||||
//dr.Cells[Column].Style.BackColor = Color.LightGreen;
|
||||
|
||||
// 设置单元格的前景色
|
||||
dr.Cells[Column].Style.ForeColor = Color.LightGreen;
|
||||
}
|
||||
else
|
||||
{
|
||||
//dr.Cells[Column].Style.BackColor = Color.Red;
|
||||
dr.Cells[Column].Style.ForeColor = Color.Red;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show("更改状态时发生错误,错误信息:" + ex.Message, "操作失败");
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 给DataGridView绘制边框
|
||||
/// </summary>
|
||||
/// <param name="dgv">dgv控件</param>
|
||||
/// <param name="e">dgv参数</param>
|
||||
public static void DgvRowPaint(DataGridView dgv, PaintEventArgs e, Color borderColor)
|
||||
{
|
||||
e.Graphics.DrawRectangle(new Pen(borderColor), new Rectangle(0, 0, dgv.Width - 1, dgv.Height - 1));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 奇偶换色
|
||||
/// </summary>
|
||||
public static void DgvStyle(DataGridView dgv, Color defaultBackColor, Color alternatingBackColor, Color gridColor)
|
||||
{
|
||||
//奇数行的背景色
|
||||
dgv.AlternatingRowsDefaultCellStyle.BackColor = alternatingBackColor;
|
||||
dgv.AlternatingRowsDefaultCellStyle.SelectionBackColor = alternatingBackColor;
|
||||
|
||||
//默认的行样式
|
||||
dgv.RowsDefaultCellStyle.BackColor = defaultBackColor;
|
||||
dgv.RowsDefaultCellStyle.SelectionBackColor = defaultBackColor;
|
||||
|
||||
|
||||
dgv.RowHeadersDefaultCellStyle.BackColor = defaultBackColor;
|
||||
dgv.RowHeadersDefaultCellStyle.SelectionBackColor = defaultBackColor;
|
||||
|
||||
//数据网格颜色
|
||||
dgv.GridColor = gridColor;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 双缓冲,解决闪烁问题
|
||||
/// </summary>
|
||||
/// <param name="dgv"></param>
|
||||
/// <param name="flag"></param>
|
||||
public static void DoubleBufferedDataGirdView(this DataGridView dgv, bool flag)
|
||||
{
|
||||
Type dgvType = dgv.GetType();
|
||||
PropertyInfo pi = dgvType.GetProperty("DoubleBuffered", BindingFlags.Instance | BindingFlags.NonPublic);
|
||||
pi.SetValue(dgv, flag, null);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 双缓冲,解决闪烁问题
|
||||
/// </summary>
|
||||
/// <param name="lv"></param>
|
||||
/// <param name="flag"></param>
|
||||
public static void DoubleBufferedListView(this ListView lv, bool flag)
|
||||
{
|
||||
Type lvType = lv.GetType();
|
||||
PropertyInfo pi = lvType.GetProperty("DoubleBuffered", BindingFlags.Instance | BindingFlags.NonPublic);
|
||||
pi.SetValue(lv, flag, null);
|
||||
}
|
||||
|
||||
public static void DoubleBufferedListBox(this ListBox lb, bool flag)
|
||||
{
|
||||
Type lvType = lb.GetType();
|
||||
PropertyInfo pi = lvType.GetProperty("DoubleBuffered", BindingFlags.Instance | BindingFlags.NonPublic);
|
||||
pi.SetValue(lb, flag, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,165 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Reflection;
|
||||
|
||||
namespace JinYuan.Helper
|
||||
{
|
||||
/// <summary>
|
||||
/// DataTable扩展方法类
|
||||
/// </summary>
|
||||
public static class DataTableExtend
|
||||
{
|
||||
/// <summary>
|
||||
/// DataTable转成List
|
||||
/// </summary>
|
||||
public static List<T> ToDataList<T>(this DataTable dt)
|
||||
{
|
||||
var list = new List<T>();
|
||||
var plist = new List<PropertyInfo>(typeof(T).GetProperties());
|
||||
|
||||
if (dt == null || dt.Rows.Count == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
foreach (DataRow item in dt.Rows)
|
||||
{
|
||||
T s = Activator.CreateInstance<T>();
|
||||
for (int i = 0; i < dt.Columns.Count; i++)
|
||||
{
|
||||
PropertyInfo info = plist.Find(p => p.Name == dt.Columns[i].ColumnName);
|
||||
if (info != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!Convert.IsDBNull(item[i]))
|
||||
{
|
||||
object v = null;
|
||||
if (info.PropertyType.ToString().Contains("System.Nullable"))
|
||||
{
|
||||
v = Convert.ChangeType(item[i], Nullable.GetUnderlyingType(info.PropertyType));
|
||||
}
|
||||
else
|
||||
{
|
||||
v = Convert.ChangeType(item[i], info.PropertyType);
|
||||
}
|
||||
info.SetValue(s, v, null);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new Exception("字段[" + info.Name + "]转换出错," + ex.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
list.Add(s);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// DataTable转成实体对象
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="dt"></param>
|
||||
/// <returns></returns>
|
||||
public static T ToDataEntity<T>(this DataTable dt)
|
||||
{
|
||||
T s = Activator.CreateInstance<T>();
|
||||
if (dt == null || dt.Rows.Count == 0)
|
||||
{
|
||||
return default(T);
|
||||
}
|
||||
var plist = new List<PropertyInfo>(typeof(T).GetProperties());
|
||||
for (int i = 0; i < dt.Columns.Count; i++)
|
||||
{
|
||||
PropertyInfo info = plist.Find(p => p.Name == dt.Columns[i].ColumnName);
|
||||
if (info != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!Convert.IsDBNull(dt.Rows[0][i]))
|
||||
{
|
||||
object v = null;
|
||||
if (info.PropertyType.ToString().Contains("System.Nullable"))
|
||||
{
|
||||
v = Convert.ChangeType(dt.Rows[0][i], Nullable.GetUnderlyingType(info.PropertyType));
|
||||
}
|
||||
else
|
||||
{
|
||||
v = Convert.ChangeType(dt.Rows[0][i], info.PropertyType);
|
||||
}
|
||||
info.SetValue(s, v, null);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new Exception("字段[" + info.Name + "]转换出错," + ex.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// List转成DataTable
|
||||
/// </summary>
|
||||
/// <typeparam name="T">实体类型</typeparam>
|
||||
/// <param name="entities">实体集合</param>
|
||||
public static DataTable ToDataTable<T>(List<T> entities)
|
||||
{
|
||||
if (entities == null || entities.Count == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var result = CreateTable<T>();
|
||||
FillData(result, entities);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建表
|
||||
/// </summary>
|
||||
private static DataTable CreateTable<T>()
|
||||
{
|
||||
var result = new DataTable();
|
||||
var type = typeof(T);
|
||||
foreach (var property in type.GetProperties(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance))
|
||||
{
|
||||
var propertyType = property.PropertyType;
|
||||
if ((propertyType.IsGenericType) && (propertyType.GetGenericTypeDefinition() == typeof(Nullable<>)))
|
||||
propertyType = propertyType.GetGenericArguments()[0];
|
||||
result.Columns.Add(property.Name, propertyType);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 填充数据
|
||||
/// </summary>
|
||||
private static void FillData<T>(DataTable dt, IEnumerable<T> entities)
|
||||
{
|
||||
foreach (var entity in entities)
|
||||
{
|
||||
dt.Rows.Add(CreateRow(dt, entity));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建行
|
||||
/// </summary>
|
||||
private static DataRow CreateRow<T>(DataTable dt, T entity)
|
||||
{
|
||||
DataRow row = dt.NewRow();
|
||||
var type = typeof(T);
|
||||
foreach (var property in type.GetProperties(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance))
|
||||
{
|
||||
row[property.Name] = property.GetValue(entity) ?? DBNull.Value;
|
||||
}
|
||||
return row;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,206 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace JinYuan.Helper
|
||||
{
|
||||
public class DeleteLog
|
||||
{
|
||||
public static void Start(string[] strPata, short[] methodSelect)
|
||||
{
|
||||
Init(strPata, methodSelect);
|
||||
}
|
||||
|
||||
private static void Init(string[] strPata, short[] methodSelect)
|
||||
{
|
||||
Task.Run(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
for (int i = 0; i < strPata.Length; i++)
|
||||
{
|
||||
switch (methodSelect[i])
|
||||
{
|
||||
case 0:
|
||||
bool b = DeleteDirectory(strPata[i], 30); //删除该目录下 超过 30天的文件
|
||||
if (b)
|
||||
{
|
||||
LogHelper.Instance.WriteLog($"已清除路径:{strPata[i]},30天内过期日志");
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
bool c = DeleteFile(strPata[i], 30);
|
||||
if (c)
|
||||
{
|
||||
LogHelper.Instance.WriteLog($"已清除路径:{strPata[i]},30天内过期日志");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
//24小时清一次
|
||||
Thread.Sleep(1000 * 60 * 60 * 24);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Thread.Sleep(1000 * 60 * 60 * 28);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void DeleteDirectory(string target_dir)
|
||||
{
|
||||
string[] files = Directory.GetFiles(target_dir);
|
||||
string[] dirs = Directory.GetDirectories(target_dir);
|
||||
foreach (string file in files)
|
||||
{
|
||||
File.SetAttributes(file, FileAttributes.Normal);
|
||||
File.Delete(file);
|
||||
}
|
||||
foreach (string dir in dirs)
|
||||
{
|
||||
DeleteDirectory(dir);
|
||||
}
|
||||
Directory.Delete(target_dir, false);
|
||||
}
|
||||
|
||||
private static bool DeleteDirectory(string fileDirect, int saveDay)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!Directory.Exists(fileDirect))
|
||||
{
|
||||
LogHelper.Instance.WriteLog($"{fileDirect},文件夹不存在");
|
||||
return false;
|
||||
}
|
||||
DateTime nowTime = DateTime.Now;
|
||||
string[] files = Directory.GetFiles(fileDirect, "*.*", SearchOption.AllDirectories); //获取该目录下所有 .txt文件
|
||||
foreach (string file in files)
|
||||
{
|
||||
FileInfo fileInfo = new FileInfo(file);
|
||||
TimeSpan t = DateTime.Now - fileInfo.CreationTime; //当前时间 减去 文件创建时间
|
||||
int day = t.Days;
|
||||
if (day > saveDay) //保存的时间,单位:天
|
||||
{
|
||||
if (IsOccupy(fileInfo.FullName)) //判断文件是否被占用
|
||||
{
|
||||
if (fileDirect.Contains("Mes"))//MesLogs
|
||||
{
|
||||
Directory.Delete(fileInfo.Directory.Parent.FullName, true);
|
||||
return true;
|
||||
}
|
||||
else//其它
|
||||
{
|
||||
Directory.Delete(fileInfo.Directory.FullName, true);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LogHelper.Instance.WriteLog($"{fileInfo.FullName},文件被占用,无法操作!");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception err)
|
||||
{
|
||||
LogHelper.Instance.WriteLog($"APILog日志删除异常,异常原因:{err}");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool DeleteFile(string fileDirect, int saveDay)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!Directory.Exists(fileDirect))
|
||||
{
|
||||
LogHelper.Instance.WriteLog($"{fileDirect},文件夹不存在");
|
||||
return false;
|
||||
}
|
||||
DateTime nowTime = DateTime.Now;
|
||||
string[] files = Directory.GetFiles(fileDirect, "*.*", SearchOption.AllDirectories); //获取该目录下所有 .txt文件
|
||||
foreach (string file in files)
|
||||
{
|
||||
FileInfo fileInfo = new FileInfo(file);
|
||||
|
||||
TimeSpan t = DateTime.Now - fileInfo.LastWriteTime;// fileInfo.CreationTime; //当前时间 减去 文件创建时间
|
||||
int day = t.Days;
|
||||
if (day > saveDay) //保存的时间,单位:天
|
||||
{
|
||||
if (IsOccupy(fileInfo.FullName)) //判断文件是否被占用
|
||||
{
|
||||
System.IO.File.Delete(fileInfo.FullName); //删除文件
|
||||
}
|
||||
else
|
||||
{
|
||||
LogHelper.Instance.WriteLog($"{fileInfo.FullName},文件被占用,无法操作!");
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
catch (Exception err)
|
||||
{
|
||||
LogHelper.Instance.WriteLog($"Logs日志删除异常,异常原因:{err}");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
public static extern IntPtr _lopen(string lpPathName, int iReadWrite);
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
public static extern bool CloseHandle(IntPtr hObject);
|
||||
|
||||
public const int OF_READWRITE = 2;
|
||||
public const int OF_SHARE_DENY_NONE = 0x40;
|
||||
public static readonly IntPtr HFILE_ERROR = new IntPtr(-1);
|
||||
|
||||
/// <summary>
|
||||
/// 判断文件是否被占用
|
||||
/// </summary>
|
||||
/// <param name="file"></param>
|
||||
/// <returns></returns>
|
||||
private static bool IsOccupy(string file)
|
||||
{
|
||||
bool result = true; //默认状态此文件未被占用
|
||||
try
|
||||
{
|
||||
//string vFileName = @"c:\temp\temp.bmp";
|
||||
string vFileName = file;
|
||||
if (!System.IO.File.Exists(vFileName))
|
||||
{
|
||||
//Logger.Info("文件都不存在!");
|
||||
result = false;
|
||||
}
|
||||
IntPtr vHandle = _lopen(vFileName, OF_READWRITE | OF_SHARE_DENY_NONE);
|
||||
if (vHandle == HFILE_ERROR)
|
||||
{
|
||||
|
||||
//Log4Helper.WriteLog("文件被占用!", "错误提示");
|
||||
result = false;
|
||||
}
|
||||
CloseHandle(vHandle);
|
||||
// Log4Helper.WriteLog("没有被占用!", "错误提示");
|
||||
|
||||
|
||||
}
|
||||
catch (Exception err)
|
||||
{
|
||||
result = false;
|
||||
//Log4Helper.WriteLog("判断文件是否被占用", err);
|
||||
|
||||
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,443 @@
|
||||
using JinYuan.Models;
|
||||
using Org.BouncyCastle.Ocsp;
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Net.NetworkInformation;
|
||||
using System.Net.Sockets;
|
||||
|
||||
namespace JinYuan.Helper
|
||||
{
|
||||
public class EnergyMeterHelper
|
||||
{
|
||||
public const int BufferSize = 1024;//1kb
|
||||
private readonly object _lockObj = new object(); // 线程安全锁
|
||||
|
||||
private int _timeout = 2000;
|
||||
private Ping _ping = null;
|
||||
private IPEndPoint _endPoint = null;
|
||||
private Socket _energyMeterSocket = null;
|
||||
private PingReply _pingReply = null;
|
||||
private string _lastError = "";
|
||||
|
||||
public enum ModBusExceptionCode //错误代码
|
||||
{
|
||||
IllegalFunction = 01,
|
||||
IllegalDataAddress,
|
||||
IllegalDataValue,
|
||||
SlaveDeviceFailure,
|
||||
Acknowledge,
|
||||
SlaveDeviceBusy,
|
||||
GatewayPathUnavailable,
|
||||
GatewayTargetDeviceFailed2Respond,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
/// </summary>
|
||||
public EnergyMeterHelper()
|
||||
{
|
||||
// used to ping the PLC
|
||||
//
|
||||
this._ping = new Ping();
|
||||
|
||||
// EndPoint parametres
|
||||
//
|
||||
this._endPoint = new IPEndPoint(0, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// set ip and port
|
||||
/// </summary>
|
||||
public void SetTCPParams(IPAddress ip, int port)
|
||||
{
|
||||
if (ip == null) throw new ArgumentNullException(nameof(ip), "IP地址不能为空");
|
||||
if (port < 1 || port > 65535) throw new ArgumentOutOfRangeException(nameof(port), "端口号必须在1-65535之间");
|
||||
|
||||
// 禁止本地回环地址
|
||||
if (ip == IPAddress.Loopback || ip == IPAddress.IPv6Loopback)
|
||||
{
|
||||
throw new ArgumentException("禁止使用本地回环地址(127.0.0.1),请配置智能电表的真实IP地址", nameof(ip));
|
||||
}
|
||||
|
||||
lock (_lockObj)
|
||||
{
|
||||
_endPoint = new IPEndPoint(ip, port); // 重新创建实例,避免修改原有对象
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// returns the connection status
|
||||
/// </summary>
|
||||
public bool IsConnected
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (_lockObj)
|
||||
{
|
||||
if (_energyMeterSocket == null) return false;
|
||||
|
||||
try
|
||||
{
|
||||
bool part1 = _energyMeterSocket.Poll(100, SelectMode.SelectRead);
|
||||
bool part2 = (_energyMeterSocket.Available == 0);
|
||||
if (part1 && part2)
|
||||
{
|
||||
// 连接已断开,释放Socket
|
||||
Close();
|
||||
return false;
|
||||
}
|
||||
return _energyMeterSocket.Connected;
|
||||
}
|
||||
catch (SocketException)
|
||||
{
|
||||
Close();
|
||||
return false;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// close the socket
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public void Close()
|
||||
{
|
||||
lock (_lockObj)
|
||||
{
|
||||
if (_energyMeterSocket == null) return;
|
||||
try
|
||||
{
|
||||
// 优雅关闭:先关闭发送/接收,再释放
|
||||
if (_energyMeterSocket.Connected)
|
||||
{
|
||||
_energyMeterSocket.Shutdown(SocketShutdown.Both);
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
finally
|
||||
{
|
||||
_energyMeterSocket.Close();
|
||||
_energyMeterSocket.Dispose();
|
||||
_energyMeterSocket = null; // 关键:置空,避免后续操作无效套接字
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool Connect()
|
||||
{
|
||||
lock (_lockObj)
|
||||
{
|
||||
// 已连接则直接返回
|
||||
if (IsConnected) return true;
|
||||
|
||||
// 先释放旧连接
|
||||
Close();
|
||||
|
||||
try
|
||||
{
|
||||
return TCPConnect();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
TxtHelper.WriteTxt($@"D:\APILog\Logs\智能电表信息\{DateTime.Now:yyyy-MM-dd}.txt",
|
||||
$"{DateTime.Now:yyyy-MM-dd HH:mm:ss} 智能电表:连接异常 {ex.Message}");
|
||||
Close();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool TCPConnect()
|
||||
{
|
||||
// 若目标是本地回环地址,直接提示错误(关键!)
|
||||
if (_endPoint.Address == IPAddress.Loopback || _endPoint.Address == IPAddress.IPv6Loopback)
|
||||
{
|
||||
TxtHelper.WriteTxt($@"D:\APILog\Logs\智能电表信息\{DateTime.Now:yyyy-MM-dd}.txt",
|
||||
$"{DateTime.Now:yyyy-MM-dd HH:mm:ss} 智能电表:连接地址为本地回环(127.0.0.1),请配置电表真实IP!");
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (_endPoint.Address == IPAddress.None)
|
||||
{
|
||||
throw new InvalidOperationException("未设置有效的IP和端口");
|
||||
}
|
||||
|
||||
// 重新创建Socket实例
|
||||
_energyMeterSocket = new Socket(_endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp)
|
||||
{
|
||||
SendTimeout = _timeout,
|
||||
ReceiveTimeout = _timeout
|
||||
};
|
||||
|
||||
// 异步连接(避免阻塞,可选)
|
||||
IAsyncResult result = _energyMeterSocket.BeginConnect(_endPoint, null, null);
|
||||
bool connectSuccess = result.AsyncWaitHandle.WaitOne(_timeout);
|
||||
|
||||
if (connectSuccess && _energyMeterSocket.Connected)
|
||||
{
|
||||
TxtHelper.WriteTxt($@"D:\APILog\Logs\智能电表信息\{DateTime.Now:yyyy-MM-dd}.txt",
|
||||
$"{DateTime.Now:yyyy-MM-dd HH:mm:ss} 智能电表:连接成功");
|
||||
return true;
|
||||
}
|
||||
|
||||
// 连接超时,释放当前Socket
|
||||
_energyMeterSocket.Close();
|
||||
_energyMeterSocket.Dispose();
|
||||
_energyMeterSocket = null;
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (SocketException ex)
|
||||
{
|
||||
TxtHelper.WriteTxt($@"D:\APILog\Logs\智能电表信息\{DateTime.Now:yyyy-MM-dd}.txt",
|
||||
$"{DateTime.Now:yyyy-MM-dd HH:mm:ss} 智能电表:网口连接失败 {ex.SocketErrorCode} - {ex.Message}");
|
||||
Close();
|
||||
return false;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
TxtHelper.WriteTxt($@"D:\APILog\Logs\智能电表信息\{DateTime.Now:yyyy-MM-dd}.txt",
|
||||
$"{DateTime.Now:yyyy-MM-dd HH:mm:ss} 智能电表:连接失败 {ex.Message}");
|
||||
Close();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public bool Ping()
|
||||
{
|
||||
if (_endPoint.Address == IPAddress.None) return false;
|
||||
|
||||
try
|
||||
{
|
||||
var reply = _ping.Send(_endPoint.Address, _timeout);
|
||||
return reply.Status == IPStatus.Success;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public bool SendAndGetRes(byte[] bytes, ref List<ElectricEnergy> listM)//, ref JetReturnResult jet
|
||||
{
|
||||
// 参数校验
|
||||
if (bytes == null || bytes.Length == 0)
|
||||
{
|
||||
_lastError = "发送指令为空";
|
||||
return false;
|
||||
}
|
||||
if (listM == null) listM = new List<ElectricEnergy>();
|
||||
|
||||
var arrayPool = ArrayPool<byte>.Shared;
|
||||
byte[] buffer = arrayPool.Rent(BufferSize);//new byte[1024];
|
||||
byte[] recvData = new byte[88 * 4 + 9];//0x58
|
||||
int size = recvData.Length; //0x58
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
if (!Ping())
|
||||
{
|
||||
_lastError = "Ping设备失败,网络不可达";
|
||||
TxtHelper.WriteTxt($@"D:\APILog\Logs\智能电表信息\{DateTime.Now:yyyy-MM-dd}.txt",
|
||||
$"{DateTime.Now:yyyy-MM-dd HH:mm:ss} 智能电表:{_lastError}");
|
||||
return false;
|
||||
}
|
||||
if (!IsConnected && !Connect())
|
||||
{
|
||||
_lastError = "重连设备失败";
|
||||
return false;
|
||||
}
|
||||
|
||||
// 发送
|
||||
Send(bytes);
|
||||
// 接收
|
||||
int recvLen = Receive(ref recvData, size);
|
||||
if (recvLen <= 0)
|
||||
{
|
||||
_lastError = "未接收到设备响应";
|
||||
TxtHelper.WriteTxt($@"D:\APILog\Logs\智能电表信息\{DateTime.Now:yyyy-MM-dd}.txt",
|
||||
$"{DateTime.Now:yyyy-MM-dd HH:mm:ss} 智能电表:{_lastError}");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 解析
|
||||
if ((recvData[0] == Convert.ToByte(01 >> 8) && recvData[1] == Convert.ToByte(01)))//pTask.id
|
||||
{
|
||||
if (recvData[7] == 0x04)//读线圈寄存器功能码
|
||||
{
|
||||
//数据赋值
|
||||
Array.Copy(recvData, 0, buffer, 0, recvData.Length);
|
||||
TxtHelper.WriteTxt($@"D:\APILog\Logs\智能电表信息\{DateTime.Now.ToString("yyyy-MM-dd")}.txt", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + $"电能表读取原始数据:{string.Join(" ", recvData)}");
|
||||
|
||||
decimal PhaseVoltageA = Convert.ToDecimal(HextoFloat(buffer[9], buffer[10], buffer[11], buffer[12]));
|
||||
decimal PhaseVoltageB = Convert.ToDecimal(HextoFloat(buffer[13], buffer[14], buffer[15], buffer[16]));
|
||||
decimal PhaseVoltageC = Convert.ToDecimal(HextoFloat(buffer[17], buffer[18], buffer[19], buffer[20]));
|
||||
decimal PhaseCurrentA = Convert.ToDecimal(HextoFloat(buffer[21], buffer[22], buffer[23], buffer[24]));
|
||||
decimal PhaseCurrentB = Convert.ToDecimal(HextoFloat(buffer[25], buffer[26], buffer[27], buffer[28]));
|
||||
decimal PhaseCurrentC = Convert.ToDecimal(HextoFloat(buffer[29], buffer[30], buffer[31], buffer[32]));
|
||||
decimal PhasePowerA = Convert.ToDecimal(HextoFloat(buffer[33], buffer[34], buffer[35], buffer[36]));
|
||||
decimal PhasePowerB = Convert.ToDecimal(HextoFloat(buffer[37], buffer[38], buffer[39], buffer[40]));
|
||||
decimal PhasePowerC = Convert.ToDecimal(HextoFloat(buffer[41], buffer[42], buffer[43], buffer[44]));
|
||||
decimal ActivePower = Convert.ToDecimal(HextoFloat(buffer[121], buffer[122], buffer[123], buffer[124]));
|
||||
decimal PowerFactor = Convert.ToDecimal(HextoFloat(buffer[133], buffer[134], buffer[135], buffer[136]));
|
||||
decimal pt = 1;
|
||||
decimal ct = 150 / 5;
|
||||
decimal AccumulatedElectricity = Convert.ToDecimal(HextoFloat(buffer[181], buffer[182], buffer[183], buffer[184]));
|
||||
|
||||
ElectricEnergy m = new ElectricEnergy();
|
||||
m.PhaseVoltageA = PhaseVoltageA;
|
||||
m.PhaseVoltageB = PhaseVoltageB;
|
||||
m.PhaseVoltageC = PhaseVoltageC;
|
||||
m.PhaseCurrentA = PhaseCurrentA * ct;
|
||||
m.PhaseCurrentB = PhaseCurrentB * ct;
|
||||
m.PhaseCurrentC = PhaseCurrentC * ct;
|
||||
m.PhasePowerA = PhaseVoltageA * PhaseCurrentA * ct;
|
||||
m.PhasePowerB = PhaseVoltageB * PhaseCurrentB * ct;
|
||||
m.PhasePowerC = PhaseVoltageC * PhaseCurrentC * ct;
|
||||
m.ActivePower = ActivePower * ct;
|
||||
m.PowerFactor = PowerFactor * ct;
|
||||
m.pt = pt;//Convert.ToDecimal(HextoFloat(buffer[0], buffer[0], buffer[0], buffer[0]));
|
||||
m.ct = ct;//Convert.ToDecimal(HextoFloat(buffer[0], buffer[0], buffer[0], buffer[0]));
|
||||
m.AccumulatedElectricity = AccumulatedElectricity;
|
||||
listM.Add(m);
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (recvData[8])
|
||||
{
|
||||
case (byte)ModBusExceptionCode.IllegalDataAddress:
|
||||
_lastError = string.Format("SendAndGetRes():ReadInputRegister [IllegalDataAddress]");
|
||||
break;
|
||||
case (byte)ModBusExceptionCode.IllegalDataValue:
|
||||
_lastError = string.Format("SendAndGetRes():ReadInputRegister [IllegalDataValue]");
|
||||
break;
|
||||
case (byte)ModBusExceptionCode.IllegalFunction:
|
||||
_lastError = string.Format("SendAndGetRes():ReadInputRegister [IllegalFunction]");
|
||||
break;
|
||||
default:
|
||||
_lastError = string.Format("SendAndGetRes():ReadInputRegister [FunctionException]");
|
||||
break;
|
||||
}
|
||||
TxtHelper.WriteTxt($@"D:\APILog\Logs\智能电表信息\{DateTime.Now.ToString("yyyy-MM-dd")}.txt", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + $"电能表读取数据异常,原因:{_lastError}");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
TxtHelper.WriteTxt($@"D:\APILog\Logs\智能电表信息\{DateTime.Now.ToString("yyyy-MM-dd")}.txt", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + $"电能表读取原始数据:{string.Join(" ", recvData)}");
|
||||
TxtHelper.WriteTxt($@"D:\APILog\Logs\智能电表信息\{DateTime.Now.ToString("yyyy-MM-dd")}.txt", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + $"电能表读取数据异常,原因:{ex}");
|
||||
Close();
|
||||
return false;
|
||||
}
|
||||
finally
|
||||
{
|
||||
arrayPool.Return(buffer);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// send a command to energy meter device
|
||||
/// </summary>
|
||||
/// <param name="command"></param>
|
||||
/// <returns></returns>
|
||||
private int Send(Byte[] command)
|
||||
{
|
||||
lock (_lockObj)
|
||||
{
|
||||
// 核心校验:Socket不为null且连接有效
|
||||
if (_energyMeterSocket == null || !IsConnected)
|
||||
{
|
||||
throw new SocketException((int)SocketError.NotConnected);
|
||||
}
|
||||
|
||||
int bytesSent = _energyMeterSocket.Send(command, 0, command.Length, SocketFlags.None);
|
||||
return bytesSent;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// receives a response from the plc
|
||||
/// </summary>
|
||||
/// <param name="response"></param>
|
||||
/// <param name="respLen"></param>
|
||||
/// <returns></returns>
|
||||
private int Receive(ref Byte[] response, int expectLen)
|
||||
{
|
||||
lock (_lockObj)
|
||||
{
|
||||
if (_energyMeterSocket == null || !IsConnected)
|
||||
{
|
||||
throw new SocketException((int)SocketError.NotConnected);
|
||||
}
|
||||
|
||||
int totalRecv = 0;
|
||||
while (totalRecv < expectLen)
|
||||
{
|
||||
// 分段接收,避免单次接收不足
|
||||
int recvLen = _energyMeterSocket.Receive(response, totalRecv, expectLen - totalRecv, SocketFlags.None);
|
||||
if (recvLen == 0)
|
||||
{
|
||||
throw new SocketException((int)SocketError.ConnectionReset);
|
||||
}
|
||||
totalRecv += recvLen;
|
||||
}
|
||||
|
||||
return totalRecv;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// HexToFloat
|
||||
/// </summary>
|
||||
/// <param name="H1">高字高字节</param>
|
||||
/// <param name="H2">高字低字节</param>
|
||||
/// <param name="D1">低字高字节</param>
|
||||
/// <param name="D2">低字低字节</param>
|
||||
/// <returns>float</returns>
|
||||
public static float HextoFloat(byte H1, byte H2, byte D1, byte D2)
|
||||
{
|
||||
try
|
||||
{
|
||||
//byte-->short
|
||||
int s1, s2;
|
||||
s1 = Convert.ToInt32(H1 * 256) + Convert.ToInt32(H2);
|
||||
s2 = Convert.ToInt32(D1 * 256) + Convert.ToInt32(D2);
|
||||
|
||||
//将输入数值short转化为无符号unsigned short
|
||||
int us1 = s1, us2 = s2;
|
||||
if (s1 < 0) us1 += 65536;
|
||||
if (s2 < 0) us2 += 65536;
|
||||
//sign: 符号位, exponent: 阶码, mantissa:尾数
|
||||
int sign, exponent;
|
||||
float mantissa;
|
||||
//计算符号位
|
||||
sign = us1 / 32768;
|
||||
//去掉符号位
|
||||
int emCode = us1 % 32768;
|
||||
//计算阶码
|
||||
exponent = emCode / 128;
|
||||
//计算尾数
|
||||
mantissa = (float)(emCode % 128 * 65536 + us2) / 8388608;
|
||||
//代入公式 fValue = (-1) ^ S x 2 ^ (E - 127) x (1 + M)
|
||||
return (float)Math.Pow(-1, sign) * (float)Math.Pow(2, exponent - 127) * (1 + mantissa);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,267 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Runtime.Serialization.Formatters.Binary;
|
||||
|
||||
namespace JinYuan.Helper
|
||||
{
|
||||
public class FileHelper
|
||||
{
|
||||
#region 1.文本文件读写
|
||||
|
||||
|
||||
public static void WriteToTxt(string path, string content, bool isAppend = false)
|
||||
{
|
||||
//【1】创建文件流
|
||||
FileStream fileStream = new FileStream(path, isAppend ? FileMode.Append : FileMode.Create);
|
||||
|
||||
//【2】创建写入器
|
||||
StreamWriter streamWriter = new StreamWriter(fileStream);
|
||||
|
||||
//【3】以流的形式写入数据
|
||||
streamWriter.Write(content);
|
||||
|
||||
//【4】关闭写入器
|
||||
streamWriter.Close();
|
||||
|
||||
//【5】关闭文件流
|
||||
fileStream.Close();
|
||||
}
|
||||
|
||||
|
||||
public static string ReadFromTxt(string path)
|
||||
{
|
||||
//判断文件是否存在
|
||||
if (!File.Exists(path))
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
//【1】创建文件流
|
||||
FileStream fileStream = new FileStream(path, FileMode.Open);
|
||||
|
||||
//【2】创建读取器
|
||||
StreamReader streamReader = new StreamReader(fileStream);
|
||||
|
||||
//【3】以流的方式读取
|
||||
string content = streamReader.ReadToEnd();
|
||||
|
||||
//【4】关闭读取器
|
||||
streamReader.Close();
|
||||
|
||||
//【5】关闭文件流
|
||||
fileStream.Close();
|
||||
|
||||
return content;
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 2.对象序列化文件
|
||||
|
||||
/// <summary>
|
||||
/// 序列化一个对象到一个文件中
|
||||
/// </summary>
|
||||
/// <param name="obj"></param>
|
||||
/// <param name="path"></param>
|
||||
public static void SerializeObject(object obj, string path)
|
||||
{
|
||||
FileStream fileStream = null;
|
||||
|
||||
try
|
||||
{
|
||||
fileStream = new FileStream(path, FileMode.Create);
|
||||
|
||||
BinaryFormatter binaryFormatter = new BinaryFormatter();
|
||||
|
||||
binaryFormatter.Serialize(fileStream, obj);
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new Exception("序列化对象出错:" + ex.Message);
|
||||
}
|
||||
finally
|
||||
{
|
||||
fileStream.Close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static T DeSerializeObject<T>(string path)
|
||||
{
|
||||
FileStream fileStream = null;
|
||||
|
||||
try
|
||||
{
|
||||
fileStream = new FileStream(path, FileMode.Open);
|
||||
|
||||
BinaryFormatter binaryFormatter = new BinaryFormatter();
|
||||
|
||||
return (T)binaryFormatter.Deserialize(fileStream);
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new Exception("反序列化对象出错:" + ex.Message);
|
||||
}
|
||||
finally
|
||||
{
|
||||
fileStream.Close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region 3.对象序列化字符串
|
||||
|
||||
/// <summary>
|
||||
/// 将对象序列化成字符串
|
||||
/// </summary>
|
||||
/// <param name="obj"></param>
|
||||
/// <returns></returns>
|
||||
public static string SerializeObjToString(object obj)
|
||||
{
|
||||
IFormatter formatter = new BinaryFormatter();
|
||||
|
||||
string result = string.Empty;
|
||||
|
||||
using (MemoryStream stream = new MemoryStream())
|
||||
{
|
||||
formatter.Serialize(stream, obj);
|
||||
|
||||
byte[] bytes = stream.ToArray();
|
||||
|
||||
result = Convert.ToBase64String(bytes);
|
||||
|
||||
stream.Flush();
|
||||
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将字符串反序列化成对象
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="str"></param>
|
||||
/// <returns></returns>
|
||||
public static T DeSerializeObjFromString<T>(string str) where T : class
|
||||
{
|
||||
IFormatter formatter = new BinaryFormatter();
|
||||
|
||||
byte[] bytes = Convert.FromBase64String(str);
|
||||
|
||||
T obj = null;
|
||||
|
||||
using (MemoryStream stream = new MemoryStream(bytes, 0, bytes.Length))
|
||||
{
|
||||
obj = (T)formatter.Deserialize(stream);
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 4.文件的基本操作
|
||||
|
||||
/// <summary>
|
||||
/// 文件复制
|
||||
/// </summary>
|
||||
/// <param name="srcFileName"></param>
|
||||
/// <param name="desFileName"></param>
|
||||
public static void CopyFile(string srcFileName, string desFileName)
|
||||
{
|
||||
if (File.Exists(desFileName))
|
||||
{
|
||||
File.Delete(desFileName);
|
||||
}
|
||||
|
||||
File.Copy(srcFileName, desFileName);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 文件移动
|
||||
/// </summary>
|
||||
/// <param name="srcFileName"></param>
|
||||
/// <param name="desFileName"></param>
|
||||
public static void MoveFile(string srcFileName, string desFileName)
|
||||
{
|
||||
if (File.Exists(srcFileName))
|
||||
{
|
||||
if (File.Exists(desFileName))
|
||||
{
|
||||
File.Delete(desFileName);
|
||||
}
|
||||
|
||||
File.Move(srcFileName, desFileName);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 文件删除
|
||||
/// </summary>
|
||||
/// <param name="fileName"></param>
|
||||
public static void DeleteFile(string fileName)
|
||||
{
|
||||
if (File.Exists(fileName))
|
||||
{
|
||||
File.Delete(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region 5.文件夹的相关操作
|
||||
|
||||
/// <summary>
|
||||
/// 获取指定目录下的所有文件
|
||||
/// </summary>
|
||||
/// <param name="path"></param>
|
||||
/// <returns></returns>
|
||||
public static string[] GetFiles(string path)
|
||||
{
|
||||
return Directory.GetFiles(path);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取指定目录下的所有子目录
|
||||
/// </summary>
|
||||
/// <param name="path"></param>
|
||||
/// <returns></returns>
|
||||
public static string[] GetDirectories(string path)
|
||||
{
|
||||
return Directory.GetDirectories(path);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建文件夹
|
||||
/// </summary>
|
||||
/// <param name="path"></param>
|
||||
public static void CreateDirectory(string path)
|
||||
{
|
||||
Directory.CreateDirectory(path);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 删除指定目录下的所有子目录和文件
|
||||
/// </summary>
|
||||
/// <param name="path"></param>
|
||||
public static void DeleteFiles(string path)
|
||||
{
|
||||
DirectoryInfo directory = new DirectoryInfo(path);
|
||||
|
||||
directory.Delete(true);
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,253 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
namespace JinYuan.Helper
|
||||
{
|
||||
public class IniConfigHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// 文件路径
|
||||
/// </summary>
|
||||
public static string iniFilePath = string.Empty;
|
||||
|
||||
|
||||
#region API函数声明
|
||||
|
||||
[DllImport("kernel32")]
|
||||
private static extern long WritePrivateProfileString(string section, string key, string val, string filePath);
|
||||
|
||||
//需要调用GetPrivateProfileString的重载
|
||||
[DllImport("kernel32", EntryPoint = "GetPrivateProfileString")]
|
||||
private static extern long GetPrivateProfileString(string section, string key,
|
||||
string def, StringBuilder retVal, int size, string filePath);
|
||||
|
||||
[DllImport("kernel32", EntryPoint = "GetPrivateProfileString")]
|
||||
private static extern uint GetPrivateProfileStringA(string section, string key,
|
||||
string def, Byte[] retVal, int size, string filePath);
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="StartupPath"></param>
|
||||
/// <param name="AppName"></param>
|
||||
public static void CreateIniFile(string StartupPath, string AppName)
|
||||
{
|
||||
iniFilePath = StartupPath + AppName;
|
||||
if (!Directory.Exists(StartupPath))
|
||||
{
|
||||
Directory.CreateDirectory(StartupPath);
|
||||
}
|
||||
if (!File.Exists(iniFilePath))
|
||||
{
|
||||
File.Create(iniFilePath).Close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#region 读取INI文件
|
||||
/// <summary>
|
||||
/// 根据节点及Key的值返回数据
|
||||
/// </summary>
|
||||
/// <param name="Section">节点</param>
|
||||
/// <param name="Key">键</param>
|
||||
/// <param name="defaultValue">默认值</param>
|
||||
/// <param name="path">路径</param>
|
||||
/// <returns>返回值</returns>
|
||||
public static string ReadIniData(string Section, string Key, string NoText, string iniFilePath)
|
||||
{
|
||||
if (File.Exists(iniFilePath))
|
||||
{
|
||||
StringBuilder stringBuilder = new StringBuilder(10240);
|
||||
|
||||
GetPrivateProfileString(Section, Key, NoText, stringBuilder, 10240, iniFilePath);
|
||||
|
||||
return stringBuilder.ToString();
|
||||
}
|
||||
else
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 根据节点及Key的值返回数据
|
||||
/// </summary>
|
||||
/// <param name="Section">节点</param>
|
||||
/// <param name="Key">键</param>
|
||||
/// <param name="NoText">默认值</param>
|
||||
/// <returns>返回值</returns>
|
||||
public static string ReadIniData(string Section, string Key, string NoText)
|
||||
{
|
||||
return ReadIniData(Section, Key, NoText, iniFilePath);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 写入Ini文件
|
||||
|
||||
/// <summary>
|
||||
/// 根据节点及Key的值写入数据
|
||||
/// </summary>
|
||||
/// <param name="Section">节点</param>
|
||||
/// <param name="Key">键</param>
|
||||
/// <param name="Value">值</param>
|
||||
/// <param name="path">路径</param>
|
||||
/// <returns>操作结果</returns>
|
||||
public static bool WriteIniData(string Section, string Key, string Value, string path)
|
||||
{
|
||||
long result = WritePrivateProfileString(Section, Key, Value, path);
|
||||
|
||||
if (result == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据节点及Key的值写入数据
|
||||
/// </summary>
|
||||
/// <param name="Section">节点</param>
|
||||
/// <param name="Key">键</param>
|
||||
/// <param name="Value">值</param>
|
||||
/// <returns>操作结果</returns>
|
||||
public static bool WriteIniData(string Section, string Key, string Value)
|
||||
{
|
||||
return WriteIniData(Section, Key, Value, iniFilePath);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 读取所有的Sections
|
||||
|
||||
/// <summary>
|
||||
/// 读取所有的Section
|
||||
/// </summary>
|
||||
/// <param name="path">路径</param>
|
||||
/// <returns>Section集合</returns>
|
||||
public static List<string> ReadSections(string path)
|
||||
{
|
||||
byte[] buffer = new byte[65536];
|
||||
|
||||
uint length = GetPrivateProfileStringA(null, null, null, buffer, buffer.Length, path);
|
||||
|
||||
int startIndex = 0;
|
||||
|
||||
List<string> sections = new List<string>();
|
||||
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
if (buffer[i] == 0)
|
||||
{
|
||||
sections.Add(Encoding.Default.GetString(buffer, startIndex, i - startIndex));
|
||||
startIndex = i + 1;
|
||||
}
|
||||
}
|
||||
|
||||
return sections;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 读取所有的Section
|
||||
/// </summary>
|
||||
/// <param name="path">路径</param>
|
||||
/// <returns>Section集合</returns>
|
||||
public static List<string> ReadSections()
|
||||
{
|
||||
byte[] buffer = new byte[65536];
|
||||
|
||||
uint length = GetPrivateProfileStringA(null, null, null, buffer, buffer.Length, iniFilePath);
|
||||
|
||||
int startIndex = 0;
|
||||
|
||||
List<string> sections = new List<string>();
|
||||
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
if (buffer[i] == 0)
|
||||
{
|
||||
sections.Add(Encoding.Default.GetString(buffer, startIndex, i - startIndex));
|
||||
startIndex = i + 1;
|
||||
}
|
||||
}
|
||||
|
||||
return sections;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region 根据某个Section读取所有的Keys
|
||||
|
||||
/// <summary>
|
||||
/// 根据某个Section读取所有的Keys
|
||||
/// </summary>
|
||||
/// <param name="section">某个section</param>
|
||||
/// <param name="path">路径</param>
|
||||
/// <returns>key的集合</returns>
|
||||
public static List<string> ReadKeys(string section, string path)
|
||||
{
|
||||
byte[] buffer = new byte[65536];
|
||||
|
||||
uint length = GetPrivateProfileStringA(section, null, null, buffer, buffer.Length, path);
|
||||
|
||||
int startIndex = 0;
|
||||
|
||||
List<string> keys = new List<string>();
|
||||
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
if (buffer[i] == 0)
|
||||
{
|
||||
keys.Add(Encoding.Default.GetString(buffer, startIndex, i - startIndex));
|
||||
startIndex = i + 1;
|
||||
}
|
||||
}
|
||||
|
||||
return keys;
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据某个Section读取所有的Keys
|
||||
/// </summary>
|
||||
/// <param name="section">某个section</param>
|
||||
/// <param name="path">路径</param>
|
||||
/// <returns>key的集合</returns>
|
||||
public static List<string> ReadKeys(string section)
|
||||
{
|
||||
byte[] buffer = new byte[65536];
|
||||
|
||||
uint length = GetPrivateProfileStringA(section, null, null, buffer, buffer.Length, iniFilePath);
|
||||
|
||||
int startIndex = 0;
|
||||
|
||||
List<string> keys = new List<string>();
|
||||
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
if (buffer[i] == 0)
|
||||
{
|
||||
keys.Add(Encoding.Default.GetString(buffer, startIndex, i - startIndex));
|
||||
startIndex = i + 1;
|
||||
}
|
||||
}
|
||||
|
||||
return keys;
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace JinYuan.Helper
|
||||
{
|
||||
public class IniFileHelper
|
||||
{
|
||||
private static string iniFilePath = "Configure.ini";
|
||||
|
||||
[DllImport("kernel32")]
|
||||
private static extern long WritePrivateProfileString(string section, string key, string val, string filePath);
|
||||
|
||||
[DllImport("kernel32")]
|
||||
private static extern long GetPrivateProfileString(string section, string key, string def, StringBuilder retVal, int size, string filePath);
|
||||
|
||||
public static string ReadIniData(string Section, string Key)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (File.Exists(iniFilePath))
|
||||
{
|
||||
StringBuilder temp = new StringBuilder(1024);
|
||||
GetPrivateProfileString(Section, Key, "", temp, 1024, iniFilePath);
|
||||
return temp.ToString();
|
||||
}
|
||||
MessageBox.Show("节点:" + Section + ",键名:" + Key + ":读取配置文件错误!");
|
||||
return null;
|
||||
}
|
||||
catch
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public static bool WriteIniData(string Section, string Key, string Value)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (File.Exists(iniFilePath))
|
||||
{
|
||||
if (WritePrivateProfileString(Section, Key, Value, iniFilePath) == 0L)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
File.Create(iniFilePath).Close();
|
||||
if (WritePrivateProfileString(Section, Key, Value, iniFilePath) == 0L)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public static void CreateIniFile(string StartupPath, string AppName)
|
||||
{
|
||||
iniFilePath = StartupPath + AppName;
|
||||
if (!Directory.Exists(StartupPath))
|
||||
{
|
||||
Directory.CreateDirectory(StartupPath);
|
||||
}
|
||||
if (!File.Exists(iniFilePath))
|
||||
{
|
||||
File.Create(iniFilePath).Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,176 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="..\packages\SixLabors.ImageSharp.3.1.6\build\SixLabors.ImageSharp.props" Condition="Exists('..\packages\SixLabors.ImageSharp.3.1.6\build\SixLabors.ImageSharp.props')" />
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{258D0AB7-2B4F-4D8F-A3CD-7A8CB4A85360}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>JinYuan.Helper</RootNamespace>
|
||||
<AssemblyName>JinYuan.Helper</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<Deterministic>true</Deterministic>
|
||||
<TargetFrameworkProfile />
|
||||
<NuGetPackageImportStamp>
|
||||
</NuGetPackageImportStamp>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="BouncyCastle.Cryptography, Version=2.0.0.0, Culture=neutral, PublicKeyToken=072edcf4a5328938, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\BouncyCastle.Cryptography.2.2.1\lib\net461\BouncyCastle.Cryptography.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="CsvHelper, Version=33.0.0.0, Culture=neutral, PublicKeyToken=8c4959082be5c823, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\CsvHelper.33.0.1\lib\net48\CsvHelper.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Enums.NET, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7ea1c1650d506225, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Enums.NET.4.0.1\lib\net45\Enums.NET.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="ICSharpCode.SharpZipLib, Version=1.3.3.11, Culture=neutral, PublicKeyToken=1b03e6acf1164f73, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\SharpZipLib.1.3.3\lib\net45\ICSharpCode.SharpZipLib.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="MathNet.Numerics, Version=4.15.0.0, Culture=neutral, PublicKeyToken=cd8b63ad3d691a37, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\MathNet.Numerics.Signed.4.15.0\lib\net461\MathNet.Numerics.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Bcl.AsyncInterfaces, Version=9.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Microsoft.Bcl.AsyncInterfaces.9.0.0\lib\net462\Microsoft.Bcl.AsyncInterfaces.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Bcl.HashCode, Version=1.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Microsoft.Bcl.HashCode.1.1.1\lib\net461\Microsoft.Bcl.HashCode.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.IO.RecyclableMemoryStream, Version=2.3.2.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Microsoft.IO.RecyclableMemoryStream.2.3.2\lib\net462\Microsoft.IO.RecyclableMemoryStream.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Newtonsoft.Json.13.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="NLog, Version=6.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\NLog.6.0.2\lib\net46\NLog.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="PLCCommunication, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>bin\Debug\PLCCommunication.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="SixLabors.Fonts, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d998eea7b14cab13, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\SixLabors.Fonts.1.0.0\lib\netstandard2.0\SixLabors.Fonts.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Buffers, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.ComponentModel.DataAnnotations" />
|
||||
<Reference Include="System.Configuration" />
|
||||
<Reference Include="System.Configuration.ConfigurationManager, Version=8.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.Configuration.ConfigurationManager.8.0.0\lib\net462\System.Configuration.ConfigurationManager.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Data.OracleClient" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Memory, Version=4.0.1.2, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.Memory.4.5.5\lib\net461\System.Memory.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Net" />
|
||||
<Reference Include="System.Numerics" />
|
||||
<Reference Include="System.Numerics.Vectors, Version=4.1.4.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Runtime.CompilerServices.Unsafe, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.Runtime.CompilerServices.Unsafe.6.0.0\lib\net461\System.Runtime.CompilerServices.Unsafe.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Runtime.Serialization" />
|
||||
<Reference Include="System.Security" />
|
||||
<Reference Include="System.Security.AccessControl, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.Security.AccessControl.6.0.0\lib\net461\System.Security.AccessControl.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Security.Cryptography.Xml, Version=6.0.0.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.Security.Cryptography.Xml.6.0.1\lib\net461\System.Security.Cryptography.Xml.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Security.Permissions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.Security.Permissions.6.0.0\lib\net461\System.Security.Permissions.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Security.Principal.Windows, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.Security.Principal.Windows.5.0.0\lib\net461\System.Security.Principal.Windows.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.ServiceProcess" />
|
||||
<Reference Include="System.Text.Encoding.CodePages, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.Text.Encoding.CodePages.6.0.0\lib\net461\System.Text.Encoding.CodePages.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Threading.Tasks.Extensions, Version=4.2.0.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.Threading.Tasks.Extensions.4.5.4\lib\net461\System.Threading.Tasks.Extensions.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Transactions" />
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
<Reference Include="System.Windows.Forms.DataVisualization" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="WindowsBase" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="ArrayHelper.cs" />
|
||||
<Compile Include="ChartHelper.cs" />
|
||||
<Compile Include="ClearMemoryHelper.cs" />
|
||||
<Compile Include="DataTableExtend.cs" />
|
||||
<Compile Include="ConvertHelper.cs" />
|
||||
<Compile Include="CSVHelper.cs" />
|
||||
<Compile Include="DataGridViewHelper.cs" />
|
||||
<Compile Include="DeleteLog.cs" />
|
||||
<Compile Include="EnergyMeterHelper.cs" />
|
||||
<Compile Include="FileHelper.cs" />
|
||||
<Compile Include="IniConfigHelper.cs" />
|
||||
<Compile Include="IniFileHelper.cs" />
|
||||
<Compile Include="JsonHelper.cs" />
|
||||
<Compile Include="Logger.cs" />
|
||||
<Compile Include="MockDataGenerator.cs" />
|
||||
<Compile Include="PLCAlarmParseHelper.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="LogHelper.cs" />
|
||||
<Compile Include="ScanerHook.cs" />
|
||||
<Compile Include="SendDateMQTT.cs" />
|
||||
<Compile Include="StreamIOHelper.cs" />
|
||||
<Compile Include="StringSecurityHelper.cs" />
|
||||
<Compile Include="TimedOperation.cs" />
|
||||
<Compile Include="TimerReset.cs" />
|
||||
<Compile Include="TxtHelper.cs" />
|
||||
<Compile Include="TypeParse.cs" />
|
||||
<Compile Include="XmlHelper.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="app.config" />
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\JinYuan.Models\JinYuan.Models.csproj">
|
||||
<Project>{4C0BCB84-5CD7-4846-8363-C4C10D46E391}</Project>
|
||||
<Name>JinYuan.Models</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>这台计算机上缺少此项目引用的 NuGet 程序包。使用“NuGet 程序包还原”可下载这些程序包。有关更多信息,请参见 http://go.microsoft.com/fwlink/?LinkID=322105。缺少的文件是 {0}。</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('..\packages\SixLabors.ImageSharp.3.1.6\build\SixLabors.ImageSharp.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\SixLabors.ImageSharp.3.1.6\build\SixLabors.ImageSharp.props'))" />
|
||||
</Target>
|
||||
</Project>
|
||||
@@ -0,0 +1,90 @@
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.Serialization.Json;
|
||||
using System.Text;
|
||||
|
||||
namespace JinYuan.Helper
|
||||
{
|
||||
public class JsonHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// 使用Newtonsoft.json.dll对象序列化成Json字符串
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="t"></param>
|
||||
/// <returns></returns>
|
||||
public static string EntityToJson<T>(T t)
|
||||
{
|
||||
try
|
||||
{
|
||||
return JsonConvert.SerializeObject(t);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 使用Newtonsoft.json.dll 将Json字符串反序列化成对象
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="json"></param>
|
||||
/// <returns></returns>
|
||||
public static T JsonToEntity<T>(string json)
|
||||
{
|
||||
try
|
||||
{
|
||||
return (T)JsonConvert.DeserializeObject(json, typeof(T));
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return default(T);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 实体类转换成JSON字符串
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="obj"></param>
|
||||
/// <returns></returns>
|
||||
public static string EntityToJson2<T>(T obj)
|
||||
{
|
||||
//序列化
|
||||
DataContractJsonSerializer js = new DataContractJsonSerializer(typeof(T));
|
||||
MemoryStream msObj = new MemoryStream();
|
||||
//将序列化之后的Json格式数据写入流中
|
||||
js.WriteObject(msObj, obj);
|
||||
msObj.Position = 0;
|
||||
//从0这个位置开始读取流中的数据
|
||||
StreamReader sr = new StreamReader(msObj, Encoding.Default);
|
||||
string json = sr.ReadToEnd();
|
||||
sr.Close();
|
||||
msObj.Close();
|
||||
return json;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// JSON字符串转换成实体类
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="json"></param>
|
||||
/// <returns></returns>
|
||||
public static T JsonToEntity2<T>(string json) where T : class
|
||||
{
|
||||
//反序列化
|
||||
using (var ms = new MemoryStream(Encoding.Default.GetBytes(json)))
|
||||
{
|
||||
DataContractJsonSerializer deseralizer = new DataContractJsonSerializer(typeof(T));
|
||||
T model = (T)deseralizer.ReadObject(ms);// //反序列化ReadObject
|
||||
return model;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,310 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
|
||||
namespace JinYuan.Helper
|
||||
{
|
||||
/// <summary>
|
||||
/// 日志操作类
|
||||
/// </summary>
|
||||
public class LogHelper
|
||||
{
|
||||
private static object singleLock = new object();
|
||||
|
||||
/// <summary>
|
||||
/// log日志文件路径
|
||||
/// </summary>
|
||||
public static string logFilePath = string.Empty;
|
||||
|
||||
|
||||
public static LogHelper _instance = null;
|
||||
public static LogHelper Instance
|
||||
{
|
||||
|
||||
get
|
||||
{
|
||||
if (_instance == null)
|
||||
{
|
||||
lock (singleLock)
|
||||
{
|
||||
if (_instance == null)
|
||||
{
|
||||
_instance = new LogHelper();
|
||||
}
|
||||
}
|
||||
}
|
||||
return _instance;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 初始化
|
||||
/// </summary>
|
||||
/// <param name="configPath"></param>
|
||||
public void InitLog(string configPath)
|
||||
{
|
||||
logFilePath = configPath;
|
||||
if (!Directory.Exists(logFilePath))
|
||||
{
|
||||
Directory.CreateDirectory(logFilePath);
|
||||
}
|
||||
//if (!File.Exists(logFilePath))
|
||||
//{
|
||||
// File.Create(logFilePath).Close();
|
||||
//}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 写日志文件数据库日志文件
|
||||
/// </summary>
|
||||
/// <param name="message">消息</param>
|
||||
public void WriteError(string message)
|
||||
{
|
||||
|
||||
AddLog(message, "Error");
|
||||
}
|
||||
|
||||
public void WriteEX(Exception ex)
|
||||
{
|
||||
AddLog(ex.Message + "\r\n" + ex.InnerException + "\r\n" + ex.StackTrace + "\r\n" + ex.Source, "SysErrorLog");
|
||||
}
|
||||
|
||||
public void WriteEX(string ErrorName, Exception ex)
|
||||
{
|
||||
AddLog(ErrorName + "\r\n" + ex.Message + "\r\n" + ex.InnerException + "\r\n" + ex.StackTrace + "\r\n" + ex.Source, "SysErrorLog");
|
||||
}
|
||||
/// <summary>
|
||||
/// 写日志文件数据库日志文件
|
||||
/// </summary>
|
||||
/// <param name="ex">消息</param>
|
||||
/// <param name="direName">日志存储目录名称</param>
|
||||
public void WriteError(Exception ex, string direName)
|
||||
{
|
||||
AddLog(ex.Message + "\r\n" + ex.InnerException + "\r\n" + ex.StackTrace + "\r\n" + ex.Source, direName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// /
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
/// <param name="direName"></param>
|
||||
public void WriteError(string message, string direName)
|
||||
{
|
||||
AddLog(message, direName);
|
||||
}
|
||||
/// <summary>
|
||||
/// 写日志文件数据库日志文件
|
||||
/// </summary>
|
||||
/// <param name="message">消息</param>
|
||||
public void WriteLog(string message)
|
||||
{
|
||||
|
||||
AddLog(message, "Info");
|
||||
}
|
||||
/// <summary>
|
||||
/// 写日志文件数据库日志文件
|
||||
/// </summary>
|
||||
/// <param name="message">消息</param>
|
||||
/// <param name="direName">日志存储目录名称</param>
|
||||
public void WriteLog(string message, string direName)
|
||||
{
|
||||
|
||||
AddLog(message, direName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 写日志文件数据库日志文件
|
||||
/// </summary>
|
||||
/// <param name="message">消息</param>
|
||||
/// <param name="direName">日志存储目录名称</param>
|
||||
private void AddLog(string message, string direName)
|
||||
{
|
||||
string fileLog = logFilePath;
|
||||
if (fileLog == "")
|
||||
{
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
var applicationName = direName;
|
||||
//从宿主配置文件中获取日志文件全路径
|
||||
//所有的接口日志文件放在一个目录下面,跟web站点的目录分开
|
||||
//日志文件一天放一个,按日期分开
|
||||
|
||||
if (string.IsNullOrEmpty(applicationName))
|
||||
{
|
||||
applicationName = "Log";
|
||||
}
|
||||
string logFullPath = fileLog + applicationName;
|
||||
|
||||
if (!Directory.Exists(logFullPath))
|
||||
{
|
||||
Directory.CreateDirectory(logFullPath);
|
||||
}
|
||||
//只保留30天的日志
|
||||
var deletePath = $@"{logFullPath}\{DateTime.Now.AddDays(-30):yyyyMMddHH}.txt";
|
||||
|
||||
if (File.Exists(deletePath))
|
||||
{
|
||||
File.Delete(deletePath);
|
||||
}
|
||||
|
||||
logFullPath = $@"{logFullPath}\{DateTime.Now:yyyyMMddHH}.txt";
|
||||
if (!File.Exists(logFullPath))
|
||||
{
|
||||
using (var fs = new FileStream(logFullPath, FileMode.Create, FileAccess.Write))
|
||||
{
|
||||
StreamWriter sw = new StreamWriter(fs);
|
||||
sw.Close();
|
||||
fs.Close();
|
||||
}
|
||||
}
|
||||
|
||||
using (StreamWriter writer = new StreamWriter(logFullPath, true))
|
||||
{
|
||||
writer.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
|
||||
writer.WriteLine(message);
|
||||
writer.WriteLine(Environment.NewLine);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 轴位置日志类
|
||||
/// </summary>
|
||||
public class PrintMotorLog
|
||||
{
|
||||
private static readonly Thread WriteThread;
|
||||
private static readonly Queue<string> MsgQueue;//先进先出集合
|
||||
public static readonly object FileLock;
|
||||
private static readonly string FilePath = "D:\\LOCAL\\轴位置修改记录(查看文件就复制到副本到桌面!!!)\\";
|
||||
static PrintMotorLog()
|
||||
{
|
||||
FileLock = new object();//文件锁
|
||||
|
||||
WriteThread = new Thread(WriteMsg);
|
||||
MsgQueue = new Queue<string>();
|
||||
WriteThread.Start();
|
||||
}
|
||||
|
||||
public static void LogInfo(string BegionTime, string MotorDescribe, string IndxDescribe, string FrontIndx, string NewIndx)
|
||||
{
|
||||
Monitor.Enter(MsgQueue);
|
||||
string strData = BegionTime + ","
|
||||
+ MotorDescribe + ","
|
||||
+ IndxDescribe + ","
|
||||
+ FrontIndx + ","
|
||||
+ NewIndx + ",";
|
||||
MsgQueue.Enqueue(strData);
|
||||
Monitor.Exit(MsgQueue);
|
||||
}
|
||||
private static void WriteMsg()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
Thread.Sleep(10);
|
||||
if (MsgQueue.Count > 0)
|
||||
{
|
||||
Monitor.Enter(MsgQueue);
|
||||
string msg = MsgQueue.Dequeue();
|
||||
Monitor.Exit(MsgQueue);
|
||||
Monitor.Enter(FileLock);
|
||||
if (!Directory.Exists(FilePath))
|
||||
{
|
||||
Directory.CreateDirectory(FilePath);
|
||||
}
|
||||
string strFilename = FilePath + "轴位置修改_" + System.DateTime.Now.ToString("yyyyMMdd") + ".csv";
|
||||
//用默认编码和缓冲区大小,为指定的文件初始化 StreamWriter 类的一个新实例。 如果该文件存在,则可以将其覆盖或向其追加。 如果该文件不存在,则此构造函数将创建一个新文件。
|
||||
try
|
||||
{
|
||||
if (!File.Exists(strFilename))
|
||||
{
|
||||
//文件标头 19
|
||||
string strProInfoFileHead = @"日期时间,轴描述,位置描述,位置修改前,当前位置";
|
||||
StreamWriter sw = new StreamWriter(strFilename, true, UnicodeEncoding.GetEncoding("GB2312"));
|
||||
sw.WriteLine(strProInfoFileHead);
|
||||
sw.Flush();
|
||||
sw.Close();
|
||||
sw.Dispose();
|
||||
}
|
||||
StreamWriter se = new StreamWriter(strFilename, true, UnicodeEncoding.GetEncoding("GB2312"));
|
||||
se.WriteLine(msg);
|
||||
se.Flush();
|
||||
se.Close();
|
||||
se.Dispose();
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
Monitor.Exit(FileLock);
|
||||
if (GetFileSize(strFilename) > 1024 * 5)
|
||||
{
|
||||
CopyToBak(strFilename);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
private static long GetFileSize(string fileName)
|
||||
{
|
||||
long strRe = 0;
|
||||
if (File.Exists(fileName))
|
||||
{
|
||||
Monitor.Enter(FileLock);
|
||||
try
|
||||
{
|
||||
var myFs = new FileStream(fileName, FileMode.Open);
|
||||
strRe = myFs.Length / 1024;
|
||||
myFs.Close();
|
||||
myFs.Dispose();
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
Monitor.Exit(FileLock);
|
||||
}
|
||||
return strRe;
|
||||
}
|
||||
|
||||
private static void CopyToBak(string sFileName)
|
||||
{
|
||||
int fileCount = 0;
|
||||
string sBakName = "";
|
||||
Monitor.Enter(FileLock);
|
||||
try
|
||||
{
|
||||
do
|
||||
{
|
||||
fileCount++;
|
||||
sBakName = sFileName + "." + fileCount + ".BAK";
|
||||
}
|
||||
while (File.Exists(sBakName));
|
||||
File.Copy(sFileName, sBakName);
|
||||
File.Delete(sFileName);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
Monitor.Exit(FileLock);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
using NLog;
|
||||
using System;
|
||||
|
||||
|
||||
|
||||
public class Logger
|
||||
{
|
||||
|
||||
private static readonly NLog.Logger loginfo = LogManager.GetLogger("loginfo");
|
||||
private static readonly NLog.Logger logerror = LogManager.GetLogger("logerror");
|
||||
private static readonly NLog.Logger logmqtt = LogManager.GetLogger("logmqtt");
|
||||
private static readonly NLog.Logger logWHX = LogManager.GetLogger("logWHX");
|
||||
|
||||
private static readonly NLog.Logger logsInfo = LogManager.GetLogger("logsInfo");
|
||||
private static readonly NLog.Logger logsMEStIME = LogManager.GetLogger("logsMEStIME");
|
||||
private static readonly NLog.Logger logsSql = LogManager.GetLogger("logsSql");
|
||||
private static readonly NLog.Logger logsSysErrorLog = LogManager.GetLogger("logsSysErrorLog");
|
||||
private static readonly NLog.Logger logsSysErrorLogcn = LogManager.GetLogger("logsSysErrorLogcn");
|
||||
public static void WriteInfo(string info)
|
||||
{
|
||||
Console.WriteLine(info);
|
||||
if (loginfo.IsInfoEnabled)
|
||||
{
|
||||
loginfo.Info(info);
|
||||
}
|
||||
}
|
||||
|
||||
public static void WriteMqtt(string info)
|
||||
{
|
||||
Console.WriteLine(info);
|
||||
if (logmqtt.IsInfoEnabled)
|
||||
{
|
||||
logmqtt.Info(info);
|
||||
}
|
||||
}
|
||||
|
||||
public static void WriteError(string error)
|
||||
{
|
||||
Console.WriteLine(error);
|
||||
if (logerror.IsErrorEnabled)
|
||||
{
|
||||
logerror.Error(error);
|
||||
}
|
||||
}
|
||||
|
||||
public static void WriteError(string info, Exception ex)
|
||||
{
|
||||
Console.WriteLine(info);
|
||||
if (logerror.IsErrorEnabled)
|
||||
{
|
||||
logerror.Error(info, ex);
|
||||
}
|
||||
}
|
||||
public static void WriteWHX(string info)
|
||||
{
|
||||
Console.WriteLine(info);
|
||||
if (logWHX.IsErrorEnabled)
|
||||
{
|
||||
logWHX.Error(info);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
using JinYuan.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace JinYuan.Helper
|
||||
{
|
||||
public static class MockDataGenerator
|
||||
{
|
||||
public static readonly Random _random = new Random();
|
||||
|
||||
// 修改为与实际数据结构匹配的类
|
||||
public class ProdData
|
||||
{
|
||||
public string DisplayTime { get; set; }
|
||||
public int ProdIn { get; set; }
|
||||
public int ProdOut { get; set; }
|
||||
public double OKRatio { get; set; }
|
||||
}
|
||||
|
||||
public class AlarmData
|
||||
{
|
||||
public string DataType { get; set; }
|
||||
public int DataCount { get; set; }
|
||||
}
|
||||
|
||||
public class NGData
|
||||
{
|
||||
public string DataType { get; set; }
|
||||
public int DataCount { get; set; }
|
||||
}
|
||||
|
||||
public static List<Chart12HourData> Generate12HourData()
|
||||
{
|
||||
var result = new List<Chart12HourData>();
|
||||
var random = new Random();
|
||||
|
||||
// 方法1:使用数组预定义顺序
|
||||
var timeSlots = new[]
|
||||
{
|
||||
"08:30", "09:30", "10:30", "11:30", "12:30", "13:30", "14:30", "15:30", "16:30", "17:30",
|
||||
"18:30", "19:30", "20:30", "21:30", "22:30", "23:30", "00:30", "01:30", "02:30", "03:30",
|
||||
"04:30", "05:30", "06:30", "07:30"
|
||||
};
|
||||
|
||||
foreach (var timeSlot in timeSlots)
|
||||
{
|
||||
var prodIn = random.Next(800, 2000);
|
||||
var prodOut = random.Next(700, prodIn);
|
||||
var okRatio = Math.Round((double)prodOut / prodIn * 100, 2);
|
||||
|
||||
result.Add(new Chart12HourData
|
||||
{
|
||||
DisplayTime = timeSlot,
|
||||
ProdIn = prodIn,
|
||||
ProdOut = prodOut,
|
||||
OKRatio = okRatio.ToString("F2") + "%"
|
||||
});
|
||||
}
|
||||
|
||||
return result; // 不需要额外排序,因为已经按照需要的顺序生成
|
||||
}
|
||||
|
||||
public static List<ChartDataType> GenerateAlarmTop10Data()
|
||||
{
|
||||
var alarmTypes = new[]
|
||||
{
|
||||
"设备故障", "原料异常", "温度超限", "压力异常",
|
||||
"速度偏差", "位置错误", "通信中断", "电源故障",
|
||||
"气压不足", "传感器异常"
|
||||
};
|
||||
|
||||
return alarmTypes
|
||||
.Select(type => new ChartDataType
|
||||
{
|
||||
DataType = type,
|
||||
DataCount = _random.Next(5, 50)
|
||||
})
|
||||
.OrderByDescending(x => x.DataCount)
|
||||
.ToList();
|
||||
}
|
||||
|
||||
public static List<ChartDataType> GenerateNGData()
|
||||
{
|
||||
var ngTypes = new[]
|
||||
{
|
||||
"尺寸超差", "表面划伤", "变形", "异物",
|
||||
"色差", "气泡", "裂纹", "焊接不良"
|
||||
};
|
||||
|
||||
return ngTypes
|
||||
.Select(type => new ChartDataType
|
||||
{
|
||||
DataType = type,
|
||||
DataCount = _random.Next(10, 100)
|
||||
})
|
||||
.OrderByDescending(x => x.DataCount)
|
||||
.ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,232 @@
|
||||
using JinYuan.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace JinYuan.Helper
|
||||
{
|
||||
public static class PLCAlarmParseHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// 三菱将报警地址值转成报警List
|
||||
/// </summary>
|
||||
/// <param name="plcAddrSuffix">PLC地址值,如100</param>
|
||||
/// <param name="byteData">PLC读取出来的值</param>
|
||||
/// <param name="plcAddrPrefix">PLC地址类型,默认值R</param>
|
||||
/// <returns></returns>
|
||||
public static List<AlarmStatus> MelsecByte2Status(int plcAddrSuffix, byte[] byteData, char plcAddrPrefix = 'R')
|
||||
{
|
||||
var listAlarmStatus = new List<AlarmStatus>();
|
||||
// byte[]转为二进制字符串表示
|
||||
string strResult = "";
|
||||
for (int i = 0; i < byteData.Length; i++)
|
||||
{
|
||||
string strTemp = System.Convert.ToString(byteData[i], 2);
|
||||
strTemp = strTemp.PadLeft(8, '0').StrReverse();
|
||||
strResult += strTemp;
|
||||
}
|
||||
|
||||
for (int i = 0; i < strResult.Length; i++)
|
||||
{
|
||||
var plcByte = i % 16;
|
||||
//如果是16的倍数地址+1
|
||||
if (plcByte % 16 == 0 && i != 0)
|
||||
{
|
||||
plcAddrSuffix++;
|
||||
}
|
||||
//将地址和状态添加到结果集
|
||||
listAlarmStatus.Add(new AlarmStatus()
|
||||
{
|
||||
PLCAdress = $"{plcAddrPrefix}{plcAddrSuffix}.{plcByte.ToString("X")}",
|
||||
Status = strResult[i] == '1'
|
||||
});
|
||||
//if (strResult[i] == '1')
|
||||
// Console.WriteLine($"{plcAddrPrefix}{plcAddrSuffix}.{plcByte.ToString("X")}:{strResult[i]}");
|
||||
}
|
||||
|
||||
return listAlarmStatus;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 欧姆龙NX系列Ethernet/IP通讯时将报警地址值转成报警List {直接读取标签地址/无需高低位互换}
|
||||
/// </summary>
|
||||
/// <param name="plcAddrSuffix">PLC地址值,如100</param>
|
||||
/// <param name="byteData">PLC读取出来的值</param>
|
||||
/// <param name="plcAddrPrefix">PLC地址类型,默认值R</param>
|
||||
/// <returns></returns>
|
||||
public static List<AlarmStatus> OmronEIPByte2Status(int plcAddrSuffix, List<byte> byteData, char plcAddrPrefix = 'W')
|
||||
{
|
||||
var listAlarmStatus = new List<AlarmStatus>();
|
||||
// byte[]转为二进制字符串表示
|
||||
string strResult = "";
|
||||
for (int i = 0; i < byteData.Count; i++)
|
||||
{
|
||||
string strTemp = System.Convert.ToString(byteData[i], 2);
|
||||
strTemp = strTemp.PadLeft(8, '0').StrReverse();
|
||||
strResult += strTemp;
|
||||
}
|
||||
|
||||
for (int i = 0; i < strResult.Length; i++)
|
||||
{
|
||||
var plcByte = i % 16;
|
||||
//如果是16的倍数地址+1
|
||||
if (plcByte % 16 == 0 && i != 0)
|
||||
{
|
||||
plcAddrSuffix++;
|
||||
}
|
||||
//将地址和状态添加到结果集
|
||||
listAlarmStatus.Add(new AlarmStatus()
|
||||
{
|
||||
PLCAdress = $"{plcAddrPrefix}6100[{plcAddrSuffix}].B[{plcByte.ToString()}]",
|
||||
Status = strResult[i] == '1'
|
||||
});
|
||||
}
|
||||
|
||||
return listAlarmStatus;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 欧姆龙FINS通讯读取EM数据寄存器是时将报警地址值转成报警List
|
||||
/// </summary>
|
||||
/// <param name="plcAddrSuffix">PLC地址值,如100</param>
|
||||
/// <param name="byteData">PLC读取出来的值</param>
|
||||
/// <param name="plcAddrPrefix">PLC地址类型,默认值W</param>
|
||||
/// <returns></returns>
|
||||
public static List<AlarmStatus> OmronFinsByte2Status(int plcAddrSuffix, byte[] byteData, char plcAddrPrefix = 'D')
|
||||
{
|
||||
var listAlarmStatus = new List<AlarmStatus>();
|
||||
#region 取消
|
||||
// byte[]转为二进制字符串表示
|
||||
//byte[] revBytes = SWAPbyte(byteData); //字节高低位互换
|
||||
//string strResult = "";
|
||||
//for (int i = 0; i < revBytes.Length; i++)
|
||||
//{
|
||||
// string strTemp = System.Convert.ToString(revBytes[i], 2);
|
||||
// strTemp = strTemp.PadLeft(8, '0').StrReverse();
|
||||
// strResult += strTemp;
|
||||
//}
|
||||
|
||||
//for (int i = 0; i < strResult.Length; i++)
|
||||
//{
|
||||
// var plcByte = i % 500;
|
||||
// //如果是16的倍数地址+1
|
||||
// if (plcByte % 500 == 0 && i != 0)
|
||||
// {
|
||||
// plcAddrSuffix++;
|
||||
// }
|
||||
// //将地址和状态添加到结果集
|
||||
// listAlarmStatus.Add(new AlarmStatus()
|
||||
// {
|
||||
// PLCAdress = $"{plcAddrPrefix}{plcAddrSuffix}.{plcByte.ToString()}",
|
||||
// Status = strResult[i] == '1'
|
||||
// });
|
||||
// //if (strResult[i] == '1')
|
||||
// // Console.WriteLine($"{plcAddrPrefix}{plcAddrSuffix}.{plcByte.ToString("X")}:{strResult[i]}");
|
||||
//}
|
||||
|
||||
//将地址和状态添加到结果集
|
||||
//for (int i = 0; i < byteData.Length / 2; i++)
|
||||
//{
|
||||
// listAlarmStatus.Add(new AlarmStatus()
|
||||
// {
|
||||
// PLCAdress = $"{plcAddrPrefix}{plcAddrSuffix + i}",
|
||||
// Status = ShortLib.GetShortFromByteArray(byteData, (i * 2)) == 1,
|
||||
// //Status = strResult[i] == '1'
|
||||
// });
|
||||
//}
|
||||
#endregion
|
||||
int wordCount = byteData.Length / 2; // 16位整数数量
|
||||
|
||||
for (int i = 0; i < wordCount; i++)
|
||||
{
|
||||
int currentAddr = plcAddrSuffix + i;
|
||||
int byteOffset = i * 2;
|
||||
|
||||
// 组合字节为16位整数(大端序)
|
||||
ushort wordValue = (ushort)(
|
||||
(byteData[byteOffset] << 8) |
|
||||
byteData[byteOffset + 1]
|
||||
);
|
||||
|
||||
// 跳过0值(无报警)
|
||||
if (wordValue == 0) continue;
|
||||
|
||||
// 计算位地址(从1开始)
|
||||
int bitPosition = wordValue;
|
||||
string address = $"{plcAddrPrefix}{currentAddr}.{bitPosition}";
|
||||
|
||||
// 添加到报警列表(只添加实际触发的位)
|
||||
listAlarmStatus.Add(new AlarmStatus()
|
||||
{
|
||||
PLCAdress = address,
|
||||
Status = true // 只有触发的位才会被添加
|
||||
});
|
||||
}
|
||||
return listAlarmStatus;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 欧姆龙FINS通讯读取W数据寄存器是时将报警地址值转成报警List
|
||||
/// </summary>
|
||||
/// <param name="plcAddrSuffix">PLC地址值,如100</param>
|
||||
/// <param name="byteData">PLC读取出来的值</param>
|
||||
/// <param name="plcAddrPrefix">PLC地址类型,默认值W</param>
|
||||
/// <returns></returns>
|
||||
//public static List<AlarmStatus> OmronByte2Status(int plcAddrSuffix, byte[] byteData, char plcAddrPrefix = 'W')
|
||||
//{
|
||||
// var listAlarmStatus = new List<AlarmStatus>();
|
||||
|
||||
// var addrCount = byteData.Length / 2;
|
||||
// // byte[]每个地址保存的都是bool值,只取双数index位
|
||||
// for (int i = 0; i < addrCount; i++)
|
||||
// {
|
||||
// //将地址和状态添加到结果集
|
||||
// listAlarmStatus.Add(new AlarmStatus()
|
||||
// {
|
||||
// PLCAdress = $"{plcAddrPrefix}{plcAddrSuffix + i}",
|
||||
// Status = byteData[i * 2 + 1] == 1
|
||||
|
||||
// });
|
||||
// //if (byteData[i * 2 + 1] == 1)
|
||||
// // Console.WriteLine($"原始数据 PLC地址:{plcAddrPrefix}{plcAddrSuffix + i} 报警值:{byteData[i * 2 + 1]}");
|
||||
// }
|
||||
|
||||
// return listAlarmStatus;
|
||||
//}
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 字符串反转
|
||||
/// </summary>
|
||||
/// <param name="str">需要反转字符串.Reverse()</param>
|
||||
/// <returns></returns>
|
||||
public static string StrReverse(this string str)
|
||||
{
|
||||
return new string(str.Reverse().ToArray());
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
///byte字节高低位互换
|
||||
/// </summary>
|
||||
/// <param name="data"></param>
|
||||
/// <returns></returns>
|
||||
public static byte[] SWAPbyte(byte[] data)
|
||||
{
|
||||
byte[] data2 = new byte[data.Length];
|
||||
for (int i = 0; i < data.Length; i += 2)
|
||||
{
|
||||
data2[i] = data[i + 1];
|
||||
data2[i + 1] = data[i];
|
||||
}
|
||||
return data2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// 有关程序集的一般信息由以下
|
||||
// 控制。更改这些特性值可修改
|
||||
// 与程序集关联的信息。
|
||||
[assembly: AssemblyTitle("JinYuan.Helper")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("JinYuan.Helper")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2023")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// 将 ComVisible 设置为 false 会使此程序集中的类型
|
||||
//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
|
||||
//请将此类型的 ComVisible 特性设置为 true。
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
|
||||
[assembly: Guid("258d0ab7-2b4f-4d8f-a3cd-7a8cb4a85360")]
|
||||
|
||||
// 程序集的版本信息由下列四个值组成:
|
||||
//
|
||||
// 主版本
|
||||
// 次版本
|
||||
// 生成号
|
||||
// 修订号
|
||||
//
|
||||
//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值
|
||||
//通过使用 "*",如下所示:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
@@ -0,0 +1,291 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
namespace JinYuan.Helper
|
||||
{
|
||||
public class ScanerHook
|
||||
{
|
||||
public delegate void ScanerDelegate(ScanerCodes codes);
|
||||
public event ScanerDelegate ScanerEvent;
|
||||
|
||||
//private const int WM_KEYDOWN = 0x100;//KEYDOWN
|
||||
//private const int WM_KEYUP = 0x101;//KEYUP
|
||||
//private const int WM_SYSKEYDOWN = 0x104;//SYSKEYDOWN
|
||||
//private const int WM_SYSKEYUP = 0x105;//SYSKEYUP
|
||||
//private static int HookProc(int nCode, Int32 wParam, IntPtr lParam);
|
||||
private int hKeyboardHook = 0;//声明键盘钩子处理的初始值
|
||||
private ScanerCodes codes = new ScanerCodes();//13为键盘钩子
|
||||
//定义成静态,这样不会抛出回收异常
|
||||
private static HookProc hookproc;
|
||||
delegate int HookProc(int nCode, Int32 wParam, IntPtr lParam);
|
||||
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
|
||||
//设置钩子
|
||||
private static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId);
|
||||
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
|
||||
//卸载钩子
|
||||
private static extern bool UnhookWindowsHookEx(int idHook);
|
||||
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
|
||||
//继续下个钩子
|
||||
private static extern int CallNextHookEx(int idHook, int nCode, Int32 wParam, IntPtr lParam);
|
||||
|
||||
[DllImport("user32", EntryPoint = "GetKeyNameText")]
|
||||
private static extern int GetKeyNameText(int IParam, StringBuilder lpBuffer, int nSize);
|
||||
[DllImport("user32", EntryPoint = "GetKeyboardState")]
|
||||
//获取按键的状态
|
||||
private static extern int GetKeyboardState(byte[] pbKeyState);
|
||||
[DllImport("user32", EntryPoint = "ToAscii")]
|
||||
//ToAscii职能的转换指定的虚拟键码和键盘状态的相应字符或字符
|
||||
private static extern bool ToAscii(int VirtualKey, int ScanCode, byte[] lpKeySate, ref uint lpChar, int uFlags);
|
||||
|
||||
//int VirtualKey //[in] 指定虚拟关键代码进行翻译。
|
||||
//int uScanCode, // [in] 指定的硬件扫描码的关键须翻译成英文。高阶位的这个值设定的关键,如果是(不压)
|
||||
//byte[] lpbKeyState, // [in] 指针,以256字节数组,包含当前键盘的状态。每个元素(字节)的数组包含状态的一个关键。如果高阶位的字节是一套,关键是下跌(按下)。在低比特,如/果设置表明,关键是对切换。在此功能,只有肘位的CAPS LOCK键是相关的。在切换状态的NUM个锁和滚动锁定键被忽略。
|
||||
//byte[] lpwTransKey, // [out] 指针的缓冲区收到翻译字符或字符。
|
||||
//uint fuState); // [in] Specifies whether a menu is active. This parameter must be 1 if a menu is active, or 0 otherwise.
|
||||
|
||||
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
//使用WINDOWS API函数代替获取当前实例的函数,防止钩子失效
|
||||
public static extern IntPtr GetModuleHandle(string name);
|
||||
public ScanerHook()
|
||||
{
|
||||
}
|
||||
public bool Start()
|
||||
{
|
||||
if (hKeyboardHook == 0)
|
||||
{
|
||||
hookproc = new HookProc(KeyboardHookProc);
|
||||
//GetModuleHandle 函数 替代 Marshal.GetHINSTANCE
|
||||
//防止在 framework4.0中 注册钩子不成功
|
||||
IntPtr modulePtr = GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName);
|
||||
//WH_KEYBOARD_LL=13
|
||||
//全局钩子 WH_KEYBOARD_LL
|
||||
// hKeyboardHook = SetWindowsHookEx(13, hookproc, Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly().GetModules()[0]), 0);
|
||||
hKeyboardHook = SetWindowsHookEx(13, hookproc, modulePtr, 0);
|
||||
}
|
||||
return (hKeyboardHook != 0);
|
||||
}
|
||||
public bool Stop()
|
||||
{
|
||||
if (hKeyboardHook != 0)
|
||||
{
|
||||
bool retKeyboard = UnhookWindowsHookEx(hKeyboardHook);
|
||||
hKeyboardHook = 0;
|
||||
return retKeyboard;
|
||||
|
||||
}
|
||||
return true;
|
||||
}
|
||||
private int KeyboardHookProc(int nCode, Int32 wParam, IntPtr lParam)
|
||||
{
|
||||
|
||||
|
||||
EventMsg msg = (EventMsg)Marshal.PtrToStructure(lParam, typeof(EventMsg));
|
||||
codes.Add(msg);
|
||||
if (ScanerEvent != null && msg.message == 13 && msg.paramH > 0 && !string.IsNullOrEmpty(codes.Result))
|
||||
{
|
||||
ScanerEvent(codes);
|
||||
}
|
||||
return CallNextHookEx(hKeyboardHook, nCode, wParam, lParam);
|
||||
}
|
||||
public class ScanerCodes
|
||||
{
|
||||
private int ts = 100; // 指定输入间隔为300毫秒以内时为连续输入
|
||||
private List<List<EventMsg>> _keys = new List<List<EventMsg>>();
|
||||
private List<int> _keydown = new List<int>(); // 保存组合键状态
|
||||
private List<string> _result = new List<string>(); // 返回结果集
|
||||
private DateTime _last = DateTime.Now;
|
||||
private byte[] _state = new byte[256];
|
||||
private string _key = string.Empty;
|
||||
private string _cur = string.Empty;
|
||||
public EventMsg Event
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_keys.Count == 0)
|
||||
{
|
||||
return new EventMsg();
|
||||
}
|
||||
else
|
||||
{
|
||||
return _keys[_keys.Count - 1][_keys[_keys.Count - 1].Count - 1];
|
||||
}
|
||||
}
|
||||
}
|
||||
public List<int> KeyDowns
|
||||
{
|
||||
get
|
||||
{
|
||||
return _keydown;
|
||||
}
|
||||
}
|
||||
public DateTime LastInput
|
||||
{
|
||||
get
|
||||
{
|
||||
return _last;
|
||||
}
|
||||
}
|
||||
public byte[] KeyboardState
|
||||
{
|
||||
get
|
||||
{
|
||||
return _state;
|
||||
}
|
||||
}
|
||||
public int KeyDownCount
|
||||
{
|
||||
get
|
||||
{
|
||||
return _keydown.Count;
|
||||
}
|
||||
}
|
||||
public string Result
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_result.Count > 0)
|
||||
{
|
||||
return _result[_result.Count - 1].Trim();
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
public string CurrentKey
|
||||
{
|
||||
get
|
||||
{
|
||||
return _key;
|
||||
}
|
||||
}
|
||||
public string CurrentChar
|
||||
{
|
||||
get
|
||||
{
|
||||
return _cur;
|
||||
}
|
||||
}
|
||||
public bool isShift
|
||||
{
|
||||
get
|
||||
{
|
||||
return _keydown.Contains(160);
|
||||
}
|
||||
}
|
||||
public void Add(EventMsg msg)
|
||||
{
|
||||
#region 记录按键信息
|
||||
|
||||
// 首次按下按键
|
||||
if (_keys.Count == 0)
|
||||
{
|
||||
_keys.Add(new List<EventMsg>());
|
||||
_keys[0].Add(msg);
|
||||
_result.Add(string.Empty);
|
||||
}
|
||||
// 未释放其他按键时按下按键
|
||||
else if (_keydown.Count > 0)
|
||||
{
|
||||
_keys[_keys.Count - 1].Add(msg);
|
||||
}
|
||||
// 单位时间内按下按键
|
||||
else if (((TimeSpan)(DateTime.Now - _last)).TotalMilliseconds < ts)
|
||||
{
|
||||
_keys[_keys.Count - 1].Add(msg);
|
||||
}
|
||||
// 从新记录输入内容
|
||||
else
|
||||
{
|
||||
_keys.Add(new List<EventMsg>());
|
||||
_keys[_keys.Count - 1].Add(msg);
|
||||
_result.Add(string.Empty);
|
||||
}
|
||||
#endregion
|
||||
_last = DateTime.Now;
|
||||
#region 获取键盘状态
|
||||
// 记录正在按下的按键
|
||||
if (msg.paramH == 0 && !_keydown.Contains(msg.message))
|
||||
{
|
||||
_keydown.Add(msg.message);
|
||||
}
|
||||
// 清除已松开的按键
|
||||
if (msg.paramH > 0 && _keydown.Contains(msg.message))
|
||||
{
|
||||
_keydown.Remove(msg.message);
|
||||
}
|
||||
#endregion
|
||||
#region 计算按键信息
|
||||
|
||||
int v = msg.message & 0xff;
|
||||
int c = msg.paramL & 0xff;
|
||||
StringBuilder strKeyName = new StringBuilder(500);
|
||||
if (GetKeyNameText(c * 65536, strKeyName, 255) > 0)
|
||||
{
|
||||
_key = strKeyName.ToString().Trim(new char[] { ' ', '\0' });
|
||||
GetKeyboardState(_state);
|
||||
if (_key.Length == 1 && msg.paramH == 0)// && msg.paramH == 0
|
||||
{
|
||||
// 根据键盘状态和shift缓存判断输出字符
|
||||
_cur = ShiftChar(_key, isShift, _state).ToString();
|
||||
_result[_result.Count - 1] += _cur;
|
||||
}
|
||||
// 备选
|
||||
else
|
||||
{
|
||||
_cur = string.Empty;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
private char ShiftChar(string k, bool isShiftDown, byte[] state)
|
||||
{
|
||||
bool capslock = state[0x14] == 1;
|
||||
bool numlock = state[0x90] == 1;
|
||||
bool scrolllock = state[0x91] == 1;
|
||||
bool shiftdown = state[0xa0] == 1;
|
||||
char chr = (capslock ? k.ToUpper() : k.ToLower()).ToCharArray()[0];
|
||||
if (isShiftDown)
|
||||
{
|
||||
if (chr >= 'a' && chr <= 'z')
|
||||
{
|
||||
chr = (char)((int)chr - 32);
|
||||
}
|
||||
else if (chr >= 'A' && chr <= 'Z')
|
||||
{
|
||||
if (chr == 'Z')
|
||||
{
|
||||
string s = "";
|
||||
}
|
||||
chr = (char)((int)chr + 32);
|
||||
}
|
||||
else
|
||||
{
|
||||
string s = "`1234567890-=[];',./";
|
||||
string u = "~!@#$%^&*()_+{}:\"<>?";
|
||||
if (s.IndexOf(chr) >= 0)
|
||||
{
|
||||
return (u.ToCharArray())[s.IndexOf(chr)];
|
||||
}
|
||||
}
|
||||
}
|
||||
return chr;
|
||||
}
|
||||
}
|
||||
|
||||
public struct EventMsg
|
||||
{
|
||||
public int message;
|
||||
public int paramL;
|
||||
public int paramH;
|
||||
public int Time;
|
||||
public int hwnd;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,856 @@
|
||||
using JinYuan.Models;
|
||||
using Newtonsoft.Json;
|
||||
using PLCCommunication.MQTT;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
|
||||
|
||||
namespace JinYuan.Helper
|
||||
{
|
||||
public class MqttService : IDisposable
|
||||
{
|
||||
private readonly MqttClient _mqttClient;
|
||||
private readonly object _syncLock = new object();
|
||||
private readonly MqttConfig _config;
|
||||
public class MqttConfig
|
||||
{
|
||||
public string ServerAddress { get; set; } = "10.22.161.1";
|
||||
public int ServerPort { get; set; } = 2883;
|
||||
public string ClientId { get; set; } = "601PWM01";
|
||||
//进出站主题
|
||||
public string TopicInOut { get; set; } = "EVE/60J/TrackInOut/601PWM01";
|
||||
//预测性维护数据主题
|
||||
public string TopicForecast { get; set; } = "EVE/60J/EQP/601PWM01";
|
||||
// 其他配置项...
|
||||
}
|
||||
|
||||
public MqttService(MqttConfig config)
|
||||
{
|
||||
_config = config;
|
||||
_mqttClient = new MqttClient(new MqttConnectionOptions
|
||||
{
|
||||
ClientId = _config.ClientId,
|
||||
IpAddress = _config.ServerAddress,
|
||||
Port = _config.ServerPort,
|
||||
Credentials = new MqttCredential("", "") // 无用户名密码
|
||||
});
|
||||
InitializeConnection();
|
||||
StartHeartbeat();//心跳检测
|
||||
}
|
||||
|
||||
#region 长连接
|
||||
/// <summary>
|
||||
/// 初始化长连接
|
||||
/// </summary>
|
||||
private void InitializeConnection()
|
||||
{
|
||||
lock (_syncLock)
|
||||
{
|
||||
if (_mqttClient.IsConnected) return;
|
||||
var result = _mqttClient.ConnectServer();
|
||||
if (result.IsSuccess)
|
||||
{
|
||||
Logger.WriteMqtt("MQTT 长连接建立成功");
|
||||
// 订阅需要的主题
|
||||
SubscribeTopics();
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.WriteMqtt($"MQTT 长连接建立失败: {result.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 订阅主题
|
||||
/// </summary>
|
||||
private void SubscribeTopics()
|
||||
{
|
||||
//_mqttClient.OnMqttMessageReceived += MqttMessageReceived;
|
||||
|
||||
var topics = new[] { _config.TopicInOut, _config.TopicForecast };
|
||||
foreach (var topic in topics)
|
||||
{
|
||||
var result = _mqttClient.SubscribeMessage(topic);
|
||||
if (result.IsSuccess)
|
||||
{
|
||||
Logger.WriteMqtt($"订阅主题成功: {topic}");
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.WriteMqtt($"订阅主题失败: {topic}, 错误: {result.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 消息接收处理
|
||||
/// </summary>
|
||||
/// <param name="client"></param>
|
||||
/// <param name="message"></param>
|
||||
private void MqttMessageReceived(MqttClient client, MqttApplicationMessage message)
|
||||
{
|
||||
Logger.WriteMqtt($"收到消息: 主题[{message.Topic}], 内容[{Encoding.UTF8.GetString(message.Payload)}]");
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 发送消息
|
||||
/// <summary>
|
||||
/// 发送进出站消息
|
||||
/// </summary>
|
||||
/// <param name="action"></param>
|
||||
public void SendInOutMessage(string action)
|
||||
{
|
||||
try
|
||||
{
|
||||
lock (_syncLock)
|
||||
{
|
||||
if (!_mqttClient.IsConnected)
|
||||
Reconnect();
|
||||
|
||||
var message = BuildInOutMessage(action);
|
||||
var result = _mqttClient.PublishMessage(new MqttApplicationMessage
|
||||
{
|
||||
Topic = _config.TopicInOut,
|
||||
Payload = Encoding.UTF8.GetBytes(message),
|
||||
QualityOfServiceLevel = MqttQualityOfServiceLevel.AtMostOnce,
|
||||
Retain = false
|
||||
});
|
||||
|
||||
if (result.IsSuccess)
|
||||
{
|
||||
Logger.WriteMqtt($"进出站消息发送成功 主题:{_config.TopicInOut}: {message}");
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.WriteError($"进出站消息发送失败: {result.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.WriteError($"发送进出站消息异常: {ex.Message}", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 发送预测数据
|
||||
/// </summary>
|
||||
/// <param name="data"></param>
|
||||
public void SendForecastMessage(Predictability_BM data)
|
||||
{
|
||||
try
|
||||
{
|
||||
lock (_syncLock)
|
||||
{
|
||||
if (!_mqttClient.IsConnected)
|
||||
{
|
||||
Reconnect();
|
||||
}
|
||||
|
||||
var message = BuildForecastMessage(data);
|
||||
var result = _mqttClient.PublishMessage(new MqttApplicationMessage
|
||||
{
|
||||
Topic = _config.TopicForecast,
|
||||
Payload = Encoding.UTF8.GetBytes(message),
|
||||
QualityOfServiceLevel = MqttQualityOfServiceLevel.AtMostOnce,
|
||||
Retain = false
|
||||
});
|
||||
|
||||
if (result.IsSuccess)
|
||||
{
|
||||
Logger.WriteInfo($"预测数据发送成功 主题:{_config.TopicForecast}: {message}");
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.WriteError($"预测数据发送失败: {result.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.WriteError($"发送预测数据异常: {ex.Message}", ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region 构建消息
|
||||
/// <summary>
|
||||
/// 构建进出站消息
|
||||
/// </summary>
|
||||
/// <param name="action"></param>
|
||||
/// <returns></returns>
|
||||
private string BuildInOutMessage(string action)
|
||||
{
|
||||
try
|
||||
{
|
||||
var message = new EnterandExit
|
||||
{
|
||||
bu_id = "EVE8BU",
|
||||
district_id = "JM",
|
||||
factory_id = "60J",
|
||||
production_line_id = "601L",
|
||||
work_center_id = "601PWE01",
|
||||
device_name = "601PWM01",
|
||||
action = action,
|
||||
action_time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")
|
||||
};
|
||||
|
||||
return JsonConvert.SerializeObject(message, new JsonSerializerSettings
|
||||
{
|
||||
NullValueHandling = NullValueHandling.Ignore,
|
||||
Formatting = Formatting.None
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.WriteError($"构建进出站消息失败: {ex.Message}", ex);
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 构建预测数据消息
|
||||
/// </summary>
|
||||
/// <param name="data"></param>
|
||||
/// <returns></returns>
|
||||
public string BuildForecastMessage(Predictability_BM predictability)
|
||||
{
|
||||
try
|
||||
{
|
||||
CollectionUpload collectionUpload = new CollectionUpload()
|
||||
{
|
||||
bu_id = "EVE8BU",
|
||||
district_id = "JM",
|
||||
factory_id = "60J",
|
||||
production_line_id = "601L",
|
||||
production_processes_id = "",
|
||||
work_center_id = "601PWE01",
|
||||
station_id = "",
|
||||
device_name = "601PWM01",
|
||||
taglist = new List<Collection>
|
||||
{
|
||||
new Collection
|
||||
{
|
||||
device_time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
|
||||
collection_items = new Dictionary<string, string>
|
||||
{
|
||||
//扭矩
|
||||
{"Coating1_Torque1", predictability.Coating1_Torque1},
|
||||
{"Coating1_Torque2", predictability.Coating1_Torque2},
|
||||
{"Coating1_Torque3", predictability.Coating1_Torque3},
|
||||
{"Coating1_Torque4", predictability.Coating1_Torque4},
|
||||
{"Coating1_Torque5", predictability.Coating1_Torque5},
|
||||
{"Coating1_Torque6", predictability.Coating1_Torque6},
|
||||
{"Coating1_Torque7", predictability.Coating1_Torque7},
|
||||
{"Coating1_Torque8", predictability.Coating1_Torque8},
|
||||
{"Coating2_Torque1", predictability.Coating2_Torque1},
|
||||
{"Coating2_Torque2", predictability.Coating2_Torque2},
|
||||
{"Coating2_Torque3", predictability.Coating2_Torque3},
|
||||
{"Coating2_Torque4", predictability.Coating2_Torque4},
|
||||
{"Coating2_Torque5", predictability.Coating2_Torque5},
|
||||
{"Coating2_Torque6", predictability.Coating2_Torque6},
|
||||
{"Coating2_Torque7", predictability.Coating2_Torque7},
|
||||
{"Coating2_Torque8", predictability.Coating2_Torque8},
|
||||
{"Folding1_Torque1", predictability.Folding1_Torque1},
|
||||
{"Folding1_Torque2", predictability.Folding1_Torque2},
|
||||
{"Folding1_Torque3", predictability.Folding1_Torque3},
|
||||
{"Folding2_Torque1", predictability.Folding2_Torque1},
|
||||
{"Folding2_Torque2", predictability.Folding2_Torque2},
|
||||
{"Folding2_Torque3", predictability.Folding2_Torque3},
|
||||
//轴速度
|
||||
{"Coating1_AxisSpeed1", predictability.Coating1_AxisSpeed1},
|
||||
{"Coating1_AxisSpeed2", predictability.Coating1_AxisSpeed2},
|
||||
{"Coating1_AxisSpeed3", predictability.Coating1_AxisSpeed3},
|
||||
{"Coating1_AxisSpeed4", predictability.Coating1_AxisSpeed4},
|
||||
{"Coating1_AxisSpeed5", predictability.Coating1_AxisSpeed5},
|
||||
{"Coating1_AxisSpeed6", predictability.Coating1_AxisSpeed6},
|
||||
{"Coating1_AxisSpeed7", predictability.Coating1_AxisSpeed7},
|
||||
{"Coating1_AxisSpeed8", predictability.Coating1_AxisSpeed8},
|
||||
{"Coating2_AxisSpeed1", predictability.Coating2_AxisSpeed1},
|
||||
{"Coating2_AxisSpeed2", predictability.Coating2_AxisSpeed2},
|
||||
{"Coating2_AxisSpeed3", predictability.Coating2_AxisSpeed3},
|
||||
{"Coating2_AxisSpeed4", predictability.Coating2_AxisSpeed4},
|
||||
{"Coating2_AxisSpeed5", predictability.Coating2_AxisSpeed5},
|
||||
{"Coating2_AxisSpeed6", predictability.Coating2_AxisSpeed6},
|
||||
{"Coating2_AxisSpeed7", predictability.Coating2_AxisSpeed7},
|
||||
{"Coating2_AxisSpeed8", predictability.Coating2_AxisSpeed8},
|
||||
{"Folding1_AxisSpeed1", predictability.Folding1_AxisSpeed1},
|
||||
{"Folding1_AxisSpeed2", predictability.Folding1_AxisSpeed2},
|
||||
{"Folding1_AxisSpeed3", predictability.Folding1_AxisSpeed3},
|
||||
{"Folding2_AxisSpeed1", predictability.Folding2_AxisSpeed1},
|
||||
{"Folding2_AxisSpeed2", predictability.Folding2_AxisSpeed2},
|
||||
{"Folding2_AxisSpeed3", predictability.Folding2_AxisSpeed3},
|
||||
//轴位置
|
||||
{"Coating1_AxisPosition1", predictability.Coating1_AxisPosition1},
|
||||
{"Coating1_AxisPosition2", predictability.Coating1_AxisPosition2},
|
||||
{"Coating1_AxisPosition3", predictability.Coating1_AxisPosition3},
|
||||
{"Coating1_AxisPosition4", predictability.Coating1_AxisPosition4},
|
||||
{"Coating1_AxisPosition5", predictability.Coating1_AxisPosition5},
|
||||
{"Coating1_AxisPosition6", predictability.Coating1_AxisPosition6},
|
||||
{"Coating1_AxisPosition7", predictability.Coating1_AxisPosition7},
|
||||
{"Coating1_AxisPosition8", predictability.Coating1_AxisPosition8},
|
||||
{"Coating2_AxisPosition1", predictability.Coating2_AxisPosition1},
|
||||
{"Coating2_AxisPosition2", predictability.Coating2_AxisPosition2},
|
||||
{"Coating2_AxisPosition3", predictability.Coating2_AxisPosition3},
|
||||
{"Coating2_AxisPosition4", predictability.Coating2_AxisPosition4},
|
||||
{"Coating2_AxisPosition5", predictability.Coating2_AxisPosition5},
|
||||
{"Coating2_AxisPosition6", predictability.Coating2_AxisPosition6},
|
||||
{"Coating2_AxisPosition7", predictability.Coating2_AxisPosition7},
|
||||
{"Coating2_AxisPosition8", predictability.Coating2_AxisPosition8},
|
||||
{"Folding1_AxisPosition1", predictability.Folding1_AxisPosition1},
|
||||
{"Folding1_AxisPosition2", predictability.Folding1_AxisPosition2},
|
||||
{"Folding1_AxisPosition3", predictability.Folding1_AxisPosition3},
|
||||
{"Folding2_AxisPosition1", predictability.Folding2_AxisPosition1},
|
||||
{"Folding2_AxisPosition2", predictability.Folding2_AxisPosition2},
|
||||
{"Folding2_AxisPosition3", predictability.Folding2_AxisPosition3},
|
||||
//行程时间
|
||||
{"Coating1_Cylinder_TravelTime1", predictability.Coating1_Cylinder_TravelTime1},
|
||||
{"Coating1_Cylinder_TravelTime2", predictability.Coating1_Cylinder_TravelTime2},
|
||||
{"Coating1_Cylinder_TravelTime3", predictability.Coating1_Cylinder_TravelTime3},
|
||||
{"Coating1_Cylinder_TravelTime4", predictability.Coating1_Cylinder_TravelTime4},
|
||||
{"Coating1_Cylinder_TravelTime5", predictability.Coating1_Cylinder_TravelTime5},
|
||||
{"Coating1_Cylinder_TravelTime6", predictability.Coating1_Cylinder_TravelTime6},
|
||||
{"Coating1_Cylinder_TravelTime7", predictability.Coating1_Cylinder_TravelTime7},
|
||||
{"Coating1_Cylinder_TravelTime8", predictability.Coating1_Cylinder_TravelTime8},
|
||||
{"Coating1_Cylinder_TravelTime9", predictability.Coating1_Cylinder_TravelTime9},
|
||||
{"Coating1_Cylinder_TravelTime10", predictability.Coating1_Cylinder_TravelTime10},
|
||||
{"Coating1_Cylinder_TravelTime11", predictability.Coating1_Cylinder_TravelTime11},
|
||||
{"Coating1_Cylinder_TravelTime12", predictability.Coating1_Cylinder_TravelTime12},
|
||||
{"Coating1_Cylinder_TravelTime13", predictability.Coating1_Cylinder_TravelTime13},
|
||||
{"Coating1_Cylinder_TravelTime14", predictability.Coating1_Cylinder_TravelTime14},
|
||||
{"Coating2_Cylinder_TravelTime1", predictability.Coating2_Cylinder_TravelTime1},
|
||||
{"Coating2_Cylinder_TravelTime2", predictability.Coating2_Cylinder_TravelTime2},
|
||||
{"Coating2_Cylinder_TravelTime3", predictability.Coating2_Cylinder_TravelTime3},
|
||||
{"Coating2_Cylinder_TravelTime4", predictability.Coating2_Cylinder_TravelTime4},
|
||||
{"Coating2_Cylinder_TravelTime5", predictability.Coating2_Cylinder_TravelTime5},
|
||||
{"Coating2_Cylinder_TravelTime6", predictability.Coating2_Cylinder_TravelTime6},
|
||||
{"Coating2_Cylinder_TravelTime7", predictability.Coating2_Cylinder_TravelTime7},
|
||||
{"Coating2_Cylinder_TravelTime8", predictability.Coating2_Cylinder_TravelTime8},
|
||||
{"Coating2_Cylinder_TravelTime9", predictability.Coating2_Cylinder_TravelTime9},
|
||||
{"Coating2_Cylinder_TravelTime10", predictability.Coating2_Cylinder_TravelTime10},
|
||||
{"Coating2_Cylinder_TravelTime11", predictability.Coating2_Cylinder_TravelTime11},
|
||||
{"Coating2_Cylinder_TravelTime12", predictability.Coating2_Cylinder_TravelTime12},
|
||||
{"Coating2_Cylinder_TravelTime13", predictability.Coating2_Cylinder_TravelTime13},
|
||||
{"Coating2_Cylinder_TravelTime14", predictability.Coating2_Cylinder_TravelTime14},
|
||||
{"CornerCutting1_Cylinder_TravelTime1", predictability.CornerCutting1_Cylinder_TravelTime1},
|
||||
{"CornerCutting1_Cylinder_TravelTime2", predictability.CornerCutting1_Cylinder_TravelTime2},
|
||||
{"CornerCutting1_Cylinder_TravelTime3", predictability.CornerCutting1_Cylinder_TravelTime3},
|
||||
{"CornerCutting1_Cylinder_TravelTime4", predictability.CornerCutting1_Cylinder_TravelTime4},
|
||||
{"CornerCutting1_Cylinder_TravelTime5", predictability.CornerCutting1_Cylinder_TravelTime5},
|
||||
{"CornerCutting1_Cylinder_TravelTime6", predictability.CornerCutting1_Cylinder_TravelTime6},
|
||||
{"CornerCutting1_Cylinder_TravelTime7", predictability.CornerCutting1_Cylinder_TravelTime7},
|
||||
{"CornerCutting1_Cylinder_TravelTime8", predictability.CornerCutting1_Cylinder_TravelTime8},
|
||||
{"CornerCutting2_Cylinder_TravelTime1", predictability.CornerCutting2_Cylinder_TravelTime1},
|
||||
{"CornerCutting2_Cylinder_TravelTime2", predictability.CornerCutting2_Cylinder_TravelTime2},
|
||||
{"CornerCutting2_Cylinder_TravelTime3", predictability.CornerCutting2_Cylinder_TravelTime3},
|
||||
{"CornerCutting2_Cylinder_TravelTime4", predictability.CornerCutting2_Cylinder_TravelTime4},
|
||||
{"CornerCutting2_Cylinder_TravelTime5", predictability.CornerCutting2_Cylinder_TravelTime5},
|
||||
{"CornerCutting2_Cylinder_TravelTime6", predictability.CornerCutting2_Cylinder_TravelTime6},
|
||||
{"CornerCutting2_Cylinder_TravelTime7", predictability.CornerCutting2_Cylinder_TravelTime7},
|
||||
{"CornerCutting2_Cylinder_TravelTime8", predictability.CornerCutting2_Cylinder_TravelTime8},
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
// 根据实际数据结构调整
|
||||
return JsonConvert.SerializeObject(collectionUpload, new JsonSerializerSettings
|
||||
{
|
||||
NullValueHandling = NullValueHandling.Ignore,
|
||||
Formatting = Formatting.None
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.WriteError($"构建预测数据消息失败: {ex.Message}", ex);
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// 重新连接
|
||||
/// </summary>
|
||||
private void Reconnect()
|
||||
{
|
||||
try
|
||||
{
|
||||
_mqttClient.ConnectClose();
|
||||
InitializeConnection();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.WriteError($"MQTT重连失败: {ex.Message}", ex);
|
||||
}
|
||||
}
|
||||
#region 资源释放跟心跳检测
|
||||
private Timer _heartbeatTimer;
|
||||
private bool _disposed = false;
|
||||
|
||||
|
||||
// 心跳检测
|
||||
private void StartHeartbeat()
|
||||
{
|
||||
_heartbeatTimer = new Timer(state =>
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!_mqttClient.IsConnected)
|
||||
{
|
||||
Logger.WriteMqtt("检测到MQTT连接断开,尝试重连...");
|
||||
Reconnect();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.WriteError($"心跳检测异常: {ex.Message}", ex);
|
||||
}
|
||||
}, null, TimeSpan.FromMinutes(1), TimeSpan.FromMinutes(1)); // 每分钟检查一次
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (_disposed) return;
|
||||
|
||||
if (disposing)
|
||||
{
|
||||
_heartbeatTimer?.Dispose();
|
||||
_mqttClient?.ConnectClose();
|
||||
_mqttClient?.Dispose();
|
||||
}
|
||||
|
||||
_disposed = true;
|
||||
}
|
||||
|
||||
~MqttService()
|
||||
{
|
||||
Dispose(false);
|
||||
}
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
/*public class SendDateMQTT
|
||||
{
|
||||
HslCommunication.MQTT.MqttClient mqttClientIN = null;
|
||||
HslCommunication.MQTT.MqttClient mqttClientOUT = null;
|
||||
HslCommunication.MQTT.MqttClient mqttClientForecast = null;
|
||||
private static readonly object ObjectIN = new object();
|
||||
private static readonly object ObjectOUT = new object();
|
||||
private static readonly object ObjectForecast = new object();
|
||||
//10.22.160.144
|
||||
public string MQTTServerAddress = "10.22.161.1";//"10.22.161.1";
|
||||
public int MQTTServerPort = 2883;//2883
|
||||
public string ClientId = "601PWM01";
|
||||
|
||||
/// <summary> 进出站主题</summary>
|
||||
public string Topic = "EVE/60J/TrackInOut/601PWM01";
|
||||
/// <summary>CTPCTQ主题</summary>
|
||||
public string Topic1 = "EVE/60J/CTPCTQ/601PWM01";
|
||||
// <summary>预测性维护数据主题</summary>
|
||||
public string Topic2 = "EVE/60J/EQP/601PWM01";
|
||||
|
||||
/// <summary>BU编码</summary>
|
||||
public string BU_id = "EVE8BU";
|
||||
/// <summary>区域简称</summary>
|
||||
public string District_id = "JM";
|
||||
/// <summary>工厂编码</summary>
|
||||
public string Factory_id = "60J";
|
||||
/// <summary>工序编码</summary>
|
||||
public string Production_line_id = "601L";
|
||||
/// <summary>工作中心编码</summary>
|
||||
public string Work_center_id = "601PWE01";
|
||||
/// <summary>设备编码</summary>
|
||||
public string Device_name = "601PWM01";
|
||||
|
||||
/// <summary>
|
||||
/// 发送Mqtt进站数据
|
||||
/// </summary>
|
||||
/// <param name="topic"></param>
|
||||
/// <param name="IP"></param>
|
||||
/// <param name="Port"></param>
|
||||
/// <param name="cTPCTQDate"></param>
|
||||
public void EnterandExitSendMessgeIN()
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
lock (ObjectIN)
|
||||
{
|
||||
if (mqttClientIN != null) { mqttClientIN.ConnectClose(); }
|
||||
Connect(mqttClientIN, MQTTServerAddress, MQTTServerPort, "", "");
|
||||
SubscribeMessage(mqttClientIN, Topic);
|
||||
PublishMessage(mqttClientIN, Topic, EnterandExitMessge("0"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.WriteError($"发送进出站数据错误,{ex.Message}", ex);
|
||||
//CommonMethods.AddLog(true, $"发送进出站数据错误,{ex.Message}");
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 发送Mqtt出站数据
|
||||
/// </summary>
|
||||
/// <param name="topic"></param>
|
||||
/// <param name="IP"></param>
|
||||
/// <param name="Port"></param>
|
||||
/// <param name="cTPCTQDate"></param>
|
||||
public void EnterandExitSendMessgeOUT()
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
lock (ObjectOUT)
|
||||
{
|
||||
if (mqttClientOUT != null) { mqttClientOUT.ConnectClose(); }
|
||||
Connect(mqttClientOUT, MQTTServerAddress, MQTTServerPort, "", "");
|
||||
SubscribeMessage(mqttClientOUT, Topic);
|
||||
PublishMessage(mqttClientOUT, Topic, EnterandExitMessge("1"));
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.WriteError($"发送进出站数据错误,{ex.Message}", ex);
|
||||
//CommonMethods.AddLog(true, $"发送进出站数据错误,{ex.Message}");
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 发送采集项数据
|
||||
/// </summary>
|
||||
/// <param name="topic"></param>
|
||||
/// <param name="IP"></param>
|
||||
/// <param name="Port"></param>
|
||||
/// <param name="预测性维护数据"></param>
|
||||
public void CollectionSendMessgeForecast(Predictability_BM predictability)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
lock (ObjectForecast)
|
||||
{
|
||||
if (mqttClientForecast != null) { mqttClientForecast.ConnectClose(); }
|
||||
Connect(mqttClientForecast, MQTTServerAddress, MQTTServerPort, "", "");
|
||||
SubscribeMessage(mqttClientForecast, Topic2);
|
||||
PublishMessage(mqttClientForecast, Topic2, CollectionMessge(predictability));
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.WriteError($"发送采集项数据错误,{ex.Message}", ex);
|
||||
//CommonMethods.AddLog(false, $"发送采集项数据错误,{ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 连接
|
||||
/// </summary>
|
||||
/// <param name="ip"></param>
|
||||
/// <param name="port"></param>
|
||||
/// <param name="name"></param>
|
||||
/// <param name="pwd"></param>
|
||||
/// <param name="clientId"></param>
|
||||
public void Connect(MqttClient mqttClient, string ip, int port, string name, string pwd, string clientId = "ClientId")
|
||||
{
|
||||
try
|
||||
{
|
||||
if (mqttClient != null) mqttClient.ConnectClose();
|
||||
|
||||
mqttClient = new MqttClient(new MqttConnectionOptions()
|
||||
{
|
||||
ClientId = clientId,
|
||||
IpAddress = ip,
|
||||
Port = port,
|
||||
Credentials = new MqttCredential(name, pwd), // 设置了用户名和密码
|
||||
});
|
||||
|
||||
OperateResult connect = mqttClient.ConnectServer();
|
||||
if (connect.IsSuccess)
|
||||
{
|
||||
Logger.WriteMqtt("MQTT 连接服务器成功");
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.WriteMqtt("MQTT 无法连接到服务器");
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.WriteError($"MQTT 无法连接到服务器: {ex.Message}");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 发布信息
|
||||
/// </summary>
|
||||
/// <param name="topic"></param>
|
||||
public void PublishMessage(MqttClient mqttClient, string topic, string Message)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
OperateResult result = mqttClient.PublishMessage(new MqttApplicationMessage()
|
||||
{
|
||||
Topic = topic, // 主题
|
||||
QualityOfServiceLevel = MqttQualityOfServiceLevel.AtMostOnce, // 消息等级
|
||||
Payload = Encoding.UTF8.GetBytes(Message), // 数据
|
||||
Retain = false, // 是否保留
|
||||
});
|
||||
if (result.IsSuccess)
|
||||
{
|
||||
Logger.WriteMqtt($"发送消息到主题 [{topic}]: {Message}");
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.WriteMqtt($"发送消息到主题 [{topic}] 失败: {result.Message}");
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.WriteError($"MQTT 无法连接到服务器: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 订阅主题
|
||||
/// </summary>
|
||||
/// <param name="topic"></param>
|
||||
public void SubscribeMessage(MqttClient mqttClient, string Topic)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
mqttClient.OnMqttMessageReceived += MqttClient_OnMqttMessageReceived; // 调用一次即可
|
||||
OperateResult Result = mqttClient.SubscribeMessage(Topic); // 订阅A的主题
|
||||
if (Result.IsSuccess)
|
||||
{
|
||||
Logger.WriteMqtt($"订阅成功[{Topic}]");
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.WriteMqtt($"订阅失败[{Topic}]");
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.WriteError($"订阅失败[{ex.Message}]");
|
||||
}
|
||||
}
|
||||
|
||||
private static void MqttClient_OnMqttMessageReceived(MqttClient client, MqttApplicationMessage message)
|
||||
{
|
||||
Logger.WriteMqtt($"收到服务器信息[{message.ToString()}]");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 拼接进出站json
|
||||
/// </summary>
|
||||
/// <param name="action"></param>
|
||||
/// <returns></returns>
|
||||
public string EnterandExitMessge(string action)
|
||||
{
|
||||
string messgeJson = string.Empty;
|
||||
try
|
||||
{
|
||||
EnterandExit enterandExit = new EnterandExit()
|
||||
{
|
||||
bu_id = BU_id,
|
||||
district_id = District_id,
|
||||
factory_id = Factory_id,
|
||||
production_line_id = Production_line_id,
|
||||
production_processes_id = "",
|
||||
work_center_id = Work_center_id,
|
||||
station_id = "",
|
||||
device_name = Device_name,
|
||||
action = action,
|
||||
action_time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
|
||||
|
||||
};
|
||||
var messageJson = JsonConvert.SerializeObject(enterandExit, new JsonSerializerSettings
|
||||
{
|
||||
NullValueHandling = NullValueHandling.Ignore,
|
||||
Formatting = Formatting.None
|
||||
});
|
||||
messgeJson = messageJson;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.WriteError($"方法:上传MQTTServer数据,上传失败: {ex.Message}", ex);
|
||||
}
|
||||
return messgeJson;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 拼接采集项数据
|
||||
/// </summary>
|
||||
/// <param name="cPQCPTDate"></param>
|
||||
/// <returns></returns>
|
||||
public string CollectionMessge(Predictability_BM predictability)
|
||||
{
|
||||
string messgejson = string.Empty;
|
||||
try
|
||||
{
|
||||
CollectionUpload collectionUpload = new CollectionUpload()
|
||||
{
|
||||
bu_id = BU_id,
|
||||
district_id = District_id,
|
||||
factory_id = Factory_id,
|
||||
production_line_id = Production_line_id,
|
||||
production_processes_id = "",
|
||||
work_center_id = Work_center_id,
|
||||
station_id = "",
|
||||
device_name = Device_name,
|
||||
taglist = new List<Collection>
|
||||
{
|
||||
new Collection
|
||||
{
|
||||
device_time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
|
||||
collection_items = new Dictionary<string, string>
|
||||
{
|
||||
//扭矩
|
||||
{"Coating1_Torque1", predictability.Coating1_Torque1},
|
||||
{"Coating1_Torque2", predictability.Coating1_Torque2},
|
||||
{"Coating1_Torque3", predictability.Coating1_Torque3},
|
||||
{"Coating1_Torque4", predictability.Coating1_Torque4},
|
||||
{"Coating1_Torque5", predictability.Coating1_Torque5},
|
||||
{"Coating1_Torque6", predictability.Coating1_Torque6},
|
||||
{"Coating1_Torque7", predictability.Coating1_Torque7},
|
||||
{"Coating1_Torque8", predictability.Coating1_Torque8},
|
||||
{"Coating2_Torque1", predictability.Coating2_Torque1},
|
||||
{"Coating2_Torque2", predictability.Coating2_Torque2},
|
||||
{"Coating2_Torque3", predictability.Coating2_Torque3},
|
||||
{"Coating2_Torque4", predictability.Coating2_Torque4},
|
||||
{"Coating2_Torque5", predictability.Coating2_Torque5},
|
||||
{"Coating2_Torque6", predictability.Coating2_Torque6},
|
||||
{"Coating2_Torque7", predictability.Coating2_Torque7},
|
||||
{"Coating2_Torque8", predictability.Coating2_Torque8},
|
||||
{"Folding1_Torque1", predictability.Folding1_Torque1},
|
||||
{"Folding1_Torque2", predictability.Folding1_Torque2},
|
||||
{"Folding1_Torque3", predictability.Folding1_Torque3},
|
||||
{"Folding2_Torque1", predictability.Folding2_Torque1},
|
||||
{"Folding2_Torque2", predictability.Folding2_Torque2},
|
||||
{"Folding2_Torque3", predictability.Folding2_Torque3},
|
||||
//轴速度
|
||||
{"Coating1_AxisSpeed1", predictability.Coating1_AxisSpeed1},
|
||||
{"Coating1_AxisSpeed2", predictability.Coating1_AxisSpeed2},
|
||||
{"Coating1_AxisSpeed3", predictability.Coating1_AxisSpeed3},
|
||||
{"Coating1_AxisSpeed4", predictability.Coating1_AxisSpeed4},
|
||||
{"Coating1_AxisSpeed5", predictability.Coating1_AxisSpeed5},
|
||||
{"Coating1_AxisSpeed6", predictability.Coating1_AxisSpeed6},
|
||||
{"Coating1_AxisSpeed7", predictability.Coating1_AxisSpeed7},
|
||||
{"Coating1_AxisSpeed8", predictability.Coating1_AxisSpeed8},
|
||||
{"Coating2_AxisSpeed1", predictability.Coating2_AxisSpeed1},
|
||||
{"Coating2_AxisSpeed2", predictability.Coating2_AxisSpeed2},
|
||||
{"Coating2_AxisSpeed3", predictability.Coating2_AxisSpeed3},
|
||||
{"Coating2_AxisSpeed4", predictability.Coating2_AxisSpeed4},
|
||||
{"Coating2_AxisSpeed5", predictability.Coating2_AxisSpeed5},
|
||||
{"Coating2_AxisSpeed6", predictability.Coating2_AxisSpeed6},
|
||||
{"Coating2_AxisSpeed7", predictability.Coating2_AxisSpeed7},
|
||||
{"Coating2_AxisSpeed8", predictability.Coating2_AxisSpeed8},
|
||||
{"Folding1_AxisSpeed1", predictability.Folding1_AxisSpeed1},
|
||||
{"Folding1_AxisSpeed2", predictability.Folding1_AxisSpeed2},
|
||||
{"Folding1_AxisSpeed3", predictability.Folding1_AxisSpeed3},
|
||||
{"Folding2_AxisSpeed1", predictability.Folding2_AxisSpeed1},
|
||||
{"Folding2_AxisSpeed2", predictability.Folding2_AxisSpeed2},
|
||||
{"Folding2_AxisSpeed3", predictability.Folding2_AxisSpeed3},
|
||||
//轴位置
|
||||
{"Coating1_AxisPosition1", predictability.Coating1_AxisPosition1},
|
||||
{"Coating1_AxisPosition2", predictability.Coating1_AxisPosition2},
|
||||
{"Coating1_AxisPosition3", predictability.Coating1_AxisPosition3},
|
||||
{"Coating1_AxisPosition4", predictability.Coating1_AxisPosition4},
|
||||
{"Coating1_AxisPosition5", predictability.Coating1_AxisPosition5},
|
||||
{"Coating1_AxisPosition6", predictability.Coating1_AxisPosition6},
|
||||
{"Coating1_AxisPosition7", predictability.Coating1_AxisPosition7},
|
||||
{"Coating1_AxisPosition8", predictability.Coating1_AxisPosition8},
|
||||
{"Coating2_AxisPosition1", predictability.Coating2_AxisPosition1},
|
||||
{"Coating2_AxisPosition2", predictability.Coating2_AxisPosition2},
|
||||
{"Coating2_AxisPosition3", predictability.Coating2_AxisPosition3},
|
||||
{"Coating2_AxisPosition4", predictability.Coating2_AxisPosition4},
|
||||
{"Coating2_AxisPosition5", predictability.Coating2_AxisPosition5},
|
||||
{"Coating2_AxisPosition6", predictability.Coating2_AxisPosition6},
|
||||
{"Coating2_AxisPosition7", predictability.Coating2_AxisPosition7},
|
||||
{"Coating2_AxisPosition8", predictability.Coating2_AxisPosition8},
|
||||
{"Folding1_AxisPosition1", predictability.Folding1_AxisPosition1},
|
||||
{"Folding1_AxisPosition2", predictability.Folding1_AxisPosition2},
|
||||
{"Folding1_AxisPosition3", predictability.Folding1_AxisPosition3},
|
||||
{"Folding2_AxisPosition1", predictability.Folding2_AxisPosition1},
|
||||
{"Folding2_AxisPosition2", predictability.Folding2_AxisPosition2},
|
||||
{"Folding2_AxisPosition3", predictability.Folding2_AxisPosition3},
|
||||
//行程时间
|
||||
{"Coating1_Cylinder_TravelTime1", predictability.Coating1_Cylinder_TravelTime1},
|
||||
{"Coating1_Cylinder_TravelTime2", predictability.Coating1_Cylinder_TravelTime2},
|
||||
{"Coating1_Cylinder_TravelTime3", predictability.Coating1_Cylinder_TravelTime3},
|
||||
{"Coating1_Cylinder_TravelTime4", predictability.Coating1_Cylinder_TravelTime4},
|
||||
{"Coating1_Cylinder_TravelTime5", predictability.Coating1_Cylinder_TravelTime5},
|
||||
{"Coating1_Cylinder_TravelTime6", predictability.Coating1_Cylinder_TravelTime6},
|
||||
{"Coating1_Cylinder_TravelTime7", predictability.Coating1_Cylinder_TravelTime7},
|
||||
{"Coating1_Cylinder_TravelTime8", predictability.Coating1_Cylinder_TravelTime8},
|
||||
{"Coating1_Cylinder_TravelTime9", predictability.Coating1_Cylinder_TravelTime9},
|
||||
{"Coating1_Cylinder_TravelTime10", predictability.Coating1_Cylinder_TravelTime10},
|
||||
{"Coating1_Cylinder_TravelTime11", predictability.Coating1_Cylinder_TravelTime11},
|
||||
{"Coating1_Cylinder_TravelTime12", predictability.Coating1_Cylinder_TravelTime12},
|
||||
{"Coating1_Cylinder_TravelTime13", predictability.Coating1_Cylinder_TravelTime13},
|
||||
{"Coating1_Cylinder_TravelTime14", predictability.Coating1_Cylinder_TravelTime14},
|
||||
{"Coating2_Cylinder_TravelTime1", predictability.Coating2_Cylinder_TravelTime1},
|
||||
{"Coating2_Cylinder_TravelTime2", predictability.Coating2_Cylinder_TravelTime2},
|
||||
{"Coating2_Cylinder_TravelTime3", predictability.Coating2_Cylinder_TravelTime3},
|
||||
{"Coating2_Cylinder_TravelTime4", predictability.Coating2_Cylinder_TravelTime4},
|
||||
{"Coating2_Cylinder_TravelTime5", predictability.Coating2_Cylinder_TravelTime5},
|
||||
{"Coating2_Cylinder_TravelTime6", predictability.Coating2_Cylinder_TravelTime6},
|
||||
{"Coating2_Cylinder_TravelTime7", predictability.Coating2_Cylinder_TravelTime7},
|
||||
{"Coating2_Cylinder_TravelTime8", predictability.Coating2_Cylinder_TravelTime8},
|
||||
{"Coating2_Cylinder_TravelTime9", predictability.Coating2_Cylinder_TravelTime9},
|
||||
{"Coating2_Cylinder_TravelTime10", predictability.Coating2_Cylinder_TravelTime10},
|
||||
{"Coating2_Cylinder_TravelTime11", predictability.Coating2_Cylinder_TravelTime11},
|
||||
{"Coating2_Cylinder_TravelTime12", predictability.Coating2_Cylinder_TravelTime12},
|
||||
{"Coating2_Cylinder_TravelTime13", predictability.Coating2_Cylinder_TravelTime13},
|
||||
{"Coating2_Cylinder_TravelTime14", predictability.Coating2_Cylinder_TravelTime14},
|
||||
{"CornerCutting1_Cylinder_TravelTime1", predictability.CornerCutting1_Cylinder_TravelTime1},
|
||||
{"CornerCutting1_Cylinder_TravelTime2", predictability.CornerCutting1_Cylinder_TravelTime2},
|
||||
{"CornerCutting1_Cylinder_TravelTime3", predictability.CornerCutting1_Cylinder_TravelTime3},
|
||||
{"CornerCutting1_Cylinder_TravelTime4", predictability.CornerCutting1_Cylinder_TravelTime4},
|
||||
{"CornerCutting1_Cylinder_TravelTime5", predictability.CornerCutting1_Cylinder_TravelTime5},
|
||||
{"CornerCutting1_Cylinder_TravelTime6", predictability.CornerCutting1_Cylinder_TravelTime6},
|
||||
{"CornerCutting1_Cylinder_TravelTime7", predictability.CornerCutting1_Cylinder_TravelTime7},
|
||||
{"CornerCutting1_Cylinder_TravelTime8", predictability.CornerCutting1_Cylinder_TravelTime8},
|
||||
{"CornerCutting2_Cylinder_TravelTime1", predictability.CornerCutting2_Cylinder_TravelTime1},
|
||||
{"CornerCutting2_Cylinder_TravelTime2", predictability.CornerCutting2_Cylinder_TravelTime2},
|
||||
{"CornerCutting2_Cylinder_TravelTime3", predictability.CornerCutting2_Cylinder_TravelTime3},
|
||||
{"CornerCutting2_Cylinder_TravelTime4", predictability.CornerCutting2_Cylinder_TravelTime4},
|
||||
{"CornerCutting2_Cylinder_TravelTime5", predictability.CornerCutting2_Cylinder_TravelTime5},
|
||||
{"CornerCutting2_Cylinder_TravelTime6", predictability.CornerCutting2_Cylinder_TravelTime6},
|
||||
{"CornerCutting2_Cylinder_TravelTime7", predictability.CornerCutting2_Cylinder_TravelTime7},
|
||||
{"CornerCutting2_Cylinder_TravelTime8", predictability.CornerCutting2_Cylinder_TravelTime8},
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
var messageJson = JsonConvert.SerializeObject(collectionUpload, new JsonSerializerSettings
|
||||
{
|
||||
NullValueHandling = NullValueHandling.Ignore,
|
||||
Formatting = Formatting.None
|
||||
});
|
||||
messgejson = messageJson;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.WriteError($"生成Json数据失败: {ex.Message}", ex);
|
||||
}
|
||||
return messgejson;
|
||||
}
|
||||
}*/
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace JinYuan.Helper
|
||||
{
|
||||
/// <summary>
|
||||
/// 流读写IO辅助类
|
||||
/// </summary>
|
||||
public class StreamIOHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// 写入文件字节流
|
||||
/// </summary>
|
||||
/// <param name="stream">待写入的流</param>
|
||||
/// <param name="bys">写入的文件流</param>
|
||||
/// <param name="isCloseStream">是否在操作后关闭流</param>
|
||||
/// <returns>是否写入成功:true:成功;false:失败</returns>
|
||||
public static bool WriteStreamBytes(Stream stream, byte[] bys, bool isCloseStream = false)
|
||||
{
|
||||
//确保文件支持写入
|
||||
if (stream == null || !stream.CanWrite)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
//单次写入的长度
|
||||
int perWriteByteLen = 1024 * 1024;
|
||||
//单次读取的索引下标
|
||||
int startIndex = 0;
|
||||
//写入的总长度
|
||||
int allLen = bys.Length;
|
||||
while (startIndex < allLen && startIndex >= 0)
|
||||
{
|
||||
stream.Write(bys, startIndex, (startIndex > allLen - perWriteByteLen) ? allLen - startIndex : perWriteByteLen);
|
||||
startIndex += perWriteByteLen;
|
||||
}
|
||||
stream.Flush();
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine(ex.Message + "\t" + ex.StackTrace);
|
||||
return false;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (isCloseStream)
|
||||
{
|
||||
CloseStream(stream);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 读取文件字节流
|
||||
/// 读取异常或者文件不存在时返回null;
|
||||
/// </summary>
|
||||
/// <param name="stream">读取的字节流</param>
|
||||
/// <param name="isCloseStream">是否在操作后关闭流</param>
|
||||
/// <returns>读取到的文件字节流</returns>
|
||||
public static byte[] ReadStreamBytes(Stream stream, bool isCloseStream = false)
|
||||
{
|
||||
//检测是否支持读操作
|
||||
if (stream == null || !stream.CanRead || stream.Length == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
byte[] resBytes = new byte[stream.Length];
|
||||
int allLen = (int)stream.Length;
|
||||
//单次读取的长度,1024字节即1kb,1024*1024=1M
|
||||
int perReadByteLen = 1024 * 1024;
|
||||
//单次读取的索引下标
|
||||
int startIndex = 0;
|
||||
//单次读取到的长度
|
||||
int readLen = 0;
|
||||
while ((readLen = stream.Read(resBytes, startIndex, (startIndex > allLen - perReadByteLen) ? allLen - startIndex : perReadByteLen)) > 0)
|
||||
{
|
||||
startIndex += readLen;
|
||||
}
|
||||
if (startIndex == allLen)
|
||||
{
|
||||
return resBytes;
|
||||
}
|
||||
else
|
||||
{
|
||||
return ArrayHelper.GetSubArray<byte>(resBytes, 0, startIndex);
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine(ex.Message + "\t" + ex.StackTrace);
|
||||
return null;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (isCloseStream)
|
||||
{
|
||||
CloseStream(stream);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 关闭流
|
||||
/// </summary>
|
||||
/// <param name="fileInfo"></param>
|
||||
public static void CloseStream(Stream fileInfo)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (fileInfo != null)
|
||||
fileInfo.Dispose();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine(ex.Message + "\t" + ex.StackTrace);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
|
||||
namespace JinYuan.Helper
|
||||
{
|
||||
/// <summary>
|
||||
/// 字符串加密解密类
|
||||
/// </summary>
|
||||
public class StringSecurityHelper
|
||||
{
|
||||
private static string md5Begin = "Hello";
|
||||
private static string md5End = "World";
|
||||
|
||||
#region SHA1 加密
|
||||
|
||||
/// <summary>
|
||||
/// 使用SHA1加密字符串。
|
||||
/// </summary>
|
||||
/// <param name="inputString">输入字符串。</param>
|
||||
/// <returns>加密后的字符串。(40个字符)</returns>
|
||||
public static string SHA1Encrypt(string inputString)
|
||||
{
|
||||
SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider();
|
||||
byte[] encryptedBytes = sha1.ComputeHash(Encoding.ASCII.GetBytes(inputString));
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < encryptedBytes.Length; i++)
|
||||
{
|
||||
sb.AppendFormat("{0:x2}", encryptedBytes[i]);
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region DES 加密/解密
|
||||
|
||||
private static byte[] key = Encoding.ASCII.GetBytes("uiertysd");
|
||||
private static byte[] iv = Encoding.ASCII.GetBytes("99008855");
|
||||
|
||||
/// <summary>
|
||||
/// DES加密。
|
||||
/// </summary>
|
||||
/// <param name="inputString">输入字符串。</param>
|
||||
/// <returns>加密后的字符串。</returns>
|
||||
public static string DESEncrypt(string inputString)
|
||||
{
|
||||
MemoryStream ms = null;
|
||||
CryptoStream cs = null;
|
||||
StreamWriter sw = null;
|
||||
|
||||
DESCryptoServiceProvider des = new DESCryptoServiceProvider();
|
||||
try
|
||||
{
|
||||
ms = new MemoryStream();
|
||||
cs = new CryptoStream(ms, des.CreateEncryptor(key, iv), CryptoStreamMode.Write);
|
||||
sw = new StreamWriter(cs);
|
||||
sw.Write(inputString);
|
||||
sw.Flush();
|
||||
cs.FlushFinalBlock();
|
||||
return Convert.ToBase64String(ms.GetBuffer(), 0, (int)ms.Length);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (sw != null) sw.Close();
|
||||
if (cs != null) cs.Close();
|
||||
if (ms != null) ms.Close();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// DES解密。
|
||||
/// </summary>
|
||||
/// <param name="inputString">输入字符串。</param>
|
||||
/// <returns>解密后的字符串。</returns>
|
||||
public static string DESDecrypt(string inputString)
|
||||
{
|
||||
MemoryStream ms = null;
|
||||
CryptoStream cs = null;
|
||||
StreamReader sr = null;
|
||||
|
||||
DESCryptoServiceProvider des = new DESCryptoServiceProvider();
|
||||
try
|
||||
{
|
||||
ms = new MemoryStream(Convert.FromBase64String(inputString));
|
||||
cs = new CryptoStream(ms, des.CreateDecryptor(key, iv), CryptoStreamMode.Read);
|
||||
sr = new StreamReader(cs);
|
||||
return sr.ReadToEnd();
|
||||
}
|
||||
catch
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (sr != null) sr.Close();
|
||||
if (cs != null) cs.Close();
|
||||
if (ms != null) ms.Close();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// MD5加密
|
||||
/// </summary>
|
||||
/// <param name="str">MD5加密前字符串</param>
|
||||
/// <returns>MD5加密后字符串</returns>
|
||||
public static string MD5Encrypt(string str)
|
||||
{
|
||||
str = string.Concat(md5Begin, str, md5End);
|
||||
MD5 md5 = new MD5CryptoServiceProvider();
|
||||
byte[] fromData = Encoding.Unicode.GetBytes(str);
|
||||
byte[] targetData = md5.ComputeHash(fromData);
|
||||
string md5String = string.Empty;
|
||||
foreach (var b in targetData)
|
||||
md5String += b.ToString("x2");
|
||||
return md5String;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Threading;
|
||||
|
||||
namespace JinYuan.Helper
|
||||
{
|
||||
/// <summary>
|
||||
/// 操作计时功能
|
||||
/// </summary>
|
||||
public class TimedOperation : IDisposable
|
||||
{
|
||||
private readonly Stopwatch _stopwatch;
|
||||
private readonly string _operationName;
|
||||
private readonly Action<long, string> _onCompleted;
|
||||
private bool _disposed = false;
|
||||
|
||||
public TimedOperation(string operationName, Action<long, string> onCompleted = null)
|
||||
{
|
||||
_stopwatch = Stopwatch.StartNew();
|
||||
_operationName = operationName;
|
||||
_onCompleted = onCompleted;
|
||||
}
|
||||
|
||||
public long ElapsedMilliseconds => _stopwatch.ElapsedMilliseconds;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (!_disposed)
|
||||
{
|
||||
_stopwatch.Stop();
|
||||
_onCompleted?.Invoke(_stopwatch.ElapsedMilliseconds, _operationName);
|
||||
_disposed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
|
||||
namespace JinYuan.Helper
|
||||
{
|
||||
/// <summary>
|
||||
/// 定时器重置时间间隔,定时器执行未超间隔则设置剩余时间后再次触发,超时则立即触发
|
||||
/// </summary>
|
||||
public class TimerReset : IDisposable
|
||||
{
|
||||
private Timer timer;
|
||||
private DateTime nextTime;
|
||||
|
||||
/// <summary>
|
||||
/// 使用using语句,在定时器TimerCallback中使用
|
||||
/// using语句块内为时间到时的执行代码,dispose计算使用的时间,来重设下次触发时间
|
||||
/// </summary>
|
||||
/// <param name="tim">定时器</param>
|
||||
/// <param name="ep">时间间隔</param>
|
||||
public TimerReset(Timer tim, int ep)
|
||||
{
|
||||
timer = tim;
|
||||
nextTime = DateTime.Now.AddMilliseconds(ep);//设置下次执行时间
|
||||
}
|
||||
public void Dispose()
|
||||
{
|
||||
//执行完后,重新设置定时器下次执行时间.
|
||||
TimeSpan timeout = nextTime.Subtract(DateTime.Now);
|
||||
if (timeout < TimeSpan.Zero)
|
||||
{
|
||||
timeout = TimeSpan.Zero;
|
||||
}
|
||||
|
||||
timer.Change(timeout, Timeout.InfiniteTimeSpan);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
|
||||
namespace JinYuan.Helper
|
||||
{
|
||||
public class TxtHelper
|
||||
{
|
||||
static ReaderWriterLockSlim sucessLogWriteLockSlim = new ReaderWriterLockSlim();
|
||||
|
||||
/// <summary>
|
||||
/// 写入TEXT文本
|
||||
/// </summary>
|
||||
/// <param name="fullName">文件名</param>
|
||||
/// <param name="content">内容</param>
|
||||
/// <returns>保存结果</returns>
|
||||
public static bool WriteTxt(string fullName, string content)
|
||||
{
|
||||
FileStream fs = null;
|
||||
StreamWriter sw = null;
|
||||
|
||||
try
|
||||
{
|
||||
string directory = fullName.Substring(0, fullName.LastIndexOf('\\'));
|
||||
if (!Directory.Exists(directory))
|
||||
{
|
||||
Directory.CreateDirectory(directory);
|
||||
}
|
||||
|
||||
sucessLogWriteLockSlim.EnterWriteLock();//加锁防止抢占
|
||||
if (!File.Exists(fullName))
|
||||
{
|
||||
fs = new FileStream(fullName, FileMode.Create, FileAccess.Write);
|
||||
sw = new StreamWriter(fs, Encoding.UTF8);
|
||||
}
|
||||
else
|
||||
{
|
||||
fs = new FileStream(fullName, FileMode.Append, FileAccess.Write);
|
||||
sw = new StreamWriter(fs, Encoding.UTF8);
|
||||
}
|
||||
|
||||
sw.WriteLine(content);
|
||||
|
||||
sw.Close();
|
||||
fs.Close();
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
sw?.Close();
|
||||
fs?.Close();
|
||||
|
||||
}
|
||||
finally
|
||||
{
|
||||
sucessLogWriteLockSlim.ExitWriteLock();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,386 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace JinYuan.Helper
|
||||
{
|
||||
public class TypeParse
|
||||
{
|
||||
/// <summary>
|
||||
/// 将数据库内取的值转成字符串
|
||||
/// </summary>
|
||||
/// <param name="obj"></param>
|
||||
/// <returns></returns>
|
||||
public static string Obj2Str(object obj)
|
||||
{
|
||||
return (obj != null) ? obj.ToString().Trim() : "";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 判断对象是否为Int32类型的数字
|
||||
/// </summary>
|
||||
/// <param name="Expression"></param>
|
||||
/// <returns></returns>
|
||||
public static bool IsNumeric(object expression)
|
||||
{
|
||||
if (expression != null)
|
||||
{
|
||||
return IsNumeric(expression.ToString());
|
||||
}
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 判断对象是否为Int32类型的数字
|
||||
/// </summary>
|
||||
/// <param name="Expression"></param>
|
||||
/// <returns></returns>
|
||||
public static bool IsNumeric(string expression)
|
||||
{
|
||||
if (expression != null)
|
||||
{
|
||||
string str = expression;
|
||||
if (str.Length > 0 && str.Length <= 11 && Regex.IsMatch(str, @"^[-]?[0-9]*[.]?[0-9]*$"))
|
||||
{
|
||||
if ((str.Length < 10) || (str.Length == 10 && str[0] == '1') || (str.Length == 11 && str[0] == '-' && str[1] == '1'))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否为Double类型
|
||||
/// </summary>
|
||||
/// <param name="expression"></param>
|
||||
/// <returns></returns>
|
||||
public static bool IsDouble(object expression)
|
||||
{
|
||||
if (expression != null)
|
||||
{
|
||||
return Regex.IsMatch(expression.ToString(), @"^([0-9])[0-9]*(\.\w*)?$");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// string型转换为bool型
|
||||
/// </summary>
|
||||
/// <param name="strValue">要转换的字符串</param>
|
||||
/// <param name="defValue">缺省值</param>
|
||||
/// <returns>转换后的bool类型结果</returns>
|
||||
public static bool StrToBool(object expression, bool defValue)
|
||||
{
|
||||
if (expression != null)
|
||||
{
|
||||
return StrToBool(expression.ToString(), defValue);
|
||||
}
|
||||
return defValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// string型转换为bool型
|
||||
/// </summary>
|
||||
/// <param name="strValue">要转换的字符串</param>
|
||||
/// <param name="defValue">缺省值</param>
|
||||
/// <returns>转换后的bool类型结果</returns>
|
||||
public static bool StrToBool(string expression, bool defValue)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (expression != null)
|
||||
{
|
||||
if (string.Compare(expression, "true", true) == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (string.Compare(expression, "false", true) == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return defValue;
|
||||
}
|
||||
return defValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将对象转换为Int32类型
|
||||
/// </summary>
|
||||
/// <param name="strValue">要转换的字符串</param>
|
||||
/// <param name="defValue">缺省值</param>
|
||||
/// <returns>转换后的int类型结果</returns>
|
||||
public static int StrToInt(object expression, int defValue)
|
||||
{
|
||||
if (expression != null)
|
||||
{
|
||||
return StrToInt(expression.ToString(), defValue);
|
||||
}
|
||||
return defValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将对象转换为Int32类型
|
||||
/// </summary>
|
||||
/// <param name="str">要转换的字符串</param>
|
||||
/// <param name="defValue">缺省值</param>
|
||||
/// <returns>转换后的int类型结果</returns>
|
||||
public static int StrToInt(string str, int defValue)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (str == null)
|
||||
return defValue;
|
||||
str = str.Trim();
|
||||
if (str.Length > 0 && str.Length <= 11 && Regex.IsMatch(str, @"^[-]?[0-9]*$"))
|
||||
{
|
||||
if ((str.Length < 10) || (str.Length == 10 && str[0] == '1') || (str.Length == 11 && str[0] == '-' && str[1] == '1'))
|
||||
{
|
||||
return Convert.ToInt32(str);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return defValue;
|
||||
}
|
||||
return defValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// string型转换为float型
|
||||
/// </summary>
|
||||
/// <param name="strValue">要转换的字符串</param>
|
||||
/// <param name="defValue">缺省值</param>
|
||||
/// <returns>转换后的int类型结果</returns>
|
||||
public static float StrToFloat(object strValue, float defValue)
|
||||
{
|
||||
if ((strValue == null))
|
||||
{
|
||||
return defValue;
|
||||
}
|
||||
return StrToFloat(strValue.ToString(), defValue);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// string型转换为float型
|
||||
/// </summary>
|
||||
/// <param name="strValue">要转换的字符串</param>
|
||||
/// <param name="defValue">缺省值</param>
|
||||
/// <returns>转换后的int类型结果</returns>
|
||||
public static float StrToFloat(string strValue, float defValue = 0)
|
||||
{
|
||||
|
||||
if (strValue == null)
|
||||
{
|
||||
return defValue;
|
||||
}
|
||||
else if (strValue.IndexOf(".") > 10)
|
||||
{
|
||||
return defValue;
|
||||
}
|
||||
float intValue = defValue;
|
||||
try
|
||||
{
|
||||
if (strValue != null)
|
||||
{
|
||||
bool IsFloat = Regex.IsMatch(strValue, @"^([-]|[0-9])[0-9]*(\.\w*)?$");
|
||||
if (IsFloat)
|
||||
{
|
||||
intValue = Convert.ToSingle(strValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return defValue;
|
||||
}
|
||||
return intValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// object型转换为decimal型
|
||||
/// </summary>
|
||||
/// <param name="strValue">要转换的字符串</param>
|
||||
/// <param name="defValue">缺省值</param>
|
||||
/// <returns>转换后的decimal类型结果</returns>
|
||||
public static decimal StrToDecimal(object strValue, decimal defValue = 0)
|
||||
{
|
||||
if ((strValue == null))
|
||||
{
|
||||
return defValue;
|
||||
}
|
||||
|
||||
return StrToDecimal(strValue.ToString(), defValue);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// string型转换为decimal型
|
||||
/// </summary>
|
||||
/// <param name="strValue">要转换的字符串</param>
|
||||
/// <param name="defValue">缺省值</param>
|
||||
/// <returns>转换后的decimal类型结果</returns>
|
||||
public static decimal StrToDecimal(string strValue, decimal defValue)
|
||||
{
|
||||
if (strValue == null || strValue == "")
|
||||
{
|
||||
return defValue;
|
||||
}
|
||||
|
||||
decimal intValue = defValue;
|
||||
try
|
||||
{
|
||||
if (strValue != null)
|
||||
{
|
||||
bool IsDecimal = Regex.IsMatch(strValue, @"^([-]|[0-9])[0-9]*(\.\w*)?$");
|
||||
if (IsDecimal)
|
||||
{
|
||||
intValue = Convert.ToDecimal(strValue);
|
||||
//int precision = 15; // 假设数据库中的精度为15
|
||||
//int scale = 3; // 假设数据库中的小数位数为3
|
||||
// 检查valueToInsert是否超出精确度和小数位数
|
||||
if (Math.Floor(intValue * (decimal)Math.Pow(18, 3)) > (decimal)Math.Pow(18, 15 - 3))
|
||||
{
|
||||
intValue = -9999;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return defValue;
|
||||
}
|
||||
return intValue;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 判断给定的字符串数组(strNumber)中的数据是不是都为数值型
|
||||
/// </summary>
|
||||
/// <param name="strNumber">要确认的字符串数组</param>
|
||||
/// <returns>是则返加true 不是则返回 false</returns>
|
||||
public static bool IsNumericArray(string[] strNumber)
|
||||
{
|
||||
if (strNumber == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (strNumber.Length < 1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
foreach (string id in strNumber)
|
||||
{
|
||||
if (!IsNumeric(id))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将数据库内取的值转成日期
|
||||
/// </summary>
|
||||
/// <param name="obj"></param>
|
||||
/// <returns></returns>
|
||||
public static DateTime Obj2DateTime(object obj)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (obj != null)
|
||||
{
|
||||
return DateTime.Parse(obj.ToString());
|
||||
}
|
||||
else
|
||||
{
|
||||
return Convert.ToDateTime("1900-1-1 00:00:00");
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
return Convert.ToDateTime("1900-1-1 00:00:00");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 判断字符串是否是yyyy-mm-dd字符串
|
||||
/// </summary>
|
||||
/// <param name="str">待判断字符串</param>
|
||||
/// <returns>判断结果</returns>
|
||||
public static bool IsDateString(string str)
|
||||
{
|
||||
bool formatPassed = Regex.IsMatch(str, @"(\d{4})-(\d{1,2})-(\d{1,2})");
|
||||
|
||||
if (!formatPassed)
|
||||
return false;
|
||||
|
||||
DateTime date;
|
||||
|
||||
return DateTime.TryParse(str, out date);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 判断字符串是否是 HH:mm 或者 HH:mm:ss 格式
|
||||
/// </summary>
|
||||
/// <param name="str">待判断字符串</param>
|
||||
/// <param name="includeSecond">是否包含秒</param>
|
||||
/// <returns>判断结果</returns>
|
||||
public static bool IsTimeString(string str, bool includeSecond)
|
||||
{
|
||||
string patten = @"([0-1][0-9]|2[0-3]):([0-5][0-9])";
|
||||
|
||||
if (includeSecond)
|
||||
patten = @"([0-1][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])";
|
||||
|
||||
bool formatPassed = Regex.IsMatch(str, patten);
|
||||
|
||||
return formatPassed;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 日期转换成unix时间戳
|
||||
/// </summary>
|
||||
/// <param name="dateTime"></param>
|
||||
/// <returns></returns>
|
||||
public static long DateTimeToUnixTimestamp(DateTime dateTime)
|
||||
{
|
||||
DateTime start = new DateTime(1970, 1, 1, 0, 0, 0, dateTime.Kind);
|
||||
return Convert.ToInt64((dateTime - start).TotalSeconds);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// unix时间戳转换成日期
|
||||
/// </summary>
|
||||
/// <param name="timeStamp">时间戳(秒)</param>
|
||||
/// <returns></returns>
|
||||
public static DateTime UnixTimestampToDateTime(DateTime target, long timeStamp)
|
||||
{
|
||||
DateTime start = new DateTime(1970, 1, 1, 0, 0, 0, target.Kind);
|
||||
return start.AddSeconds(timeStamp);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 日期转换成unix时间戳(13位精确到毫秒)
|
||||
/// </summary>
|
||||
/// <param name="dateTime"></param>
|
||||
/// <returns></returns>
|
||||
public static long DateTimeToUnixTimestamp_Ms(DateTime dateTime)
|
||||
{
|
||||
DateTime start = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
|
||||
|
||||
return Convert.ToInt64(dateTime.Subtract(start).TotalMilliseconds);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,230 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Runtime.Serialization.Formatters.Binary;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace JinYuan.Helper
|
||||
{
|
||||
/// <summary>
|
||||
/// 序列化辅助类
|
||||
/// </summary>
|
||||
public class XmlHelper
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// 二进制方式的序列化
|
||||
/// </summary>
|
||||
/// <typeparam name="T">类型</typeparam>
|
||||
/// <param name="obj">序列化对象</param>
|
||||
/// <returns>序列化后的内存</returns>
|
||||
public static Stream BinarySerialize<T>(T obj)
|
||||
{
|
||||
MemoryStream serMs = new MemoryStream();
|
||||
IFormatter iBinaryFormatter = new BinaryFormatter();
|
||||
iBinaryFormatter.Serialize(serMs, obj);
|
||||
if (serMs.Length > 0)
|
||||
serMs.Position = 0;
|
||||
return serMs;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 二进制方式的反序列化
|
||||
/// </summary>
|
||||
/// <typeparam name="T">类型</typeparam>
|
||||
/// <param name="ms">待序列化的内存</param>
|
||||
/// <returns>反序列化后的对象</returns>
|
||||
public static T BinaryDeserializer<T>(Stream ms) where T : class
|
||||
{
|
||||
T res = default(T);
|
||||
if (ms.Length > 0)
|
||||
ms.Position = 0;
|
||||
IFormatter iBinaryFormatter = new BinaryFormatter();
|
||||
res = iBinaryFormatter.Deserialize(ms) as T;
|
||||
return res;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Xml方式的序列化
|
||||
/// </summary>
|
||||
/// <typeparam name="T">类型</typeparam>
|
||||
/// <param name="obj">序列化对象</param>
|
||||
/// <returns>序列化后的内存</returns>
|
||||
public static Stream XmlSerialize<T>(T obj)
|
||||
{
|
||||
MemoryStream serMs = new MemoryStream();
|
||||
XmlSerializer ser = new XmlSerializer(obj.GetType());
|
||||
try
|
||||
{
|
||||
ser.Serialize(serMs, obj);
|
||||
if (serMs.Length > 0)
|
||||
serMs.Position = 0;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
//LogHelper.Current.WriteEx(string.Format("序列化对象异常:{0}", obj.ToString()), ex);
|
||||
return null;
|
||||
}
|
||||
|
||||
return serMs;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Xml方式的序列化
|
||||
/// </summary>
|
||||
/// <param name="obj"></param>
|
||||
/// <returns></returns>
|
||||
public static Stream XmlSerializeObj(object obj)
|
||||
{
|
||||
MemoryStream serMs = new MemoryStream();
|
||||
XmlSerializer ser = new XmlSerializer(obj.GetType());
|
||||
ser.Serialize(serMs, obj);
|
||||
if (serMs.Length > 0)
|
||||
serMs.Position = 0;
|
||||
return serMs;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Xml方式的反序列化
|
||||
/// </summary>
|
||||
/// <typeparam name="T">类型</typeparam>
|
||||
/// <param name="ms">待序列化的内存</param>
|
||||
/// <returns>反序列化后的对象</returns>
|
||||
public static T XmlDeserializer<T>(Stream ms) where T : class
|
||||
{
|
||||
T res = default(T);
|
||||
if (ms.Length > 0)
|
||||
ms.Position = 0;
|
||||
XmlSerializer ser = new XmlSerializer(typeof(T));
|
||||
res = ser.Deserialize(ms) as T;
|
||||
return res;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将List集合保存成XML文档
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="lstT"></param>
|
||||
/// <param name="filePath"></param>
|
||||
public static bool SaveListToXML<T>(List<T> lstT, string filePath)
|
||||
{
|
||||
try
|
||||
{
|
||||
FileInfo fInfo = new FileInfo(filePath);
|
||||
if (!fInfo.Directory.Exists)
|
||||
{
|
||||
fInfo.Directory.Create();
|
||||
}
|
||||
Stream stream = XmlSerialize(lstT);
|
||||
if (stream != null)
|
||||
{
|
||||
byte[] bs = StreamIOHelper.ReadStreamBytes(stream);
|
||||
using (FileStream fs = new FileStream(filePath, FileMode.Create))
|
||||
{
|
||||
fs.Write(bs, 0, bs.Length);
|
||||
}
|
||||
stream.Close();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
//LogHelper.Current.WriteEx("将List保存成XML文档发生异常", ex, EnumLogType.Error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 读取XML信息成List集合
|
||||
/// </summary>
|
||||
public static List<T> ReadXMLToList<T>(string filePath)
|
||||
{
|
||||
try
|
||||
{
|
||||
FileInfo fInfo = new FileInfo(filePath);
|
||||
if (!fInfo.Directory.Exists)
|
||||
{
|
||||
fInfo.Directory.Create();
|
||||
}
|
||||
using (FileStream fs = new FileStream(filePath, FileMode.Open))
|
||||
{
|
||||
var crList = XmlDeserializer<List<T>>(fs);
|
||||
return crList;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
//LogHelper.Current.WriteEx("读取XML转换成List异常", ex, EnumLogType.Error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将类的实例保存成XML文档
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="t"></param>
|
||||
/// <param name="filePath"></param>
|
||||
/// <returns></returns>
|
||||
public static bool SaveModelToXML<T>(T t, string filePath) where T : class
|
||||
{
|
||||
try
|
||||
{
|
||||
FileInfo fInfo = new FileInfo(filePath);
|
||||
if (!fInfo.Directory.Exists)
|
||||
{
|
||||
fInfo.Directory.Create();
|
||||
}
|
||||
using (FileStream fs = new FileStream(filePath, FileMode.Create))
|
||||
{
|
||||
using (Stream stream = XmlSerialize<T>(t))
|
||||
{
|
||||
byte[] bs = StreamIOHelper.ReadStreamBytes(stream);
|
||||
fs.Write(bs, 0, bs.Length);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
//LogHelper.Current.WriteEx("将Class保存成XML文档发生异常", ex, EnumLogType.Error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将XML文档中数据读取到类的实例中
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="filePath"></param>
|
||||
/// <returns></returns>
|
||||
public static T ReadXMLToModel<T>(string filePath) where T : class
|
||||
{
|
||||
try
|
||||
{
|
||||
FileInfo fInfo = new FileInfo(filePath);
|
||||
if (!fInfo.Directory.Exists)
|
||||
{
|
||||
fInfo.Directory.Create();
|
||||
}
|
||||
using (FileStream fs = new FileStream(filePath, FileMode.Open))
|
||||
{
|
||||
T model = XmlDeserializer<T>(fs);
|
||||
return model;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
//LogHelper.Current.WriteEx("读取XML转换成实例异常", ex, EnumLogType.Error);
|
||||
return default(T);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<runtime>
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Memory" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.0.1.2" newVersion="4.0.1.2" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Numerics.Vectors" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.1.4.0" newVersion="4.1.4.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Buffers" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Text.Encoding.CodePages" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Security.Cryptography.Xml" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-6.0.0.1" newVersion="6.0.0.1" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-13.0.0.0" newVersion="13.0.0.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Microsoft.Bcl.AsyncInterfaces" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-9.0.0.0" newVersion="9.0.0.0" />
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
</runtime>
|
||||
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8" /></startup></configuration>
|
||||
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="BouncyCastle.Cryptography" version="2.2.1" targetFramework="net472" />
|
||||
<package id="CsvHelper" version="33.0.1" targetFramework="net48" />
|
||||
<package id="Enums.NET" version="4.0.1" targetFramework="net472" />
|
||||
<package id="MathNet.Numerics.Signed" version="4.15.0" targetFramework="net472" />
|
||||
<package id="Microsoft.Bcl.AsyncInterfaces" version="9.0.0" targetFramework="net472" />
|
||||
<package id="Microsoft.Bcl.HashCode" version="1.1.1" targetFramework="net472" />
|
||||
<package id="Microsoft.CSharp" version="4.7.0" targetFramework="net472" />
|
||||
<package id="Microsoft.IO.RecyclableMemoryStream" version="2.3.2" targetFramework="net472" />
|
||||
<package id="Newtonsoft.Json" version="13.0.3" targetFramework="net472" />
|
||||
<package id="NLog" version="6.0.2" targetFramework="net48" />
|
||||
<package id="SharpZipLib" version="1.3.3" targetFramework="net472" />
|
||||
<package id="SixLabors.Fonts" version="1.0.0" targetFramework="net472" />
|
||||
<package id="SixLabors.ImageSharp" version="3.1.6" targetFramework="net472" />
|
||||
<package id="System.Buffers" version="4.5.1" targetFramework="net472" />
|
||||
<package id="System.Configuration.ConfigurationManager" version="8.0.0" targetFramework="net472" />
|
||||
<package id="System.Memory" version="4.5.5" targetFramework="net472" />
|
||||
<package id="System.Numerics.Vectors" version="4.5.0" targetFramework="net472" />
|
||||
<package id="System.Runtime.CompilerServices.Unsafe" version="6.0.0" targetFramework="net472" />
|
||||
<package id="System.Security.AccessControl" version="6.0.0" targetFramework="net472" />
|
||||
<package id="System.Security.Cryptography.Xml" version="6.0.1" targetFramework="net472" />
|
||||
<package id="System.Security.Permissions" version="6.0.0" targetFramework="net472" />
|
||||
<package id="System.Security.Principal.Windows" version="5.0.0" targetFramework="net472" />
|
||||
<package id="System.Text.Encoding.CodePages" version="6.0.0" targetFramework="net472" />
|
||||
<package id="System.Threading.Tasks.Extensions" version="4.5.4" targetFramework="net472" />
|
||||
</packages>
|
||||
Reference in New Issue
Block a user