添加项目文件。

This commit is contained in:
xyy
2026-03-11 15:21:27 +08:00
parent c0e2ea6482
commit 34083df6de
66 changed files with 8066 additions and 0 deletions

12
Data/BaseWindow.xaml Normal file
View File

@@ -0,0 +1,12 @@
<Window x:Class="自救器呼吸器综合检验仪.Data.BaseWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:自救器呼吸器综合检验仪.Data"
mc:Ignorable="d"
Title="BaseWindow" Height="450" Width="800">
<Grid>
</Grid>
</Window>

34
Data/BaseWindow.xaml.cs Normal file
View File

@@ -0,0 +1,34 @@
using Modbus.Device;
using System;
using System.Net.Sockets;
using System.Windows;
namespace .Data
{
public partial class BaseWindow : Window
{
// 共享资源(从管理器获取,不自己创建)
protected TcpClient _tcpClient => ModbusResourceManager.Instance.TcpClient;
protected IModbusMaster _modbusMaster => ModbusResourceManager.Instance.ModbusMaster;
protected System.Timers.Timer _readTimer { get; set; } = new System.Timers.Timer();
// 窗口关闭时仅停止定时器,不释放资源(资源由管理器统一释放)
protected override void OnClosed(EventArgs e)
{
base.OnClosed(e);
_readTimer?.Stop();
_readTimer?.Dispose();
}
// 检查资源是否可用(避免空引用报错)
protected bool CheckResourceAvailable()
{
if (_tcpClient == null || !_tcpClient.Connected || _modbusMaster == null)
{
MessageBox.Show("TCP连接已断开请重新初始化连接", "提示");
return false;
}
return true;
}
}
}

28
Data/BoolSign.cs Normal file
View File

@@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace .Data
{
public class BoolSignal
{
private bool _previousValue;
public event Action OnRisingEdge;
// bool value = true;
public bool Value { get; set; }
public void CheckRisingEdge()
{
if (Value && !_previousValue)
{
OnRisingEdge?.Invoke();
}
_previousValue = Value;
}
}
}

74
Data/DataChange.cs Normal file
View File

@@ -0,0 +1,74 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace
{
public class DataChange
{
/// <summary>
/// ushort转为float类型
/// </summary>
/// <param name="P1"></param>
/// <param name="P2"></param>
/// <returns>float型数据</returns>
public float UshortToFloat(ushort P1, ushort P2)
{
int intSign, intSignRest, intExponent, intExponentRest;
float faResult, faDigit;
intSign = P1 / 32768;
intSignRest = P1 % 32768;
intExponent = intSignRest / 128;
intExponentRest = intSignRest % 128;
faDigit = (float)(intExponentRest * 65536 + P2) / 8388608;
faResult = (float)Math.Pow(-1, intSign) * (float)Math.Pow(2, intExponent - 127) * (faDigit + 1);
return faResult;
}
/// <summary>
/// ushort转为int类型
/// </summary>
/// <param name="u1"></param>
/// <param name="u2"></param>
/// <returns>返回int型数据</returns>
public int UshortToInt1(ushort u1, ushort u2)
{
ushort[] maidong = new ushort[2] { u1, u2 };
byte[] bytes = new byte[maidong.Length * 2];
Buffer.BlockCopy(maidong, 0, bytes, 0, bytes.Length);
int result = BitConverter.ToInt32(bytes, 0);
// 将字节数组转换为32位无符号整数
return result;
}
/// <summary>
/// Float转为Ushort数组发送
/// </summary>
/// <param name="value"></param>
/// <returns>返回ushort数组</returns>
public ushort[] SplitFloatToUShortArray(float value)
{
byte[] floatBytes = BitConverter.GetBytes(value);
ushort[] ushortArray = new ushort[floatBytes.Length / 2];
for (int i = 0, j = 0; i < floatBytes.Length; i += 2, j++)
{
ushortArray[j] = BitConverter.ToUInt16(floatBytes, i);
}
return ushortArray;
}
/// <summary>
/// Int转为ushort数组发送
/// </summary>
/// <param name="res"></param>
/// <returns>返回ushort数组</returns>
public ushort[] intToushorts(int res)
{
ushort ust1 = (ushort)(res >> 16);
ushort ust2 = (ushort)res;
return new ushort[] { ust2, ust1 };
}
}
}

