mirror of
https://github.com/jie65535/SphygmomanometerTester.git
synced 2024-07-27 19:09:00 +08:00
添加项目文件。
This commit is contained in:
parent
5cd2a3329a
commit
3211d1431b
25
SphygmomanometerTester.sln
Normal file
25
SphygmomanometerTester.sln
Normal file
@ -0,0 +1,25 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.3.32929.385
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SphygmomanometerTester", "SphygmomanometerTester\SphygmomanometerTester.csproj", "{8C5FDDD2-5EC5-4AD7-AB24-F87665872A95}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{8C5FDDD2-5EC5-4AD7-AB24-F87665872A95}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{8C5FDDD2-5EC5-4AD7-AB24-F87665872A95}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{8C5FDDD2-5EC5-4AD7-AB24-F87665872A95}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{8C5FDDD2-5EC5-4AD7-AB24-F87665872A95}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {5E052F27-92AD-454F-9611-88871647070C}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
6
SphygmomanometerTester/App.config
Normal file
6
SphygmomanometerTester/App.config
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<configuration>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8" />
|
||||
</startup>
|
||||
</configuration>
|
553
SphygmomanometerTester/FormMain.Designer.cs
generated
Normal file
553
SphygmomanometerTester/FormMain.Designer.cs
generated
Normal file
@ -0,0 +1,553 @@
|
||||
namespace SphygmomanometerTester
|
||||
{
|
||||
partial class FormMain
|
||||
{
|
||||
/// <summary>
|
||||
/// 必需的设计器变量。
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// 清理所有正在使用的资源。
|
||||
/// </summary>
|
||||
/// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Windows 窗体设计器生成的代码
|
||||
|
||||
/// <summary>
|
||||
/// 设计器支持所需的方法 - 不要修改
|
||||
/// 使用代码编辑器修改此方法的内容。
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.GrpSerialPort = new System.Windows.Forms.GroupBox();
|
||||
this.CmbSerialPortName = new System.Windows.Forms.ComboBox();
|
||||
this.LblPortName = new System.Windows.Forms.Label();
|
||||
this.BtnUpdatePortNames = new System.Windows.Forms.Button();
|
||||
this.BtnOpenPort = new System.Windows.Forms.Button();
|
||||
this.BtnClosePort = new System.Windows.Forms.Button();
|
||||
this.GrpSphygmomanometer = new System.Windows.Forms.GroupBox();
|
||||
this.BtnConnect = new System.Windows.Forms.Button();
|
||||
this.BtnStartMeasure = new System.Windows.Forms.Button();
|
||||
this.BtnStopMeasure = new System.Windows.Forms.Button();
|
||||
this.LblSystolicPressure = new System.Windows.Forms.Label();
|
||||
this.GrpMeasureResult = new System.Windows.Forms.GroupBox();
|
||||
this.LblSystolicPressureValue = new System.Windows.Forms.Label();
|
||||
this.LblDiastolicPressure = new System.Windows.Forms.Label();
|
||||
this.LblDiastolicPressureValue = new System.Windows.Forms.Label();
|
||||
this.LblPulse = new System.Windows.Forms.Label();
|
||||
this.LblPulseValue = new System.Windows.Forms.Label();
|
||||
this.GrpPressure = new System.Windows.Forms.GroupBox();
|
||||
this.LblPressureValue = new System.Windows.Forms.Label();
|
||||
this.LblInterval = new System.Windows.Forms.Label();
|
||||
this.NudInterval = new System.Windows.Forms.NumericUpDown();
|
||||
this.ChkLoopTest = new System.Windows.Forms.CheckBox();
|
||||
this.LblLoopTestTip = new System.Windows.Forms.Label();
|
||||
this.PrbIntervalProgress = new System.Windows.Forms.ProgressBar();
|
||||
this.GrpLog = new System.Windows.Forms.GroupBox();
|
||||
this.TxtLog = new System.Windows.Forms.TextBox();
|
||||
this.GrpStat = new System.Windows.Forms.GroupBox();
|
||||
this.BtnResetStat = new System.Windows.Forms.Button();
|
||||
this.FlpStatLabels = new System.Windows.Forms.FlowLayoutPanel();
|
||||
this.LblTestStat = new System.Windows.Forms.Label();
|
||||
this.LblTestSuccessCount = new System.Windows.Forms.Label();
|
||||
this.LblTestStatSeparator1 = new System.Windows.Forms.Label();
|
||||
this.LblTestFailedCount = new System.Windows.Forms.Label();
|
||||
this.LblTestStatSeparator2 = new System.Windows.Forms.Label();
|
||||
this.LblTestCount = new System.Windows.Forms.Label();
|
||||
this.GrpSerialPort.SuspendLayout();
|
||||
this.GrpSphygmomanometer.SuspendLayout();
|
||||
this.GrpMeasureResult.SuspendLayout();
|
||||
this.GrpPressure.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.NudInterval)).BeginInit();
|
||||
this.GrpLog.SuspendLayout();
|
||||
this.GrpStat.SuspendLayout();
|
||||
this.FlpStatLabels.SuspendLayout();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// GrpSerialPort
|
||||
//
|
||||
this.GrpSerialPort.Controls.Add(this.BtnClosePort);
|
||||
this.GrpSerialPort.Controls.Add(this.BtnOpenPort);
|
||||
this.GrpSerialPort.Controls.Add(this.BtnUpdatePortNames);
|
||||
this.GrpSerialPort.Controls.Add(this.LblPortName);
|
||||
this.GrpSerialPort.Controls.Add(this.CmbSerialPortName);
|
||||
this.GrpSerialPort.Location = new System.Drawing.Point(13, 12);
|
||||
this.GrpSerialPort.Name = "GrpSerialPort";
|
||||
this.GrpSerialPort.Size = new System.Drawing.Size(561, 60);
|
||||
this.GrpSerialPort.TabIndex = 0;
|
||||
this.GrpSerialPort.TabStop = false;
|
||||
this.GrpSerialPort.Text = "串口设置";
|
||||
//
|
||||
// CmbSerialPortName
|
||||
//
|
||||
this.CmbSerialPortName.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
|
||||
this.CmbSerialPortName.FormattingEnabled = true;
|
||||
this.CmbSerialPortName.Location = new System.Drawing.Point(71, 22);
|
||||
this.CmbSerialPortName.Name = "CmbSerialPortName";
|
||||
this.CmbSerialPortName.Size = new System.Drawing.Size(120, 25);
|
||||
this.CmbSerialPortName.TabIndex = 1;
|
||||
//
|
||||
// LblPortName
|
||||
//
|
||||
this.LblPortName.AutoSize = true;
|
||||
this.LblPortName.Location = new System.Drawing.Point(21, 25);
|
||||
this.LblPortName.Name = "LblPortName";
|
||||
this.LblPortName.Size = new System.Drawing.Size(44, 17);
|
||||
this.LblPortName.TabIndex = 0;
|
||||
this.LblPortName.Text = "端口:";
|
||||
//
|
||||
// BtnUpdatePortNames
|
||||
//
|
||||
this.BtnUpdatePortNames.Location = new System.Drawing.Point(197, 22);
|
||||
this.BtnUpdatePortNames.Name = "BtnUpdatePortNames";
|
||||
this.BtnUpdatePortNames.Size = new System.Drawing.Size(75, 25);
|
||||
this.BtnUpdatePortNames.TabIndex = 2;
|
||||
this.BtnUpdatePortNames.Text = "刷新";
|
||||
this.BtnUpdatePortNames.UseVisualStyleBackColor = true;
|
||||
this.BtnUpdatePortNames.Click += new System.EventHandler(this.BtnUpdatePortNames_Click);
|
||||
//
|
||||
// BtnOpenPort
|
||||
//
|
||||
this.BtnOpenPort.Location = new System.Drawing.Point(278, 22);
|
||||
this.BtnOpenPort.Name = "BtnOpenPort";
|
||||
this.BtnOpenPort.Size = new System.Drawing.Size(75, 25);
|
||||
this.BtnOpenPort.TabIndex = 3;
|
||||
this.BtnOpenPort.Text = "打开";
|
||||
this.BtnOpenPort.UseVisualStyleBackColor = true;
|
||||
this.BtnOpenPort.Click += new System.EventHandler(this.BtnOpenPort_Click);
|
||||
//
|
||||
// BtnClosePort
|
||||
//
|
||||
this.BtnClosePort.Location = new System.Drawing.Point(359, 22);
|
||||
this.BtnClosePort.Name = "BtnClosePort";
|
||||
this.BtnClosePort.Size = new System.Drawing.Size(75, 25);
|
||||
this.BtnClosePort.TabIndex = 4;
|
||||
this.BtnClosePort.Text = "关闭";
|
||||
this.BtnClosePort.UseVisualStyleBackColor = true;
|
||||
this.BtnClosePort.Click += new System.EventHandler(this.BtnClosePort_Click);
|
||||
//
|
||||
// GrpSphygmomanometer
|
||||
//
|
||||
this.GrpSphygmomanometer.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
||||
this.GrpSphygmomanometer.Controls.Add(this.PrbIntervalProgress);
|
||||
this.GrpSphygmomanometer.Controls.Add(this.LblLoopTestTip);
|
||||
this.GrpSphygmomanometer.Controls.Add(this.ChkLoopTest);
|
||||
this.GrpSphygmomanometer.Controls.Add(this.NudInterval);
|
||||
this.GrpSphygmomanometer.Controls.Add(this.LblInterval);
|
||||
this.GrpSphygmomanometer.Controls.Add(this.BtnStopMeasure);
|
||||
this.GrpSphygmomanometer.Controls.Add(this.BtnStartMeasure);
|
||||
this.GrpSphygmomanometer.Controls.Add(this.BtnConnect);
|
||||
this.GrpSphygmomanometer.Location = new System.Drawing.Point(13, 272);
|
||||
this.GrpSphygmomanometer.Name = "GrpSphygmomanometer";
|
||||
this.GrpSphygmomanometer.Size = new System.Drawing.Size(560, 77);
|
||||
this.GrpSphygmomanometer.TabIndex = 3;
|
||||
this.GrpSphygmomanometer.TabStop = false;
|
||||
this.GrpSphygmomanometer.Text = "血压计控制";
|
||||
//
|
||||
// BtnConnect
|
||||
//
|
||||
this.BtnConnect.Anchor = System.Windows.Forms.AnchorStyles.Top;
|
||||
this.BtnConnect.Location = new System.Drawing.Point(24, 31);
|
||||
this.BtnConnect.Name = "BtnConnect";
|
||||
this.BtnConnect.Size = new System.Drawing.Size(100, 30);
|
||||
this.BtnConnect.TabIndex = 0;
|
||||
this.BtnConnect.Text = "测试连接";
|
||||
this.BtnConnect.UseVisualStyleBackColor = true;
|
||||
this.BtnConnect.Click += new System.EventHandler(this.BtnConnect_Click);
|
||||
//
|
||||
// BtnStartMeasure
|
||||
//
|
||||
this.BtnStartMeasure.Anchor = System.Windows.Forms.AnchorStyles.Top;
|
||||
this.BtnStartMeasure.Location = new System.Drawing.Point(132, 31);
|
||||
this.BtnStartMeasure.Name = "BtnStartMeasure";
|
||||
this.BtnStartMeasure.Size = new System.Drawing.Size(100, 30);
|
||||
this.BtnStartMeasure.TabIndex = 1;
|
||||
this.BtnStartMeasure.Text = "开始测量";
|
||||
this.BtnStartMeasure.UseVisualStyleBackColor = true;
|
||||
this.BtnStartMeasure.Click += new System.EventHandler(this.BtnStartMeasure_Click);
|
||||
//
|
||||
// BtnStopMeasure
|
||||
//
|
||||
this.BtnStopMeasure.Anchor = System.Windows.Forms.AnchorStyles.Top;
|
||||
this.BtnStopMeasure.Location = new System.Drawing.Point(238, 31);
|
||||
this.BtnStopMeasure.Name = "BtnStopMeasure";
|
||||
this.BtnStopMeasure.Size = new System.Drawing.Size(100, 30);
|
||||
this.BtnStopMeasure.TabIndex = 2;
|
||||
this.BtnStopMeasure.Text = "中断测量";
|
||||
this.BtnStopMeasure.UseVisualStyleBackColor = true;
|
||||
this.BtnStopMeasure.Click += new System.EventHandler(this.BtnStopMeasure_Click);
|
||||
//
|
||||
// LblSystolicPressure
|
||||
//
|
||||
this.LblSystolicPressure.Anchor = System.Windows.Forms.AnchorStyles.Top;
|
||||
this.LblSystolicPressure.AutoSize = true;
|
||||
this.LblSystolicPressure.Font = new System.Drawing.Font("微软雅黑", 14F);
|
||||
this.LblSystolicPressure.Location = new System.Drawing.Point(55, 33);
|
||||
this.LblSystolicPressure.Name = "LblSystolicPressure";
|
||||
this.LblSystolicPressure.Size = new System.Drawing.Size(74, 25);
|
||||
this.LblSystolicPressure.TabIndex = 1;
|
||||
this.LblSystolicPressure.Text = "收缩压:";
|
||||
//
|
||||
// GrpMeasureResult
|
||||
//
|
||||
this.GrpMeasureResult.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
||||
this.GrpMeasureResult.Controls.Add(this.LblPulseValue);
|
||||
this.GrpMeasureResult.Controls.Add(this.LblPulse);
|
||||
this.GrpMeasureResult.Controls.Add(this.LblDiastolicPressureValue);
|
||||
this.GrpMeasureResult.Controls.Add(this.LblDiastolicPressure);
|
||||
this.GrpMeasureResult.Controls.Add(this.LblSystolicPressureValue);
|
||||
this.GrpMeasureResult.Controls.Add(this.LblSystolicPressure);
|
||||
this.GrpMeasureResult.Location = new System.Drawing.Point(13, 189);
|
||||
this.GrpMeasureResult.Name = "GrpMeasureResult";
|
||||
this.GrpMeasureResult.Size = new System.Drawing.Size(560, 77);
|
||||
this.GrpMeasureResult.TabIndex = 2;
|
||||
this.GrpMeasureResult.TabStop = false;
|
||||
this.GrpMeasureResult.Text = "测量结果";
|
||||
//
|
||||
// LblSystolicPressureValue
|
||||
//
|
||||
this.LblSystolicPressureValue.Anchor = System.Windows.Forms.AnchorStyles.Top;
|
||||
this.LblSystolicPressureValue.AutoSize = true;
|
||||
this.LblSystolicPressureValue.Font = new System.Drawing.Font("微软雅黑", 14F);
|
||||
this.LblSystolicPressureValue.Location = new System.Drawing.Point(135, 33);
|
||||
this.LblSystolicPressureValue.Name = "LblSystolicPressureValue";
|
||||
this.LblSystolicPressureValue.Size = new System.Drawing.Size(23, 25);
|
||||
this.LblSystolicPressureValue.TabIndex = 2;
|
||||
this.LblSystolicPressureValue.Text = "0";
|
||||
//
|
||||
// LblDiastolicPressure
|
||||
//
|
||||
this.LblDiastolicPressure.Anchor = System.Windows.Forms.AnchorStyles.Top;
|
||||
this.LblDiastolicPressure.AutoSize = true;
|
||||
this.LblDiastolicPressure.Font = new System.Drawing.Font("微软雅黑", 14F);
|
||||
this.LblDiastolicPressure.Location = new System.Drawing.Point(230, 33);
|
||||
this.LblDiastolicPressure.Name = "LblDiastolicPressure";
|
||||
this.LblDiastolicPressure.Size = new System.Drawing.Size(69, 25);
|
||||
this.LblDiastolicPressure.TabIndex = 3;
|
||||
this.LblDiastolicPressure.Text = "舒张压";
|
||||
//
|
||||
// LblDiastolicPressureValue
|
||||
//
|
||||
this.LblDiastolicPressureValue.Anchor = System.Windows.Forms.AnchorStyles.Top;
|
||||
this.LblDiastolicPressureValue.AutoSize = true;
|
||||
this.LblDiastolicPressureValue.Font = new System.Drawing.Font("微软雅黑", 14F);
|
||||
this.LblDiastolicPressureValue.Location = new System.Drawing.Point(305, 33);
|
||||
this.LblDiastolicPressureValue.Name = "LblDiastolicPressureValue";
|
||||
this.LblDiastolicPressureValue.Size = new System.Drawing.Size(23, 25);
|
||||
this.LblDiastolicPressureValue.TabIndex = 4;
|
||||
this.LblDiastolicPressureValue.Text = "0";
|
||||
//
|
||||
// LblPulse
|
||||
//
|
||||
this.LblPulse.Anchor = System.Windows.Forms.AnchorStyles.Top;
|
||||
this.LblPulse.AutoSize = true;
|
||||
this.LblPulse.Font = new System.Drawing.Font("微软雅黑", 14F);
|
||||
this.LblPulse.Location = new System.Drawing.Point(399, 33);
|
||||
this.LblPulse.Name = "LblPulse";
|
||||
this.LblPulse.Size = new System.Drawing.Size(55, 25);
|
||||
this.LblPulse.TabIndex = 5;
|
||||
this.LblPulse.Text = "脉搏:";
|
||||
//
|
||||
// LblPulseValue
|
||||
//
|
||||
this.LblPulseValue.Anchor = System.Windows.Forms.AnchorStyles.Top;
|
||||
this.LblPulseValue.AutoSize = true;
|
||||
this.LblPulseValue.Font = new System.Drawing.Font("微软雅黑", 14F);
|
||||
this.LblPulseValue.Location = new System.Drawing.Point(460, 33);
|
||||
this.LblPulseValue.Name = "LblPulseValue";
|
||||
this.LblPulseValue.Size = new System.Drawing.Size(23, 25);
|
||||
this.LblPulseValue.TabIndex = 6;
|
||||
this.LblPulseValue.Text = "0";
|
||||
//
|
||||
// GrpPressure
|
||||
//
|
||||
this.GrpPressure.Anchor = System.Windows.Forms.AnchorStyles.Left;
|
||||
this.GrpPressure.Controls.Add(this.LblPressureValue);
|
||||
this.GrpPressure.Location = new System.Drawing.Point(192, 78);
|
||||
this.GrpPressure.Name = "GrpPressure";
|
||||
this.GrpPressure.Size = new System.Drawing.Size(200, 105);
|
||||
this.GrpPressure.TabIndex = 1;
|
||||
this.GrpPressure.TabStop = false;
|
||||
this.GrpPressure.Text = "实时压力值(mmHg)";
|
||||
//
|
||||
// LblPressureValue
|
||||
//
|
||||
this.LblPressureValue.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.LblPressureValue.Font = new System.Drawing.Font("微软雅黑", 20F);
|
||||
this.LblPressureValue.Location = new System.Drawing.Point(3, 19);
|
||||
this.LblPressureValue.Name = "LblPressureValue";
|
||||
this.LblPressureValue.Size = new System.Drawing.Size(194, 83);
|
||||
this.LblPressureValue.TabIndex = 0;
|
||||
this.LblPressureValue.Text = "0";
|
||||
this.LblPressureValue.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
|
||||
//
|
||||
// LblInterval
|
||||
//
|
||||
this.LblInterval.AutoSize = true;
|
||||
this.LblInterval.Location = new System.Drawing.Point(357, 31);
|
||||
this.LblInterval.Name = "LblInterval";
|
||||
this.LblInterval.Size = new System.Drawing.Size(50, 17);
|
||||
this.LblInterval.TabIndex = 3;
|
||||
this.LblInterval.Text = "间隔(S):";
|
||||
//
|
||||
// NudInterval
|
||||
//
|
||||
this.NudInterval.Increment = new decimal(new int[] {
|
||||
30,
|
||||
0,
|
||||
0,
|
||||
0});
|
||||
this.NudInterval.Location = new System.Drawing.Point(413, 29);
|
||||
this.NudInterval.Maximum = new decimal(new int[] {
|
||||
2147483647,
|
||||
0,
|
||||
0,
|
||||
0});
|
||||
this.NudInterval.Name = "NudInterval";
|
||||
this.NudInterval.Size = new System.Drawing.Size(60, 23);
|
||||
this.NudInterval.TabIndex = 4;
|
||||
this.NudInterval.Value = new decimal(new int[] {
|
||||
120,
|
||||
0,
|
||||
0,
|
||||
0});
|
||||
//
|
||||
// ChkLoopTest
|
||||
//
|
||||
this.ChkLoopTest.AutoSize = true;
|
||||
this.ChkLoopTest.Location = new System.Drawing.Point(479, 31);
|
||||
this.ChkLoopTest.Name = "ChkLoopTest";
|
||||
this.ChkLoopTest.Size = new System.Drawing.Size(75, 21);
|
||||
this.ChkLoopTest.TabIndex = 5;
|
||||
this.ChkLoopTest.Text = "循环测试";
|
||||
this.ChkLoopTest.UseVisualStyleBackColor = true;
|
||||
this.ChkLoopTest.CheckedChanged += new System.EventHandler(this.ChkLoopTest_CheckedChanged);
|
||||
//
|
||||
// LblLoopTestTip
|
||||
//
|
||||
this.LblLoopTestTip.AutoSize = true;
|
||||
this.LblLoopTestTip.ForeColor = System.Drawing.SystemColors.GrayText;
|
||||
this.LblLoopTestTip.Location = new System.Drawing.Point(360, 55);
|
||||
this.LblLoopTestTip.Name = "LblLoopTestTip";
|
||||
this.LblLoopTestTip.Size = new System.Drawing.Size(188, 17);
|
||||
this.LblLoopTestTip.TabIndex = 6;
|
||||
this.LblLoopTestTip.Text = "收到测试结果指定时间后自动开始";
|
||||
//
|
||||
// PrbIntervalProgress
|
||||
//
|
||||
this.PrbIntervalProgress.Location = new System.Drawing.Point(360, 14);
|
||||
this.PrbIntervalProgress.Name = "PrbIntervalProgress";
|
||||
this.PrbIntervalProgress.Size = new System.Drawing.Size(188, 10);
|
||||
this.PrbIntervalProgress.TabIndex = 7;
|
||||
this.PrbIntervalProgress.Visible = false;
|
||||
//
|
||||
// GrpLog
|
||||
//
|
||||
this.GrpLog.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
||||
| System.Windows.Forms.AnchorStyles.Left)
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.GrpLog.Controls.Add(this.TxtLog);
|
||||
this.GrpLog.Location = new System.Drawing.Point(579, 12);
|
||||
this.GrpLog.Name = "GrpLog";
|
||||
this.GrpLog.Size = new System.Drawing.Size(233, 284);
|
||||
this.GrpLog.TabIndex = 4;
|
||||
this.GrpLog.TabStop = false;
|
||||
this.GrpLog.Text = "日志";
|
||||
//
|
||||
// TxtLog
|
||||
//
|
||||
this.TxtLog.BackColor = System.Drawing.Color.White;
|
||||
this.TxtLog.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.TxtLog.Location = new System.Drawing.Point(3, 19);
|
||||
this.TxtLog.Multiline = true;
|
||||
this.TxtLog.Name = "TxtLog";
|
||||
this.TxtLog.ReadOnly = true;
|
||||
this.TxtLog.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
|
||||
this.TxtLog.Size = new System.Drawing.Size(227, 262);
|
||||
this.TxtLog.TabIndex = 0;
|
||||
//
|
||||
// GrpStat
|
||||
//
|
||||
this.GrpStat.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.GrpStat.Controls.Add(this.FlpStatLabels);
|
||||
this.GrpStat.Controls.Add(this.BtnResetStat);
|
||||
this.GrpStat.Location = new System.Drawing.Point(579, 301);
|
||||
this.GrpStat.Name = "GrpStat";
|
||||
this.GrpStat.Size = new System.Drawing.Size(230, 48);
|
||||
this.GrpStat.TabIndex = 5;
|
||||
this.GrpStat.TabStop = false;
|
||||
this.GrpStat.Text = "统计";
|
||||
//
|
||||
// BtnResetStat
|
||||
//
|
||||
this.BtnResetStat.Dock = System.Windows.Forms.DockStyle.Right;
|
||||
this.BtnResetStat.Location = new System.Drawing.Point(177, 19);
|
||||
this.BtnResetStat.Name = "BtnResetStat";
|
||||
this.BtnResetStat.Size = new System.Drawing.Size(50, 26);
|
||||
this.BtnResetStat.TabIndex = 1;
|
||||
this.BtnResetStat.Text = "重置";
|
||||
this.BtnResetStat.UseVisualStyleBackColor = true;
|
||||
this.BtnResetStat.Click += new System.EventHandler(this.BtnResetStat_Click);
|
||||
//
|
||||
// FlpStatLabels
|
||||
//
|
||||
this.FlpStatLabels.Controls.Add(this.LblTestStat);
|
||||
this.FlpStatLabels.Controls.Add(this.LblTestSuccessCount);
|
||||
this.FlpStatLabels.Controls.Add(this.LblTestStatSeparator1);
|
||||
this.FlpStatLabels.Controls.Add(this.LblTestFailedCount);
|
||||
this.FlpStatLabels.Controls.Add(this.LblTestStatSeparator2);
|
||||
this.FlpStatLabels.Controls.Add(this.LblTestCount);
|
||||
this.FlpStatLabels.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.FlpStatLabels.Location = new System.Drawing.Point(3, 19);
|
||||
this.FlpStatLabels.Name = "FlpStatLabels";
|
||||
this.FlpStatLabels.Size = new System.Drawing.Size(174, 26);
|
||||
this.FlpStatLabels.TabIndex = 2;
|
||||
//
|
||||
// LblTestStat
|
||||
//
|
||||
this.LblTestStat.AutoSize = true;
|
||||
this.LblTestStat.Location = new System.Drawing.Point(0, 4);
|
||||
this.LblTestStat.Margin = new System.Windows.Forms.Padding(0, 4, 0, 0);
|
||||
this.LblTestStat.Name = "LblTestStat";
|
||||
this.LblTestStat.Size = new System.Drawing.Size(59, 17);
|
||||
this.LblTestStat.TabIndex = 0;
|
||||
this.LblTestStat.Text = "测量次数:";
|
||||
//
|
||||
// LblTestSuccessCount
|
||||
//
|
||||
this.LblTestSuccessCount.AutoSize = true;
|
||||
this.LblTestSuccessCount.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
|
||||
this.LblTestSuccessCount.ForeColor = System.Drawing.Color.Green;
|
||||
this.LblTestSuccessCount.Location = new System.Drawing.Point(59, 4);
|
||||
this.LblTestSuccessCount.Margin = new System.Windows.Forms.Padding(0, 4, 0, 0);
|
||||
this.LblTestSuccessCount.Name = "LblTestSuccessCount";
|
||||
this.LblTestSuccessCount.Size = new System.Drawing.Size(15, 17);
|
||||
this.LblTestSuccessCount.TabIndex = 1;
|
||||
this.LblTestSuccessCount.Text = "0";
|
||||
//
|
||||
// LblTestStatSeparator1
|
||||
//
|
||||
this.LblTestStatSeparator1.AutoSize = true;
|
||||
this.LblTestStatSeparator1.Location = new System.Drawing.Point(74, 4);
|
||||
this.LblTestStatSeparator1.Margin = new System.Windows.Forms.Padding(0, 4, 0, 0);
|
||||
this.LblTestStatSeparator1.Name = "LblTestStatSeparator1";
|
||||
this.LblTestStatSeparator1.Size = new System.Drawing.Size(13, 17);
|
||||
this.LblTestStatSeparator1.TabIndex = 2;
|
||||
this.LblTestStatSeparator1.Text = "/";
|
||||
//
|
||||
// LblTestFailedCount
|
||||
//
|
||||
this.LblTestFailedCount.AutoSize = true;
|
||||
this.LblTestFailedCount.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
|
||||
this.LblTestFailedCount.ForeColor = System.Drawing.Color.Red;
|
||||
this.LblTestFailedCount.Location = new System.Drawing.Point(87, 4);
|
||||
this.LblTestFailedCount.Margin = new System.Windows.Forms.Padding(0, 4, 0, 0);
|
||||
this.LblTestFailedCount.Name = "LblTestFailedCount";
|
||||
this.LblTestFailedCount.Size = new System.Drawing.Size(15, 17);
|
||||
this.LblTestFailedCount.TabIndex = 3;
|
||||
this.LblTestFailedCount.Text = "0";
|
||||
//
|
||||
// LblTestStatSeparator2
|
||||
//
|
||||
this.LblTestStatSeparator2.AutoSize = true;
|
||||
this.LblTestStatSeparator2.Location = new System.Drawing.Point(102, 4);
|
||||
this.LblTestStatSeparator2.Margin = new System.Windows.Forms.Padding(0, 4, 0, 0);
|
||||
this.LblTestStatSeparator2.Name = "LblTestStatSeparator2";
|
||||
this.LblTestStatSeparator2.Size = new System.Drawing.Size(13, 17);
|
||||
this.LblTestStatSeparator2.TabIndex = 4;
|
||||
this.LblTestStatSeparator2.Text = "/";
|
||||
//
|
||||
// LblTestCount
|
||||
//
|
||||
this.LblTestCount.AutoSize = true;
|
||||
this.LblTestCount.Location = new System.Drawing.Point(115, 4);
|
||||
this.LblTestCount.Margin = new System.Windows.Forms.Padding(0, 4, 0, 0);
|
||||
this.LblTestCount.Name = "LblTestCount";
|
||||
this.LblTestCount.Size = new System.Drawing.Size(15, 17);
|
||||
this.LblTestCount.TabIndex = 5;
|
||||
this.LblTestCount.Text = "0";
|
||||
//
|
||||
// FormMain
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 17F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.ClientSize = new System.Drawing.Size(824, 361);
|
||||
this.Controls.Add(this.GrpStat);
|
||||
this.Controls.Add(this.GrpLog);
|
||||
this.Controls.Add(this.GrpPressure);
|
||||
this.Controls.Add(this.GrpMeasureResult);
|
||||
this.Controls.Add(this.GrpSphygmomanometer);
|
||||
this.Controls.Add(this.GrpSerialPort);
|
||||
this.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
|
||||
this.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
|
||||
this.MinimumSize = new System.Drawing.Size(840, 400);
|
||||
this.Name = "FormMain";
|
||||
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
|
||||
this.Text = "血压计通讯测试工具";
|
||||
this.GrpSerialPort.ResumeLayout(false);
|
||||
this.GrpSerialPort.PerformLayout();
|
||||
this.GrpSphygmomanometer.ResumeLayout(false);
|
||||
this.GrpSphygmomanometer.PerformLayout();
|
||||
this.GrpMeasureResult.ResumeLayout(false);
|
||||
this.GrpMeasureResult.PerformLayout();
|
||||
this.GrpPressure.ResumeLayout(false);
|
||||
((System.ComponentModel.ISupportInitialize)(this.NudInterval)).EndInit();
|
||||
this.GrpLog.ResumeLayout(false);
|
||||
this.GrpLog.PerformLayout();
|
||||
this.GrpStat.ResumeLayout(false);
|
||||
this.FlpStatLabels.ResumeLayout(false);
|
||||
this.FlpStatLabels.PerformLayout();
|
||||
this.ResumeLayout(false);
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.GroupBox GrpSerialPort;
|
||||
private System.Windows.Forms.Button BtnClosePort;
|
||||
private System.Windows.Forms.Button BtnOpenPort;
|
||||
private System.Windows.Forms.Button BtnUpdatePortNames;
|
||||
private System.Windows.Forms.Label LblPortName;
|
||||
private System.Windows.Forms.ComboBox CmbSerialPortName;
|
||||
private System.Windows.Forms.GroupBox GrpSphygmomanometer;
|
||||
private System.Windows.Forms.Button BtnConnect;
|
||||
private System.Windows.Forms.Button BtnStopMeasure;
|
||||
private System.Windows.Forms.Button BtnStartMeasure;
|
||||
private System.Windows.Forms.Label LblSystolicPressure;
|
||||
private System.Windows.Forms.GroupBox GrpMeasureResult;
|
||||
private System.Windows.Forms.Label LblSystolicPressureValue;
|
||||
private System.Windows.Forms.Label LblPulseValue;
|
||||
private System.Windows.Forms.Label LblPulse;
|
||||
private System.Windows.Forms.Label LblDiastolicPressureValue;
|
||||
private System.Windows.Forms.Label LblDiastolicPressure;
|
||||
private System.Windows.Forms.GroupBox GrpPressure;
|
||||
private System.Windows.Forms.Label LblPressureValue;
|
||||
private System.Windows.Forms.ProgressBar PrbIntervalProgress;
|
||||
private System.Windows.Forms.Label LblLoopTestTip;
|
||||
private System.Windows.Forms.CheckBox ChkLoopTest;
|
||||
private System.Windows.Forms.NumericUpDown NudInterval;
|
||||
private System.Windows.Forms.Label LblInterval;
|
||||
private System.Windows.Forms.GroupBox GrpLog;
|
||||
private System.Windows.Forms.TextBox TxtLog;
|
||||
private System.Windows.Forms.GroupBox GrpStat;
|
||||
private System.Windows.Forms.FlowLayoutPanel FlpStatLabels;
|
||||
private System.Windows.Forms.Label LblTestStat;
|
||||
private System.Windows.Forms.Label LblTestSuccessCount;
|
||||
private System.Windows.Forms.Label LblTestStatSeparator1;
|
||||
private System.Windows.Forms.Label LblTestFailedCount;
|
||||
private System.Windows.Forms.Label LblTestStatSeparator2;
|
||||
private System.Windows.Forms.Label LblTestCount;
|
||||
private System.Windows.Forms.Button BtnResetStat;
|
||||
}
|
||||
}
|
||||
|
436
SphygmomanometerTester/FormMain.cs
Normal file
436
SphygmomanometerTester/FormMain.cs
Normal file
@ -0,0 +1,436 @@
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.IO.Ports;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
using SphygmomanometerTester.Sphygmomanometer.MaiBoBo;
|
||||
using SphygmomanometerTester.Sphygmomanometer.OMRON;
|
||||
|
||||
namespace SphygmomanometerTester
|
||||
{
|
||||
public partial class FormMain : Form
|
||||
{
|
||||
public static FormMain Instance { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 血压计实例
|
||||
/// </summary>
|
||||
private readonly Sphygmomanometer.Sphygmomanometer sphygmomanometer = new Omron();
|
||||
|
||||
#region - 窗口构造与事件 -
|
||||
|
||||
public FormMain()
|
||||
{
|
||||
Instance = this;
|
||||
InitializeComponent();
|
||||
|
||||
if (sphygmomanometer is MaiBoBo maiBoBo)
|
||||
maiBoBo.MeasuringPoll += Sphygmomanometer_MeasuringPoll;
|
||||
sphygmomanometer.MeasureOver += Sphygmomanometer_MeasureOver;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 窗体加载时触发
|
||||
/// </summary>
|
||||
/// <param name="e"></param>
|
||||
protected override void OnLoad(EventArgs e)
|
||||
{
|
||||
base.OnLoad(e);
|
||||
CmbSerialPortName.DataSource = SerialPort.GetPortNames();
|
||||
UpdateControlButtons();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 窗口关闭时触发
|
||||
/// </summary>
|
||||
protected override void OnFormClosed(FormClosedEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!string.IsNullOrEmpty(TxtLog.Text))
|
||||
{
|
||||
// 保存日志文件
|
||||
File.WriteAllText(DateTime.Now.ToString("MMddHHmm") + ".log", TxtLog.Text);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
|
||||
sphygmomanometer.CloseCom();
|
||||
|
||||
base.OnFormClosed(e);
|
||||
}
|
||||
|
||||
#endregion - 窗口构造与事件 -
|
||||
|
||||
#region - 血压计事件 -
|
||||
|
||||
/// <summary>
|
||||
/// 测量过程压力上报事件
|
||||
/// </summary>
|
||||
private void Sphygmomanometer_MeasuringPoll(object sender, MaiBoBo.MeasurePoll e)
|
||||
{
|
||||
BeginInvoke(new Action(() =>
|
||||
{
|
||||
LblPressureValue.Text = e.Pressure.ToString();
|
||||
}));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测量结束事件
|
||||
/// </summary>
|
||||
private void Sphygmomanometer_MeasureOver(object sender, Sphygmomanometer.MeasureResult e)
|
||||
{
|
||||
BeginInvoke(new Action(() =>
|
||||
{
|
||||
// 显示结果
|
||||
LblPressureValue.Text = "0";
|
||||
LblSystolicPressureValue.Text = e.SystolicPressure.ToString();
|
||||
LblDiastolicPressureValue.Text = e.DiastolicPressure.ToString();
|
||||
LblPulseValue.Text = e.Pulse.ToString();
|
||||
if (!string.IsNullOrEmpty(e.Message))
|
||||
{
|
||||
StatEndTest(false);
|
||||
Log("测量失败:" + e.Message);
|
||||
if (!ChkLoopTest.Checked)
|
||||
{
|
||||
MessageBox.Show(e.Message, "测量出错", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
StatEndTest(true);
|
||||
Log($"测量完成,结果:收缩压={e.SystolicPressure} 舒张压={e.DiastolicPressure} 脉搏={e.Pulse}");
|
||||
}
|
||||
|
||||
// 检查并循环测量
|
||||
CheckAndLoop();
|
||||
}));
|
||||
}
|
||||
|
||||
#endregion - 血压计事件 -
|
||||
|
||||
#region - 控制按钮 -
|
||||
|
||||
/// <summary>
|
||||
/// 更新控制按钮状态
|
||||
/// </summary>
|
||||
private void UpdateControlButtons()
|
||||
{
|
||||
var isOpen = sphygmomanometer.IsOpen;
|
||||
CmbSerialPortName.Enabled = !isOpen;
|
||||
BtnUpdatePortNames.Enabled = !isOpen;
|
||||
BtnOpenPort.Enabled = !isOpen;
|
||||
BtnClosePort.Enabled = isOpen;
|
||||
BtnConnect.Enabled = isOpen;
|
||||
BtnStartMeasure.Enabled = isOpen;
|
||||
BtnStopMeasure.Enabled = isOpen;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 刷新串口列表
|
||||
/// </summary>
|
||||
private void BtnUpdatePortNames_Click(object sender, EventArgs e)
|
||||
{
|
||||
CmbSerialPortName.DataSource = SerialPort.GetPortNames();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 点击打开串口
|
||||
/// </summary>
|
||||
private void BtnOpenPort_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(CmbSerialPortName.Text))
|
||||
{
|
||||
Log("打开串口 " + CmbSerialPortName.Text);
|
||||
try
|
||||
{
|
||||
sphygmomanometer.OpenCom(CmbSerialPortName.Text);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log("打开串口异常", ex);
|
||||
MessageBox.Show("串口打开失败", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
MessageBox.Show("请选择端口", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
}
|
||||
UpdateControlButtons();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 点击关闭串口
|
||||
/// </summary>
|
||||
private void BtnClosePort_Click(object sender, EventArgs e)
|
||||
{
|
||||
Log("关闭串口");
|
||||
sphygmomanometer.CloseCom();
|
||||
UpdateControlButtons();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 点击测试连接按钮
|
||||
/// </summary>
|
||||
private async void BtnConnect_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (!(sphygmomanometer is MaiBoBo maiBoBo))
|
||||
{
|
||||
MessageBox.Show("当前血压计不支持测试连接状态", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
return;
|
||||
}
|
||||
|
||||
var btn = (Button)sender;
|
||||
try
|
||||
{
|
||||
btn.Enabled = false;
|
||||
LblPressureValue.Text = "0";
|
||||
Log("尝试连接血压计,发送连接测试");
|
||||
await maiBoBo.Connect();
|
||||
Log("正常响应");
|
||||
await ButtonOk(btn);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log("连接测试异常", ex);
|
||||
MessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
}
|
||||
finally
|
||||
{
|
||||
btn.Enabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 点击开始测量按钮
|
||||
/// </summary>
|
||||
private async void BtnStartMeasure_Click(object sender, EventArgs e)
|
||||
{
|
||||
var btn = (Button)sender;
|
||||
try
|
||||
{
|
||||
btn.Enabled = false;
|
||||
LblPressureValue.Text = "0";
|
||||
Log($"尝试开始第 {TestCount + 1} 次测量...");
|
||||
await sphygmomanometer.StartMeasure();
|
||||
StatBeginTest();
|
||||
await ButtonOk(btn);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log("开始测量异常", ex);
|
||||
MessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
}
|
||||
finally
|
||||
{
|
||||
btn.Enabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 点击停止测量按钮
|
||||
/// </summary>
|
||||
private async void BtnStopMeasure_Click(object sender, EventArgs e)
|
||||
{
|
||||
var btn = (Button)sender;
|
||||
try
|
||||
{
|
||||
btn.Enabled = false;
|
||||
LblPressureValue.Text = "0";
|
||||
Log("尝试取消测量");
|
||||
await sphygmomanometer.StopMeasure();
|
||||
await ButtonOk(btn);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log("停止测量异常", ex);
|
||||
MessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
}
|
||||
finally
|
||||
{
|
||||
btn.Enabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查并启动循环
|
||||
/// </summary>
|
||||
private void CheckAndLoop()
|
||||
{
|
||||
if (!ChkLoopTest.Checked) return;
|
||||
var interval = (int)NudInterval.Value;
|
||||
if (interval > 0)
|
||||
{
|
||||
PrbIntervalProgress.Maximum = interval;
|
||||
PrbIntervalProgress.Value = 0;
|
||||
PrbIntervalProgress.Visible = true;
|
||||
CancellationTokenSource = new CancellationTokenSource();
|
||||
var cancellationToken = CancellationTokenSource.Token;
|
||||
Log($"启动任务,等待 {interval} 秒后重新开始测试...");
|
||||
Task.Run(async () =>
|
||||
{
|
||||
for (var i = 0; i < interval && !cancellationToken.IsCancellationRequested; i++)
|
||||
{
|
||||
await Task.Delay(1000, cancellationToken);
|
||||
Invoke(new Action(() =>
|
||||
{
|
||||
PrbIntervalProgress.Value += 1;
|
||||
if (PrbIntervalProgress.Value == PrbIntervalProgress.Maximum)
|
||||
PrbIntervalProgress.Visible = false;
|
||||
}));
|
||||
}
|
||||
|
||||
if (!cancellationToken.IsCancellationRequested && sphygmomanometer.IsOpen)
|
||||
{
|
||||
BeginInvoke(new Action(() => BtnStartMeasure_Click(BtnStartMeasure, EventArgs.Empty)));
|
||||
}
|
||||
}, cancellationToken);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log("无间隔循环测试继续");
|
||||
BtnStartMeasure_Click(BtnStartMeasure, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
private CancellationTokenSource CancellationTokenSource;
|
||||
|
||||
/// <summary>
|
||||
/// 循环测试复选框改变事件
|
||||
/// </summary>
|
||||
private void ChkLoopTest_CheckedChanged(object sender, EventArgs e)
|
||||
{
|
||||
if (ChkLoopTest.Checked) return;
|
||||
if (CancellationTokenSource != null && !CancellationTokenSource.IsCancellationRequested)
|
||||
{
|
||||
CancellationTokenSource.Cancel();
|
||||
PrbIntervalProgress.Visible = false;
|
||||
Log("取消循环测试");
|
||||
}
|
||||
}
|
||||
|
||||
#endregion - 控制按钮 -
|
||||
|
||||
#region - 日志 -
|
||||
|
||||
/// <summary>
|
||||
/// 写日志到文本框
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
public void Log(string message)
|
||||
{
|
||||
if (InvokeRequired)
|
||||
{
|
||||
Invoke(new Action<string>(Log), message);
|
||||
return;
|
||||
}
|
||||
var scrollToEnd = TxtLog.SelectionStart == TxtLog.Text.Length;
|
||||
TxtLog.AppendText(DateTime.Now.ToLongTimeString());
|
||||
TxtLog.AppendText(" ");
|
||||
TxtLog.AppendText(message);
|
||||
TxtLog.AppendText(Environment.NewLine);
|
||||
if (!scrollToEnd) return;
|
||||
TxtLog.SelectionStart = TxtLog.Text.Length;
|
||||
TxtLog.SelectionLength = 0;
|
||||
TxtLog.ScrollToCaret();
|
||||
}
|
||||
|
||||
public void Log(string message, Exception ex)
|
||||
{
|
||||
Log(message + " " + ex);
|
||||
}
|
||||
|
||||
#endregion - 日志 -
|
||||
|
||||
#region - 工具 -
|
||||
|
||||
/// <summary>
|
||||
/// 按钮OK动画
|
||||
/// </summary>
|
||||
/// <param name="btn"></param>
|
||||
/// <returns></returns>
|
||||
private static async Task ButtonOk(Control btn)
|
||||
{
|
||||
var text = btn.Text;
|
||||
var color = btn.ForeColor;
|
||||
btn.Text = "OK";
|
||||
btn.ForeColor = Color.LawnGreen;
|
||||
await Task.Delay(1000);
|
||||
btn.Text = text;
|
||||
btn.ForeColor = color;
|
||||
}
|
||||
|
||||
#endregion - 工具 -
|
||||
|
||||
#region - 重置统计 -
|
||||
|
||||
/// <summary>
|
||||
/// 测试次数
|
||||
/// </summary>
|
||||
private int TestCount;
|
||||
|
||||
/// <summary>
|
||||
/// 测试成功次数
|
||||
/// </summary>
|
||||
private int TestSuccessCount;
|
||||
|
||||
/// <summary>
|
||||
/// 测试失败次数
|
||||
/// </summary>
|
||||
private int TestFailedCount;
|
||||
|
||||
/// <summary>
|
||||
/// 点击重置统计按钮
|
||||
/// </summary>
|
||||
private void BtnResetStat_Click(object sender, EventArgs e)
|
||||
{
|
||||
TestCount = 0;
|
||||
TestSuccessCount = 0;
|
||||
TestFailedCount = 0;
|
||||
UpdateStat();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新统计
|
||||
/// </summary>
|
||||
private void UpdateStat()
|
||||
{
|
||||
if (InvokeRequired)
|
||||
Invoke(new Action(UpdateStat));
|
||||
else
|
||||
{
|
||||
LblTestCount.Text = TestCount.ToString();
|
||||
LblTestSuccessCount.Text = TestSuccessCount.ToString();
|
||||
LblTestFailedCount.Text = TestFailedCount.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 统计开始测试
|
||||
/// </summary>
|
||||
private void StatBeginTest()
|
||||
{
|
||||
TestCount += 1;
|
||||
UpdateStat();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 统计测试结束
|
||||
/// </summary>
|
||||
/// <param name="isSuccess">测试是否成功</param>
|
||||
private void StatEndTest(bool isSuccess)
|
||||
{
|
||||
if (isSuccess) TestSuccessCount++;
|
||||
else TestFailedCount++;
|
||||
UpdateStat();
|
||||
}
|
||||
|
||||
#endregion - 重置统计 -
|
||||
}
|
||||
}
|
120
SphygmomanometerTester/FormMain.resx
Normal file
120
SphygmomanometerTester/FormMain.resx
Normal file
@ -0,0 +1,120 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
22
SphygmomanometerTester/Program.cs
Normal file
22
SphygmomanometerTester/Program.cs
Normal file
@ -0,0 +1,22 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace SphygmomanometerTester
|
||||
{
|
||||
internal static class Program
|
||||
{
|
||||
/// <summary>
|
||||
/// 应用程序的主入口点。
|
||||
/// </summary>
|
||||
[STAThread]
|
||||
static void Main()
|
||||
{
|
||||
Application.EnableVisualStyles();
|
||||
Application.SetCompatibleTextRenderingDefault(false);
|
||||
Application.Run(new FormMain());
|
||||
}
|
||||
}
|
||||
}
|
35
SphygmomanometerTester/Properties/AssemblyInfo.cs
Normal file
35
SphygmomanometerTester/Properties/AssemblyInfo.cs
Normal file
@ -0,0 +1,35 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// 有关程序集的一般信息由以下
|
||||
// 控制。更改这些特性值可修改
|
||||
// 与程序集关联的信息。
|
||||
[assembly: AssemblyTitle("SphygmomanometerTester")]
|
||||
[assembly: AssemblyDescription("血压计测试工具")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("SphygmomanometerTester")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2023 jie65535")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// 将 ComVisible 设置为 false 会使此程序集中的类型
|
||||
//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
|
||||
//请将此类型的 ComVisible 特性设置为 true。
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
|
||||
[assembly: Guid("8c5fddd2-5ec5-4ad7-ab24-f87665872a95")]
|
||||
|
||||
// 程序集的版本信息由下列四个值组成:
|
||||
//
|
||||
// 主版本
|
||||
// 次版本
|
||||
// 生成号
|
||||
// 修订号
|
||||
//
|
||||
//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值
|
||||
//通过使用 "*",如下所示:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
71
SphygmomanometerTester/Properties/Resources.Designer.cs
generated
Normal file
71
SphygmomanometerTester/Properties/Resources.Designer.cs
generated
Normal file
@ -0,0 +1,71 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// 此代码由工具生成。
|
||||
// 运行时版本: 4.0.30319.42000
|
||||
//
|
||||
// 对此文件的更改可能导致不正确的行为,如果
|
||||
// 重新生成代码,则所做更改将丢失。
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace SphygmomanometerTester.Properties
|
||||
{
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 强类型资源类,用于查找本地化字符串等。
|
||||
/// </summary>
|
||||
// 此类是由 StronglyTypedResourceBuilder
|
||||
// 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。
|
||||
// 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen
|
||||
// (以 /str 作为命令选项),或重新生成 VS 项目。
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
internal class Resources
|
||||
{
|
||||
|
||||
private static global::System.Resources.ResourceManager resourceMan;
|
||||
|
||||
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||
|
||||
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
internal Resources()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 返回此类使用的缓存 ResourceManager 实例。
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Resources.ResourceManager ResourceManager
|
||||
{
|
||||
get
|
||||
{
|
||||
if ((resourceMan == null))
|
||||
{
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SphygmomanometerTester.Properties.Resources", typeof(Resources).Assembly);
|
||||
resourceMan = temp;
|
||||
}
|
||||
return resourceMan;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 重写当前线程的 CurrentUICulture 属性,对
|
||||
/// 使用此强类型资源类的所有资源查找执行重写。
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Globalization.CultureInfo Culture
|
||||
{
|
||||
get
|
||||
{
|
||||
return resourceCulture;
|
||||
}
|
||||
set
|
||||
{
|
||||
resourceCulture = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
117
SphygmomanometerTester/Properties/Resources.resx
Normal file
117
SphygmomanometerTester/Properties/Resources.resx
Normal file
@ -0,0 +1,117 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
30
SphygmomanometerTester/Properties/Settings.Designer.cs
generated
Normal file
30
SphygmomanometerTester/Properties/Settings.Designer.cs
generated
Normal file
@ -0,0 +1,30 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.42000
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace SphygmomanometerTester.Properties
|
||||
{
|
||||
|
||||
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
|
||||
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
|
||||
{
|
||||
|
||||
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
|
||||
|
||||
public static Settings Default
|
||||
{
|
||||
get
|
||||
{
|
||||
return defaultInstance;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
7
SphygmomanometerTester/Properties/Settings.settings
Normal file
7
SphygmomanometerTester/Properties/Settings.settings
Normal file
@ -0,0 +1,7 @@
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
|
||||
<Profiles>
|
||||
<Profile Name="(Default)" />
|
||||
</Profiles>
|
||||
<Settings />
|
||||
</SettingsFile>
|
437
SphygmomanometerTester/Sphygmomanometer/MaiBoBo/MaiBoBo.cs
Normal file
437
SphygmomanometerTester/Sphygmomanometer/MaiBoBo/MaiBoBo.cs
Normal file
@ -0,0 +1,437 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.IO.Ports;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SphygmomanometerTester.Sphygmomanometer.MaiBoBo
|
||||
{
|
||||
public class MaiBoBo : Sphygmomanometer
|
||||
{
|
||||
public MaiBoBo()
|
||||
{
|
||||
// 串口波特率为115200
|
||||
// 串口的其它参数保持默认即可
|
||||
SerialPort.BaudRate = 115200;
|
||||
|
||||
SerialPort.DataReceived += SerialPort_DataReceived;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 通讯尝试超时时间(毫秒)
|
||||
/// </summary>
|
||||
private const int TryTimeoutMs = 200;
|
||||
|
||||
/// <summary>
|
||||
/// 最大重试次数
|
||||
/// </summary>
|
||||
private const int RetryMax = 5;
|
||||
|
||||
public Task Connect() => RequestAsync(PackageConnect, BloodPressureSubCode.Connect);
|
||||
|
||||
public override Task StartMeasure() => RequestAsync(PackageStart, BloodPressureSubCode.Start);
|
||||
|
||||
public override Task StopMeasure() => RequestAsync(PackageStop, BloodPressureSubCode.Stop);
|
||||
|
||||
public override event EventHandler<MeasureResult> MeasureOver;
|
||||
|
||||
/// <summary>
|
||||
/// 测量中报告
|
||||
/// </summary>
|
||||
public class MeasurePoll : EventArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// 当前压力值
|
||||
/// </summary>
|
||||
public int Pressure;
|
||||
|
||||
public MeasurePoll(int pressure)
|
||||
{
|
||||
Pressure = pressure;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测量中压力上报
|
||||
/// </summary>
|
||||
public event EventHandler<MeasurePoll> MeasuringPoll;
|
||||
|
||||
#region - 通讯协议 -
|
||||
|
||||
/// <summary>
|
||||
/// 协议包
|
||||
/// </summary>
|
||||
/// <param name="type">类型标识</param>
|
||||
/// <param name="sub">类型子码</param>
|
||||
/// <param name="data">数据内容</param>
|
||||
/// <returns>包字节数组</returns>
|
||||
private static byte[] GetPackage(byte type, byte sub, byte data = 0)
|
||||
{
|
||||
var package = new byte[]
|
||||
{
|
||||
0xCC, 0x80, // 前导码
|
||||
0x03, // 设备版本
|
||||
0x03, // 数据长度
|
||||
type, // 类型标识
|
||||
sub, // 类型子码
|
||||
data, // 数据内容
|
||||
0x00 // 校验码(包头和校验除外的字节异或)
|
||||
};
|
||||
|
||||
byte xorsum = 0;
|
||||
for (var i = 2; i < package.Length - 1; i++)
|
||||
xorsum ^= package[i];
|
||||
|
||||
package[package.Length - 1] = xorsum;
|
||||
|
||||
return package;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 连接指令
|
||||
/// </summary>
|
||||
private static readonly byte[] PackageConnect = GetPackage((byte)TypeCode.BloodPressure, (byte)BloodPressureSubCode.Connect);
|
||||
|
||||
/// <summary>
|
||||
/// 启动指令
|
||||
/// </summary>
|
||||
private static readonly byte[] PackageStart = GetPackage((byte)TypeCode.BloodPressure, (byte)BloodPressureSubCode.Start);
|
||||
|
||||
/// <summary>
|
||||
/// 停止指令
|
||||
/// </summary>
|
||||
private static readonly byte[] PackageStop = GetPackage((byte)TypeCode.BloodPressure, (byte)BloodPressureSubCode.Stop);
|
||||
|
||||
/// <summary>
|
||||
/// 请求信号量,控制请求并发数
|
||||
/// </summary>
|
||||
private readonly SemaphoreSlim requestSemaphore = new SemaphoreSlim(1, 1);
|
||||
|
||||
/// <summary>
|
||||
/// 请求信号量集
|
||||
/// </summary>
|
||||
private readonly SemaphoreSlim[] RequestMap = new SemaphoreSlim[4];
|
||||
|
||||
/// <summary>
|
||||
/// 发送并等待响应,错误会以异常的方式抛出,需要捕获并处理异常!
|
||||
/// </summary>
|
||||
/// <param name="package">通讯包</param>
|
||||
/// <param name="code">请求代码</param>
|
||||
/// <exception cref="IOException">串口未打开时抛出</exception>
|
||||
/// <exception cref="TimeoutException">若等待响应超时时抛出</exception>
|
||||
private async Task RequestAsync(byte[] package, BloodPressureSubCode code)
|
||||
{
|
||||
if (!IsOpen)
|
||||
throw new IOException("通讯端口未连接,无法发送数据");
|
||||
|
||||
try
|
||||
{
|
||||
// 同时只能存在一个请求
|
||||
await requestSemaphore.WaitAsync();
|
||||
|
||||
var semaphore = new SemaphoreSlim(0);
|
||||
RequestMap[(int)code] = semaphore;
|
||||
|
||||
// 重试RetryMax次
|
||||
for (var tryCount = 1; tryCount <= RetryMax; tryCount++)
|
||||
{
|
||||
try
|
||||
{
|
||||
Write(package, 0, package.Length);
|
||||
if (await semaphore.WaitAsync(TryTimeoutMs))
|
||||
{
|
||||
// 正常响应,直接返回
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 超时,重试
|
||||
Console.WriteLine($"等待回复超时,正在重试第{tryCount}次");
|
||||
}
|
||||
}
|
||||
catch (TimeoutException) { } // 忽略超时异常
|
||||
catch (Exception ex)
|
||||
{
|
||||
// 发生异常时忽略,重试RetryMax次
|
||||
Console.WriteLine("等待响应时发生预期外的异常!" + ex);
|
||||
}
|
||||
}
|
||||
|
||||
Console.WriteLine("等待响应超时");
|
||||
// 未收到回复,抛出超时异常,报告等待响应超时
|
||||
throw new TimeoutException("等待响应超时");
|
||||
}
|
||||
finally
|
||||
{
|
||||
RequestMap[(int)code] = null;
|
||||
requestSemaphore.Release();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 包最小字节数,用以判断包是否完整
|
||||
/// </summary>
|
||||
private const int PackageMinSize = 5;
|
||||
|
||||
/// <summary>
|
||||
/// 串口收到数据时触发
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
|
||||
{
|
||||
var n = SerialPort.BytesToRead;
|
||||
Thread.Sleep(15);
|
||||
|
||||
// 等待接收剩余的数据
|
||||
while (n < SerialPort.BytesToRead)
|
||||
{
|
||||
n = SerialPort.BytesToRead;
|
||||
Thread.Sleep(15);
|
||||
}
|
||||
|
||||
// 读取到缓冲区
|
||||
var buf = new byte[n];
|
||||
// buf 为本次收到的报文消息
|
||||
Read(buf, 0, n);
|
||||
|
||||
Console.WriteLine("接收到数据:" + BitConverter.ToString(buf).Replace('-', ' ').ToUpper());
|
||||
|
||||
// 包头索引
|
||||
var i = 0;
|
||||
|
||||
// 寻找包开始
|
||||
findPackage:
|
||||
|
||||
// 找到包头
|
||||
while (i < n && (buf[i] != 0xAA || buf[i + 1] != 0x80))
|
||||
i++;
|
||||
if (n - i >= PackageMinSize) // 是否至少包含一个包
|
||||
{
|
||||
// 数据长度
|
||||
var dataLength = buf[i + 3];
|
||||
// 包长 = 数据长度 + 包头包尾长度
|
||||
var packageLength = dataLength + PackageMinSize;
|
||||
|
||||
if (i == 0 && packageLength == n)
|
||||
{
|
||||
if (CheckPackage(buf))
|
||||
{
|
||||
// 校验包完整后解析包内容
|
||||
OnReceivedPackage(buf);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 包校验失败
|
||||
Console.WriteLine("数据包校验失败!");
|
||||
i++; // 尝试寻找下一包
|
||||
goto findPackage;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (CheckPackage(buf, i, packageLength))
|
||||
{
|
||||
// 校验包完整后解析包内容
|
||||
var package = new byte[packageLength];
|
||||
Array.Copy(buf, i, package, 0, packageLength);
|
||||
OnReceivedPackage(package);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 包校验失败
|
||||
Console.WriteLine("数据包校验失败!");
|
||||
i++; // 尝试寻找下一包
|
||||
goto findPackage;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 未找到包头或者包不完整
|
||||
Console.WriteLine("不是有效的数据包!");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 校验包是否正常
|
||||
/// </summary>
|
||||
/// <param name="package">数据包</param>
|
||||
/// <returns>是否正常</returns>
|
||||
private static bool CheckPackage(byte[] package)
|
||||
=> CheckPackage(package, 0, package.Length);
|
||||
|
||||
/// <summary>
|
||||
/// 校验包是否正常
|
||||
/// </summary>
|
||||
/// <param name="package">数据包</param>
|
||||
/// <param name="offset">偏移</param>
|
||||
/// <param name="count">字节数</param>
|
||||
/// <returns>是否正常</returns>
|
||||
private static bool CheckPackage(byte[] package, int offset, int count)
|
||||
{
|
||||
var xorsum = 0;
|
||||
for (var i = offset + 2; i < count - 1; i++)
|
||||
xorsum ^= package[i];
|
||||
return xorsum == package[package.Length - 1];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 接收到完整包时触发
|
||||
/// </summary>
|
||||
/// <param name="package">包内容</param>
|
||||
private void OnReceivedPackage(byte[] package)
|
||||
{
|
||||
var index = 4;
|
||||
var type = (TypeCode)package[index++];
|
||||
var subType = package[index++];
|
||||
|
||||
if (type != TypeCode.BloodPressure)
|
||||
return; // 类型不是血压相关,忽略
|
||||
|
||||
// 根据子码做对应的处理
|
||||
switch ((BloodPressureSubCode)subType)
|
||||
{
|
||||
case BloodPressureSubCode.Connect: // 应答连接
|
||||
case BloodPressureSubCode.Start: // 应答启动
|
||||
case BloodPressureSubCode.Stop: // 应答停止
|
||||
RequestMap[subType]?.Release(); // 释放信号量
|
||||
break;
|
||||
|
||||
case BloodPressureSubCode.Poll: // 实时压力
|
||||
var pressure = (package[index++] << 8) | package[index];
|
||||
Console.WriteLine($"实时压力值:{pressure}");
|
||||
OnMeasuringPoll(pressure);
|
||||
break;
|
||||
|
||||
case BloodPressureSubCode.Result: // 测量结果
|
||||
var userId = package[index++].ToString();
|
||||
var measureTime = DateTime.Now;
|
||||
try
|
||||
{
|
||||
measureTime =
|
||||
// 测量时间 年-2000,月,日,时,分,秒
|
||||
new DateTime(package[index++] + 2000, package[index++], package[index++],
|
||||
package[index++], package[index++], package[index++]);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
|
||||
// 转换测量结果
|
||||
var result = new MeasureResult(
|
||||
// 用户标识
|
||||
userId,
|
||||
// 测量时间
|
||||
measureTime,
|
||||
// 收缩压
|
||||
(package[index++] << 8) | package[index++],
|
||||
// 舒张压
|
||||
(package[index++] << 8) | package[index++],
|
||||
// 脉搏数
|
||||
(package[index++] << 8) | package[index]);
|
||||
Console.WriteLine($"接收到测量结果:{result.MeasureTime}\t收缩压:{result.SystolicPressure}\t舒张压:{result.DiastolicPressure}\t脉搏数:{result.Pulse}");
|
||||
OnMeasureOver(result);
|
||||
break;
|
||||
|
||||
case BloodPressureSubCode.Error: // 发生错误
|
||||
var message = "未知错误";
|
||||
switch (package[index]) // 错误代码
|
||||
{
|
||||
case 1:
|
||||
message = "臂筒内上游气囊压力超过安全压力";
|
||||
break;
|
||||
|
||||
case 2:
|
||||
message = "测量中手臂放置不正确或臂筒内上游气囊漏气";
|
||||
break;
|
||||
|
||||
case 5:
|
||||
message = "测量中手臂放置不正确或臂筒内下游气囊漏气";
|
||||
break;
|
||||
|
||||
case 6:
|
||||
message = "手臂放置方式不正确或脉搏传感器无信号";
|
||||
break;
|
||||
|
||||
case 9:
|
||||
message = "臂筒内气囊放气时间过长";
|
||||
break;
|
||||
}
|
||||
|
||||
Console.WriteLine("接收到测量报错信息:" + message);
|
||||
OnMeasureOver(new MeasureResult(message));
|
||||
break;
|
||||
|
||||
default:
|
||||
// 未知的报文
|
||||
Console.WriteLine("未知的上报数据");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测量结束时调用
|
||||
/// </summary>
|
||||
/// <param name="result">测量结果</param>
|
||||
private void OnMeasureOver(MeasureResult result)
|
||||
=> MeasureOver?.Invoke(this, result);
|
||||
|
||||
/// <summary>
|
||||
/// 测量过程中上报压力时调用
|
||||
/// </summary>
|
||||
/// <param name="pressure">压力值</param>
|
||||
private void OnMeasuringPoll(int pressure)
|
||||
=> MeasuringPoll?.Invoke(this, new MeasurePoll(pressure));
|
||||
|
||||
/// <summary>
|
||||
/// 类型代码
|
||||
/// </summary>
|
||||
private enum TypeCode : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// 血压相关
|
||||
/// </summary>
|
||||
BloodPressure = 0x01,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 血压测量子码
|
||||
/// </summary>
|
||||
private enum BloodPressureSubCode : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// 连接
|
||||
/// </summary>
|
||||
Connect = 0x01,
|
||||
|
||||
/// <summary>
|
||||
/// 开始
|
||||
/// </summary>
|
||||
Start = 0x02,
|
||||
|
||||
/// <summary>
|
||||
/// 停止
|
||||
/// </summary>
|
||||
Stop = 0x03,
|
||||
|
||||
/// <summary>
|
||||
/// 测量过程上报
|
||||
/// </summary>
|
||||
Poll = 0x05,
|
||||
|
||||
/// <summary>
|
||||
/// 测量结果
|
||||
/// </summary>
|
||||
Result = 0x06,
|
||||
|
||||
/// <summary>
|
||||
/// 发生错误
|
||||
/// </summary>
|
||||
Error = 0x07,
|
||||
}
|
||||
|
||||
#endregion - 通讯协议 -
|
||||
}
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
namespace SphygmomanometerTester.Sphygmomanometer.MaiBoBo
|
||||
{
|
||||
public class RBP_9000c : MaiBoBo
|
||||
{
|
||||
}
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
namespace SphygmomanometerTester.Sphygmomanometer.MaiBoBo
|
||||
{
|
||||
public class RBP_9001 : MaiBoBo
|
||||
{
|
||||
}
|
||||
}
|
177
SphygmomanometerTester/Sphygmomanometer/OMRON/Omron.cs
Normal file
177
SphygmomanometerTester/Sphygmomanometer/OMRON/Omron.cs
Normal file
@ -0,0 +1,177 @@
|
||||
using System;
|
||||
using System.IO.Ports;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SphygmomanometerTester.Sphygmomanometer.OMRON
|
||||
{
|
||||
public class Omron : Sphygmomanometer
|
||||
{
|
||||
public Omron()
|
||||
{
|
||||
SerialPort.BaudRate = 2400;
|
||||
SerialPort.Parity = Parity.Even;
|
||||
SerialPort.DataBits = 7;
|
||||
SerialPort.StopBits = StopBits.One;
|
||||
|
||||
SerialPort.DataReceived += SerialPort_DataReceived;
|
||||
}
|
||||
|
||||
public override Task StartMeasure()
|
||||
{
|
||||
Write(PackageStart, 0, PackageStart.Length);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task RestartMeasure()
|
||||
{
|
||||
Write(PackageRestart, 0, PackageRestart.Length);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public override Task StopMeasure()
|
||||
{
|
||||
Write(PackageStop, 0, PackageStop.Length);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public override event EventHandler<MeasureResult> MeasureOver;
|
||||
|
||||
#region 通讯协议
|
||||
|
||||
/// <summary>
|
||||
/// 包起始标识
|
||||
/// </summary>
|
||||
private const byte StartTx = 0x02;
|
||||
|
||||
/// <summary>
|
||||
/// 包结束标识
|
||||
/// </summary>
|
||||
private const byte EndTx = 0x03;
|
||||
|
||||
/// <summary>
|
||||
/// 生成通讯报文
|
||||
/// </summary>
|
||||
/// <param name="payload">数据内容</param>
|
||||
/// <returns>通讯包</returns>
|
||||
private static byte[] GetPackage(byte payload) => new[] { StartTx, payload, EndTx };
|
||||
|
||||
/// <summary>
|
||||
/// 开始报文
|
||||
/// </summary>
|
||||
private static readonly byte[] PackageStart = GetPackage((byte)'S');
|
||||
|
||||
/// <summary>
|
||||
/// 结束报文
|
||||
/// </summary>
|
||||
private static readonly byte[] PackageStop = GetPackage((byte)'R');
|
||||
|
||||
/// <summary>
|
||||
/// 重新开始报文
|
||||
/// </summary>
|
||||
private static readonly byte[] PackageRestart = GetPackage((byte)'B');
|
||||
|
||||
/// <summary>
|
||||
/// 接受通讯缓冲区
|
||||
/// </summary>
|
||||
private readonly byte[] buffer = new byte[384];
|
||||
|
||||
/// <summary>
|
||||
/// 接收索引
|
||||
/// </summary>
|
||||
private int index;
|
||||
|
||||
/// <summary>
|
||||
/// 最后收到数据的时间
|
||||
/// </summary>
|
||||
private DateTime lastReceivedTime = DateTime.MinValue;
|
||||
|
||||
/// <summary>
|
||||
/// 串口收到数据时触发
|
||||
/// </summary>
|
||||
private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
|
||||
{
|
||||
var now = DateTime.Now;
|
||||
// 如果距离上次收到数据超过了300ms,清空输入缓冲区
|
||||
if ((now - lastReceivedTime).TotalMilliseconds > 300)
|
||||
index = 0;
|
||||
// 更新最后收到数据的时间
|
||||
lastReceivedTime = now;
|
||||
|
||||
// 接收数据
|
||||
index += Read(buffer, index, buffer.Length - index);
|
||||
|
||||
// 从收到的数据中找到合法的包
|
||||
var start = -1;
|
||||
for (var i = 0; i < index; i++)
|
||||
{
|
||||
if (start == -1)
|
||||
{
|
||||
// 找到包头
|
||||
if (buffer[i] == StartTx)
|
||||
{
|
||||
start = i;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 找到包尾
|
||||
if (buffer[i] == EndTx)
|
||||
{
|
||||
// 处理收到的数据
|
||||
var len = i - (start + 1);
|
||||
var data = new byte[len];
|
||||
Array.Copy(buffer, start + 1, data, 0, len);
|
||||
index = 0;
|
||||
OnDataReceived(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 当测量完成时触发
|
||||
/// </summary>
|
||||
/// <param name="data">测量结果报文数据</param>
|
||||
private void OnDataReceived(byte[] data)
|
||||
{
|
||||
// 返回的结果是一个ASCII字符串
|
||||
var msg = Encoding.ASCII.GetString(data);
|
||||
// 按照通讯协议,收到的是38个字节,开头是固定的ID9999999
|
||||
if (msg.Length != 38 || !msg.StartsWith("ID99999999"))
|
||||
return;
|
||||
|
||||
var year = msg.Substring(11, 2);
|
||||
var month = msg.Substring(14, 2);
|
||||
var day = msg.Substring(17, 2);
|
||||
var hour = msg.Substring(20, 2);
|
||||
var minute = msg.Substring(23, 2);
|
||||
if (!DateTime.TryParse($"20{year}/{month}/{day} {hour}:{minute}", out var time))
|
||||
time = DateTime.Now;
|
||||
var message = "";
|
||||
if (!int.TryParse(msg.Substring(26, 3), out var systolicPressure)
|
||||
| !int.TryParse(msg.Substring(31, 3), out var diastolicPressure)
|
||||
| !int.TryParse(msg.Substring(35, 3), out var pulse))
|
||||
{
|
||||
message = "没有数据,请调整姿势重新测量!";
|
||||
}
|
||||
|
||||
var result = message != "" ? new MeasureResult(message) : new MeasureResult(
|
||||
"99999999",
|
||||
time,
|
||||
systolicPressure,
|
||||
diastolicPressure,
|
||||
pulse);
|
||||
OnMeasureOver(result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测量结束时调用
|
||||
/// </summary>
|
||||
/// <param name="result">测量结果</param>
|
||||
private void OnMeasureOver(MeasureResult result)
|
||||
=> MeasureOver?.Invoke(this, result);
|
||||
|
||||
#endregion 通讯协议
|
||||
}
|
||||
}
|
82
SphygmomanometerTester/Sphygmomanometer/SerialControl.cs
Normal file
82
SphygmomanometerTester/Sphygmomanometer/SerialControl.cs
Normal file
@ -0,0 +1,82 @@
|
||||
using System;
|
||||
using System.IO.Ports;
|
||||
using System.Text;
|
||||
|
||||
namespace SphygmomanometerTester.Sphygmomanometer
|
||||
{
|
||||
public abstract class SerialControl
|
||||
{
|
||||
/// <summary>
|
||||
/// 串口对象
|
||||
/// </summary>
|
||||
protected readonly SerialPort SerialPort = new SerialPort();
|
||||
|
||||
public bool IsOpen => SerialPort.IsOpen;
|
||||
|
||||
/// <summary>
|
||||
/// 打开串口
|
||||
/// </summary>
|
||||
/// <param name="portName">端口号</param>
|
||||
/// <returns></returns>
|
||||
public void OpenCom(string portName)
|
||||
{
|
||||
if (SerialPort.IsOpen) return;
|
||||
FormMain.Instance.Log("打开串口 " + portName);
|
||||
SerialPort.PortName = portName;
|
||||
SerialPort.Open();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 关闭端口
|
||||
/// </summary>
|
||||
public void CloseCom()
|
||||
{
|
||||
if (!SerialPort.IsOpen) return;
|
||||
FormMain.Instance.Log("关闭串口");
|
||||
SerialPort.Close();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 字节到Hex字符串
|
||||
/// </summary>
|
||||
/// <param name="buffer">缓冲区</param>
|
||||
/// <param name="offset">偏移量</param>
|
||||
/// <param name="count">字节数</param>
|
||||
/// <returns>Hex字符串</returns>
|
||||
public static string BytesToHex(byte[] buffer, int offset, int count)
|
||||
{
|
||||
var result = string.Empty;
|
||||
for (var i = 0; i < count; i++)
|
||||
result += Convert.ToString(buffer[i + offset], 16)
|
||||
.ToUpper()
|
||||
.PadLeft(2, '0') + " ";
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 写入数据到串口
|
||||
/// </summary>
|
||||
/// <param name="buffer">缓冲区</param>
|
||||
/// <param name="offset">偏移量</param>
|
||||
/// <param name="count">字节数</param>
|
||||
public void Write(byte[] buffer, int offset, int count)
|
||||
{
|
||||
FormMain.Instance.Log("发送出:" + BytesToHex(buffer, offset, count) + " | " + Encoding.UTF8.GetString(buffer, offset, count));
|
||||
SerialPort.Write(buffer, offset, count);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从串口读取数据
|
||||
/// </summary>
|
||||
/// <param name="buffer">缓冲区</param>
|
||||
/// <param name="offset">偏移量</param>
|
||||
/// <param name="count">字节数</param>
|
||||
/// <returns>读取到的字节数</returns>
|
||||
public int Read(byte[] buffer, int offset, int count)
|
||||
{
|
||||
var n = SerialPort.Read(buffer, offset, count);
|
||||
FormMain.Instance.Log("接收到:" + BytesToHex(buffer, offset, n) + " | " + Encoding.UTF8.GetString(buffer, offset, n));
|
||||
return n;
|
||||
}
|
||||
}
|
||||
}
|
74
SphygmomanometerTester/Sphygmomanometer/Sphygmomanometer.cs
Normal file
74
SphygmomanometerTester/Sphygmomanometer/Sphygmomanometer.cs
Normal file
@ -0,0 +1,74 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SphygmomanometerTester.Sphygmomanometer
|
||||
{
|
||||
public abstract class Sphygmomanometer : SerialControl
|
||||
{
|
||||
/// <summary>
|
||||
/// 开始测量
|
||||
/// </summary>
|
||||
public abstract Task StartMeasure();
|
||||
|
||||
/// <summary>
|
||||
/// 提前结束测量
|
||||
/// </summary>
|
||||
public abstract Task StopMeasure();
|
||||
|
||||
/// <summary>
|
||||
/// 测量结束事件
|
||||
/// </summary>
|
||||
public abstract event EventHandler<MeasureResult> MeasureOver;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测量结果
|
||||
/// </summary>
|
||||
public class MeasureResult : EventArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// 用户标识
|
||||
/// </summary>
|
||||
public string UserId;
|
||||
|
||||
/// <summary>
|
||||
/// 测量时间
|
||||
/// </summary>
|
||||
public DateTime MeasureTime;
|
||||
|
||||
/// <summary>
|
||||
/// 收缩压
|
||||
/// </summary>
|
||||
public int SystolicPressure;
|
||||
|
||||
/// <summary>
|
||||
/// 舒张压
|
||||
/// </summary>
|
||||
public int DiastolicPressure;
|
||||
|
||||
/// <summary>
|
||||
/// 脉搏
|
||||
/// </summary>
|
||||
public int Pulse;
|
||||
|
||||
/// <summary>
|
||||
/// 消息,如果存在异常时设置,正常情况下为空
|
||||
/// </summary>
|
||||
public string Message;
|
||||
|
||||
public MeasureResult(string message)
|
||||
{
|
||||
UserId = string.Empty;
|
||||
Message = message;
|
||||
}
|
||||
|
||||
public MeasureResult(string userId, DateTime measureTime, int systolicPressure, int diastolicPressure, int pulse)
|
||||
{
|
||||
UserId = userId;
|
||||
MeasureTime = measureTime;
|
||||
SystolicPressure = systolicPressure;
|
||||
DiastolicPressure = diastolicPressure;
|
||||
Pulse = pulse;
|
||||
}
|
||||
}
|
||||
}
|
89
SphygmomanometerTester/SphygmomanometerTester.csproj
Normal file
89
SphygmomanometerTester/SphygmomanometerTester.csproj
Normal file
@ -0,0 +1,89 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<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>{8C5FDDD2-5EC5-4AD7-AB24-F87665872A95}</ProjectGuid>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<RootNamespace>SphygmomanometerTester</RootNamespace>
|
||||
<AssemblyName>SphygmomanometerTester</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
<Deterministic>true</Deterministic>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<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' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Deployment" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="FormMain.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="FormMain.Designer.cs">
|
||||
<DependentUpon>FormMain.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Sphygmomanometer\Sphygmomanometer.cs" />
|
||||
<Compile Include="Sphygmomanometer\MaiBoBo\MaiBoBo.cs" />
|
||||
<Compile Include="Sphygmomanometer\MaiBoBo\RBP-9000c.cs" />
|
||||
<Compile Include="Sphygmomanometer\MaiBoBo\RBP-9001.cs" />
|
||||
<Compile Include="Sphygmomanometer\OMRON\Omron.cs" />
|
||||
<Compile Include="Sphygmomanometer\SerialControl.cs" />
|
||||
<EmbeddedResource Include="FormMain.resx">
|
||||
<DependentUpon>FormMain.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Properties\Resources.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
<SubType>Designer</SubType>
|
||||
</EmbeddedResource>
|
||||
<Compile Include="Properties\Resources.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
</Compile>
|
||||
<None Include="Properties\Settings.settings">
|
||||
<Generator>SettingsSingleFileGenerator</Generator>
|
||||
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
|
||||
</None>
|
||||
<Compile Include="Properties\Settings.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Settings.settings</DependentUpon>
|
||||
<DesignTimeSharedInput>True</DesignTimeSharedInput>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
@ -0,0 +1,2 @@
|
||||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||
<s:String x:Key="/Default/CodeEditing/Localization/Localizable/@EntryValue">No</s:String></wpf:ResourceDictionary>
|
Loading…
Reference in New Issue
Block a user