151
Data/ExperData.cs Normal file
View File

@@ -0,0 +1,151 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace
{
public class ExperData: INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
#region
static string experName = "";
/// <summary>
/// 实验人员
/// </summary>
public string ExperName { get { return experName; } set { experName = value; } }
static string experDate = "";
/// <summary>
/// 实验日期
/// </summary>
public string ExperDate { get { return experDate; } set { experDate = value; } }
static string experNum = "";
/// <summary>
/// 实验编号
/// </summary>
public string ExperNum { get { return experNum; } set { experNum = value; } }
static string experType = " ";
/// <summary>
/// 实验种类
/// </summary>
public string ExperType { get { return experType; } set { experType = value; } }
static float experMaskType = 2.0f;
/// <summary>
/// 口罩类型
/// </summary>
public float ExperMaskType { get { return experMaskType; } set { experMaskType = value; } }
/// <summary>
/// 面罩类型
/// </summary>
static string maskType;
public string MaskType { get { return maskType; } set { maskType = value; } }
static float _yangPinXiShu = 1.0f;
/// <summary>
/// 样品系数
/// </summary>
public float YangPinXiShu { get { return _yangPinXiShu; } set { _yangPinXiShu = value; } }
static string _testStatus = "";
/// <summary>
/// 实验状态
/// </summary>
public string TestStatus { get { return _testStatus; } set { _testStatus = value; } }
static float benDiNongDu = 0.00f;
/// <summary>
/// 本底浓度
/// </summary>
public float BenDiNongDu { get { return benDiNongDu; } set { benDiNongDu = value; } }
static float huanJingWenDu = 0.00f;
/// <summary>
/// 环境温度
/// </summary>
public float HuanJingWenDu { get { return huanJingWenDu; } set { huanJingWenDu = value; } }
static float huanJingShiDu = 0.00f;
/// <summary>
/// 环境湿度
/// </summary>
public float HuanJingShiDu { get { return huanJingShiDu; } set { huanJingShiDu = value; } }
static float o2NongDu = 0.00f;
/// <summary>
/// 环境氧浓度
/// </summary>
public float O2NongDu { get { return o2NongDu; } set { o2NongDu = value; } }
static float cO2NongDu = 0.00f;
/// <summary>
/// 环境C02浓度
/// </summary>
public float CO2NongDu_Indoor { get { return cO2NongDu; } set { cO2NongDu = value; } }
static float inDoor_TSINongDu = 0.00f;
/// <summary>
/// 环境气溶胶浓度
/// </summary>
public float InDoor_TSINongDu { get { return inDoor_TSINongDu; } set { inDoor_TSINongDu = value; } }
static float mask_CO2NongDu = 0.00f;
/// <summary>
/// 口罩内CO2浓度
/// </summary>
public float Mask_CO2NongDu { get { return mask_CO2NongDu; } set { mask_CO2NongDu = value; } }
static float mask_TSINongDu = 0.00f;
/// <summary>
/// 口罩内气溶胶浓度
/// </summary>
public float Mask_TSINongDu { get { return mask_TSINongDu; } set { mask_TSINongDu = value; } }
static float _liuLiang = 0.00f;
/// <summary>
/// 流量
/// </summary>
public float LiuLiang { get { return _liuLiang; } set { _liuLiang = value; } }
static float _xieloulv = 0.00f;
/// <summary>
/// 泄露率
/// </summary>
public float XieLouLv { get { return _xieloulv; } set { _xieloulv = value; } }
#endregion
#region
//单独动作泄露率
public float CumulativeLeakageRate(List<float> inDoor_Tsi,List<float> out_Door_Tsi,float benDiNongdu,float xiShu)
{
if (inDoor_Tsi.Count != 0 && out_Door_Tsi.Count != 0&& benDiNongdu!=0.0f)
{
//计算室内Tsi浓度平均值
float inDoor_Tsi_Avg = inDoor_Tsi.Average();
//计算室外Tsi浓度平均值
float out_Door_Tsi_Avg = out_Door_Tsi.Average();
//计算泄露率
float leakageRate = ((out_Door_Tsi_Avg - inDoor_Tsi_Avg) * xiShu) / benDiNongdu;
return leakageRate;
}
else
{
return 0.00f;
}
}
//全部动作泄露率
public float CumulativeLeakageRate_All(List<float> All_Cv_List)
{
return All_Cv_List.Average();
}
#endregion
}
}

185
Data/Function.cs Normal file
View File

@@ -0,0 +1,185 @@
using Modbus.Device;
using Modbus;
using Sunny.UI;
using System;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
namespace
{
public class Function
{
ModbusMaster master;
IModbusMaster modbusMaster;
DataChange dc = new DataChange();
public enum ButtonType
{
,
,
,
}
public enum DataType
{
,
}
public Function(ModbusMaster master_in)
{
this.master = master_in;
}
public Function(IModbusMaster modbusMaster)
{
this.modbusMaster = modbusMaster;
}
public void BtnClickFunction(ButtonType buttonType, ushort address)
{
try
{
switch (buttonType)
{
case ButtonType.:
master.WriteSingleCoil(1, address, true);
Thread.Sleep(100);
master.WriteSingleCoil(1, address, false);
Thread.Sleep(100);
break;
case ButtonType.:
if (master.ReadCoils(1, address, 1)[0])
{
master.WriteSingleCoil(1, address, false); Thread.Sleep(100);
}
else
{ master.WriteSingleCoil(1, address, true); Thread.Sleep(100); }
break;
case ButtonType.:
master.WriteSingleCoil(1, address, true);
Thread.Sleep(100);
break;
case ButtonType.:
master.WriteSingleCoil(1, address, false);
Thread.Sleep(100);
break;
default:
break;
}
}
catch (Exception ex)
{
}
}
public void BtnClickFunctionForNew(ButtonType buttonType, ushort address)
{
try
{
switch (buttonType)
{
case ButtonType.:
modbusMaster.WriteSingleCoil(1, address, true);
Thread.Sleep(100);
modbusMaster.WriteSingleCoil(1, address, false);
Thread.Sleep(100);
break;
case ButtonType.:
if (modbusMaster.ReadCoils(1, address, 1)[0])
{
modbusMaster.WriteSingleCoil(1, address, false); Thread.Sleep(100);
}
else
{ modbusMaster.WriteSingleCoil(1, address, true); Thread.Sleep(100); }
break;
case ButtonType.:
modbusMaster.WriteSingleCoil(1, address, true);
Thread.Sleep(100);
break;
case ButtonType.:
modbusMaster.WriteSingleCoil(1, address, false);
Thread.Sleep(100);
break;
default:
break;
}
}
catch (Exception ex)
{
}
}
public void WriteToPLC(string inPutValue, ushort address, DataType dataType)
{
try
{
switch (dataType)
{
case DataType.:
double value = inPutValue.ToDouble();
if (UIInputDialog.ShowInputDoubleDialog(ref value, UIStyle.Inherited, desc: "请输入值", showMask: false))
{
master.WriteMultipleRegisters(1, address, dc.SplitFloatToUShortArray((float)value));
}
break;
case DataType.:
int value_int = inPutValue.ToInt();
if (UIInputDialog.ShowInputIntegerDialog(ref value_int, UIStyle.Inherited, desc: "请输入数据:"))
{
master.WriteMultipleRegisters(1, address, dc.intToushorts(value_int));
}
break;
default:
break;
}
}
catch (Exception ex)
{
MessageBox.Show("操作失败!" + "\n" + "\n" + ex.Message, "错误");
}
}
public void WriteToPLCForNew(string inPutValue, ushort address, DataType dataType)
{
try
{
//KeyboardHelper.ShowSoftKeyboard();
switch (dataType)
{
case DataType.:
double value = inPutValue.ToDouble();
if (UIInputDialog.ShowInputDoubleDialog(ref value, UIStyle.Inherited, desc: "请输入值", showMask: false))
{
modbusMaster.WriteMultipleRegisters(1, address, dc.SplitFloatToUShortArray((float)value));
}
break;
case DataType.:
int value_int = inPutValue.ToInt();
if (UIInputDialog.ShowInputIntegerDialog(ref value_int, UIStyle.Inherited, desc: "请输入数据:"))
{
modbusMaster.WriteMultipleRegisters(1, address, dc.intToushorts(value_int));
}
break;
default:
break;
}
//KeyboardHelper.HideSoftKeyboard();
}
catch (Exception ex)
{
MessageBox.Show("操作失败!" + "\n" + "\n" + ex.Message, "错误");
}
}
}
}

21
Data/LoginData.cs Normal file
View File

@@ -0,0 +1,21 @@
namespace
{
public class LoginData
{
static string _userName = "";
public string UserName
{
get { return _userName; }
set { _userName = value; }
}
//登陆权限
static int _userPower = 0;//0为普通用户1为管理员
public int UserPower
{
get { return _userPower; }
set { _userPower = value; }
}
}
}

View File

@@ -0,0 +1,76 @@
using Modbus.Device;
using System;
using System.Net.Http;
using System.Net.Sockets;
namespace .Data
{
// 单例模式:全局唯一资源管理器
public class ModbusResourceManager
{
// 私有构造函数禁止外部new
private ModbusResourceManager() { }
// 唯一实例
private static readonly Lazy<ModbusResourceManager> _instance = new Lazy<ModbusResourceManager>(() => new ModbusResourceManager());
public static ModbusResourceManager Instance => _instance.Value;
// 共享资源
public TcpClient TcpClient { get; private set; }
public IModbusMaster ModbusMaster { get; private set; }
// 初始化资源在程序启动时调用如MainWindow加载时
public bool Init(string ip, int port)
{
try
{
// 先释放旧资源
ReleaseResource();
// 创建新连接
TcpClient = new TcpClient();
TcpClient.Connect(ip, port);
ModbusMaster = ModbusIpMaster.CreateIp(TcpClient);
return true;
}
catch (Exception ex)
{
Console.WriteLine($"资源初始化失败:{ex.Message}");
ReleaseResource();
return false;
}
}
// 在 ModbusResourceManager 类中添加
public void Dispose()
{
try
{
ModbusMaster?.Dispose();
TcpClient?.Close();
}
catch
{
// 忽略清理时的异常
}
}
// 释放资源(统一释放,避免重复关闭)
public void ReleaseResource()
{
try
{
ModbusMaster?.Dispose();
ModbusMaster = null;
//if (TcpClient?.Connected ?? false)
//{
// TcpClient.Close();
//}
TcpClient?.Dispose();
TcpClient = null;
}
catch { }
}
}
}

13
Data/PLC_Data.cs Normal file
View File

@@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace .Data
{
internal class PLC_Data
{
}
}

71
Data/keyboard.cs Normal file
View File

@@ -0,0 +1,71 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Security.Principal;
using System.Windows;
public class KeyboardHelper
{
public static void ShowSoftKeyboard()
{
if (!IsRunAsAdmin())
{
RestartAsAdmin();
return;
}
// 替换原有的 Process.Start 代码
string oskPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.System), "osk.exe");
if (File.Exists(oskPath))
{
Process.Start(new ProcessStartInfo
{
FileName = oskPath,
UseShellExecute = true
});
}
else
{
//MessageBox.Show("未找到屏幕键盘程序osk.exe可能系统文件缺失或非Windows系统。", "错误");
}
}
public static void HideSoftKeyboard()
{
try
{
Process.Start("cmd.exe", "/C taskkill /IM osk.exe /F");
}
catch (Exception ex)
{
Console.WriteLine("Error: " + ex.Message);
}
}
private static bool IsRunAsAdmin()
{
WindowsIdentity identity = WindowsIdentity.GetCurrent();
WindowsPrincipal principal = new WindowsPrincipal(identity);
return principal.IsInRole(WindowsBuiltInRole.Administrator);
}
private static void RestartAsAdmin()
{
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.UseShellExecute = true;
startInfo.WorkingDirectory = Environment.CurrentDirectory;
startInfo.FileName = Process.GetCurrentProcess().MainModule.FileName;
startInfo.Verb = "runas";
try
{
Process.Start(startInfo);
}
catch (Exception ex)
{
Console.WriteLine("Error: " + ex.Message);
}
Environment.Exit(0);
}
}