diff --git a/SphygmomanometerTester.sln b/SphygmomanometerTester.sln
new file mode 100644
index 0000000..308e3b1
--- /dev/null
+++ b/SphygmomanometerTester.sln
@@ -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
diff --git a/SphygmomanometerTester/App.config b/SphygmomanometerTester/App.config
new file mode 100644
index 0000000..193aecc
--- /dev/null
+++ b/SphygmomanometerTester/App.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/SphygmomanometerTester/FormMain.Designer.cs b/SphygmomanometerTester/FormMain.Designer.cs
new file mode 100644
index 0000000..3d6555c
--- /dev/null
+++ b/SphygmomanometerTester/FormMain.Designer.cs
@@ -0,0 +1,553 @@
+namespace SphygmomanometerTester
+{
+ partial class FormMain
+ {
+ ///
+ /// 必需的设计器变量。
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// 清理所有正在使用的资源。
+ ///
+ /// 如果应释放托管资源,为 true;否则为 false。
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows 窗体设计器生成的代码
+
+ ///
+ /// 设计器支持所需的方法 - 不要修改
+ /// 使用代码编辑器修改此方法的内容。
+ ///
+ 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;
+ }
+}
+
diff --git a/SphygmomanometerTester/FormMain.cs b/SphygmomanometerTester/FormMain.cs
new file mode 100644
index 0000000..3698c07
--- /dev/null
+++ b/SphygmomanometerTester/FormMain.cs
@@ -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; }
+
+ ///
+ /// 血压计实例
+ ///
+ 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;
+ }
+
+ ///
+ /// 窗体加载时触发
+ ///
+ ///
+ protected override void OnLoad(EventArgs e)
+ {
+ base.OnLoad(e);
+ CmbSerialPortName.DataSource = SerialPort.GetPortNames();
+ UpdateControlButtons();
+ }
+
+ ///
+ /// 窗口关闭时触发
+ ///
+ 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 - 血压计事件 -
+
+ ///
+ /// 测量过程压力上报事件
+ ///
+ private void Sphygmomanometer_MeasuringPoll(object sender, MaiBoBo.MeasurePoll e)
+ {
+ BeginInvoke(new Action(() =>
+ {
+ LblPressureValue.Text = e.Pressure.ToString();
+ }));
+ }
+
+ ///
+ /// 测量结束事件
+ ///
+ 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 - 控制按钮 -
+
+ ///
+ /// 更新控制按钮状态
+ ///
+ 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;
+ }
+
+ ///
+ /// 刷新串口列表
+ ///
+ private void BtnUpdatePortNames_Click(object sender, EventArgs e)
+ {
+ CmbSerialPortName.DataSource = SerialPort.GetPortNames();
+ }
+
+ ///
+ /// 点击打开串口
+ ///
+ 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();
+ }
+
+ ///
+ /// 点击关闭串口
+ ///
+ private void BtnClosePort_Click(object sender, EventArgs e)
+ {
+ Log("关闭串口");
+ sphygmomanometer.CloseCom();
+ UpdateControlButtons();
+ }
+
+ ///
+ /// 点击测试连接按钮
+ ///
+ 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;
+ }
+ }
+
+ ///
+ /// 点击开始测量按钮
+ ///
+ 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;
+ }
+ }
+
+ ///
+ /// 点击停止测量按钮
+ ///
+ 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;
+ }
+ }
+
+ ///
+ /// 检查并启动循环
+ ///
+ 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;
+
+ ///
+ /// 循环测试复选框改变事件
+ ///
+ 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 - 日志 -
+
+ ///
+ /// 写日志到文本框
+ ///
+ ///
+ public void Log(string message)
+ {
+ if (InvokeRequired)
+ {
+ Invoke(new Action(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 - 工具 -
+
+ ///
+ /// 按钮OK动画
+ ///
+ ///
+ ///
+ 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 - 重置统计 -
+
+ ///
+ /// 测试次数
+ ///
+ private int TestCount;
+
+ ///
+ /// 测试成功次数
+ ///
+ private int TestSuccessCount;
+
+ ///
+ /// 测试失败次数
+ ///
+ private int TestFailedCount;
+
+ ///
+ /// 点击重置统计按钮
+ ///
+ private void BtnResetStat_Click(object sender, EventArgs e)
+ {
+ TestCount = 0;
+ TestSuccessCount = 0;
+ TestFailedCount = 0;
+ UpdateStat();
+ }
+
+ ///
+ /// 更新统计
+ ///
+ private void UpdateStat()
+ {
+ if (InvokeRequired)
+ Invoke(new Action(UpdateStat));
+ else
+ {
+ LblTestCount.Text = TestCount.ToString();
+ LblTestSuccessCount.Text = TestSuccessCount.ToString();
+ LblTestFailedCount.Text = TestFailedCount.ToString();
+ }
+ }
+
+ ///
+ /// 统计开始测试
+ ///
+ private void StatBeginTest()
+ {
+ TestCount += 1;
+ UpdateStat();
+ }
+
+ ///
+ /// 统计测试结束
+ ///
+ /// 测试是否成功
+ private void StatEndTest(bool isSuccess)
+ {
+ if (isSuccess) TestSuccessCount++;
+ else TestFailedCount++;
+ UpdateStat();
+ }
+
+ #endregion - 重置统计 -
+ }
+}
\ No newline at end of file
diff --git a/SphygmomanometerTester/FormMain.resx b/SphygmomanometerTester/FormMain.resx
new file mode 100644
index 0000000..1af7de1
--- /dev/null
+++ b/SphygmomanometerTester/FormMain.resx
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/SphygmomanometerTester/Program.cs b/SphygmomanometerTester/Program.cs
new file mode 100644
index 0000000..718a599
--- /dev/null
+++ b/SphygmomanometerTester/Program.cs
@@ -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
+ {
+ ///
+ /// 应用程序的主入口点。
+ ///
+ [STAThread]
+ static void Main()
+ {
+ Application.EnableVisualStyles();
+ Application.SetCompatibleTextRenderingDefault(false);
+ Application.Run(new FormMain());
+ }
+ }
+}
diff --git a/SphygmomanometerTester/Properties/AssemblyInfo.cs b/SphygmomanometerTester/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..a780f69
--- /dev/null
+++ b/SphygmomanometerTester/Properties/AssemblyInfo.cs
@@ -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")]
diff --git a/SphygmomanometerTester/Properties/Resources.Designer.cs b/SphygmomanometerTester/Properties/Resources.Designer.cs
new file mode 100644
index 0000000..28c48a4
--- /dev/null
+++ b/SphygmomanometerTester/Properties/Resources.Designer.cs
@@ -0,0 +1,71 @@
+//------------------------------------------------------------------------------
+//
+// 此代码由工具生成。
+// 运行时版本: 4.0.30319.42000
+//
+// 对此文件的更改可能导致不正确的行为,如果
+// 重新生成代码,则所做更改将丢失。
+//
+//------------------------------------------------------------------------------
+
+namespace SphygmomanometerTester.Properties
+{
+
+
+ ///
+ /// 强类型资源类,用于查找本地化字符串等。
+ ///
+ // 此类是由 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()
+ {
+ }
+
+ ///
+ /// 返回此类使用的缓存 ResourceManager 实例。
+ ///
+ [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;
+ }
+ }
+
+ ///
+ /// 重写当前线程的 CurrentUICulture 属性,对
+ /// 使用此强类型资源类的所有资源查找执行重写。
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture
+ {
+ get
+ {
+ return resourceCulture;
+ }
+ set
+ {
+ resourceCulture = value;
+ }
+ }
+ }
+}
diff --git a/SphygmomanometerTester/Properties/Resources.resx b/SphygmomanometerTester/Properties/Resources.resx
new file mode 100644
index 0000000..af7dbeb
--- /dev/null
+++ b/SphygmomanometerTester/Properties/Resources.resx
@@ -0,0 +1,117 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/SphygmomanometerTester/Properties/Settings.Designer.cs b/SphygmomanometerTester/Properties/Settings.Designer.cs
new file mode 100644
index 0000000..bd5ff01
--- /dev/null
+++ b/SphygmomanometerTester/Properties/Settings.Designer.cs
@@ -0,0 +1,30 @@
+//------------------------------------------------------------------------------
+//
+// 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.
+//
+//------------------------------------------------------------------------------
+
+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;
+ }
+ }
+ }
+}
diff --git a/SphygmomanometerTester/Properties/Settings.settings b/SphygmomanometerTester/Properties/Settings.settings
new file mode 100644
index 0000000..3964565
--- /dev/null
+++ b/SphygmomanometerTester/Properties/Settings.settings
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/SphygmomanometerTester/Sphygmomanometer/MaiBoBo/MaiBoBo.cs b/SphygmomanometerTester/Sphygmomanometer/MaiBoBo/MaiBoBo.cs
new file mode 100644
index 0000000..7232480
--- /dev/null
+++ b/SphygmomanometerTester/Sphygmomanometer/MaiBoBo/MaiBoBo.cs
@@ -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;
+ }
+
+ ///
+ /// 通讯尝试超时时间(毫秒)
+ ///
+ private const int TryTimeoutMs = 200;
+
+ ///
+ /// 最大重试次数
+ ///
+ 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 MeasureOver;
+
+ ///
+ /// 测量中报告
+ ///
+ public class MeasurePoll : EventArgs
+ {
+ ///
+ /// 当前压力值
+ ///
+ public int Pressure;
+
+ public MeasurePoll(int pressure)
+ {
+ Pressure = pressure;
+ }
+ }
+
+ ///
+ /// 测量中压力上报
+ ///
+ public event EventHandler MeasuringPoll;
+
+ #region - 通讯协议 -
+
+ ///
+ /// 协议包
+ ///
+ /// 类型标识
+ /// 类型子码
+ /// 数据内容
+ /// 包字节数组
+ 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;
+ }
+
+ ///
+ /// 连接指令
+ ///
+ private static readonly byte[] PackageConnect = GetPackage((byte)TypeCode.BloodPressure, (byte)BloodPressureSubCode.Connect);
+
+ ///
+ /// 启动指令
+ ///
+ private static readonly byte[] PackageStart = GetPackage((byte)TypeCode.BloodPressure, (byte)BloodPressureSubCode.Start);
+
+ ///
+ /// 停止指令
+ ///
+ private static readonly byte[] PackageStop = GetPackage((byte)TypeCode.BloodPressure, (byte)BloodPressureSubCode.Stop);
+
+ ///
+ /// 请求信号量,控制请求并发数
+ ///
+ private readonly SemaphoreSlim requestSemaphore = new SemaphoreSlim(1, 1);
+
+ ///
+ /// 请求信号量集
+ ///
+ private readonly SemaphoreSlim[] RequestMap = new SemaphoreSlim[4];
+
+ ///
+ /// 发送并等待响应,错误会以异常的方式抛出,需要捕获并处理异常!
+ ///
+ /// 通讯包
+ /// 请求代码
+ /// 串口未打开时抛出
+ /// 若等待响应超时时抛出
+ 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();
+ }
+ }
+
+ ///
+ /// 包最小字节数,用以判断包是否完整
+ ///
+ private const int PackageMinSize = 5;
+
+ ///
+ /// 串口收到数据时触发
+ ///
+ ///
+ ///
+ 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("不是有效的数据包!");
+ }
+ }
+
+ ///
+ /// 校验包是否正常
+ ///
+ /// 数据包
+ /// 是否正常
+ private static bool CheckPackage(byte[] package)
+ => CheckPackage(package, 0, package.Length);
+
+ ///
+ /// 校验包是否正常
+ ///
+ /// 数据包
+ /// 偏移
+ /// 字节数
+ /// 是否正常
+ 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];
+ }
+
+ ///
+ /// 接收到完整包时触发
+ ///
+ /// 包内容
+ 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;
+ }
+ }
+
+ ///
+ /// 测量结束时调用
+ ///
+ /// 测量结果
+ private void OnMeasureOver(MeasureResult result)
+ => MeasureOver?.Invoke(this, result);
+
+ ///
+ /// 测量过程中上报压力时调用
+ ///
+ /// 压力值
+ private void OnMeasuringPoll(int pressure)
+ => MeasuringPoll?.Invoke(this, new MeasurePoll(pressure));
+
+ ///
+ /// 类型代码
+ ///
+ private enum TypeCode : byte
+ {
+ ///
+ /// 血压相关
+ ///
+ BloodPressure = 0x01,
+ }
+
+ ///
+ /// 血压测量子码
+ ///
+ private enum BloodPressureSubCode : byte
+ {
+ ///
+ /// 连接
+ ///
+ Connect = 0x01,
+
+ ///
+ /// 开始
+ ///
+ Start = 0x02,
+
+ ///
+ /// 停止
+ ///
+ Stop = 0x03,
+
+ ///
+ /// 测量过程上报
+ ///
+ Poll = 0x05,
+
+ ///
+ /// 测量结果
+ ///
+ Result = 0x06,
+
+ ///
+ /// 发生错误
+ ///
+ Error = 0x07,
+ }
+
+ #endregion - 通讯协议 -
+ }
+}
\ No newline at end of file
diff --git a/SphygmomanometerTester/Sphygmomanometer/MaiBoBo/RBP-9000c.cs b/SphygmomanometerTester/Sphygmomanometer/MaiBoBo/RBP-9000c.cs
new file mode 100644
index 0000000..d60abc7
--- /dev/null
+++ b/SphygmomanometerTester/Sphygmomanometer/MaiBoBo/RBP-9000c.cs
@@ -0,0 +1,6 @@
+namespace SphygmomanometerTester.Sphygmomanometer.MaiBoBo
+{
+ public class RBP_9000c : MaiBoBo
+ {
+ }
+}
diff --git a/SphygmomanometerTester/Sphygmomanometer/MaiBoBo/RBP-9001.cs b/SphygmomanometerTester/Sphygmomanometer/MaiBoBo/RBP-9001.cs
new file mode 100644
index 0000000..f49c9cb
--- /dev/null
+++ b/SphygmomanometerTester/Sphygmomanometer/MaiBoBo/RBP-9001.cs
@@ -0,0 +1,6 @@
+namespace SphygmomanometerTester.Sphygmomanometer.MaiBoBo
+{
+ public class RBP_9001 : MaiBoBo
+ {
+ }
+}
diff --git a/SphygmomanometerTester/Sphygmomanometer/OMRON/Omron.cs b/SphygmomanometerTester/Sphygmomanometer/OMRON/Omron.cs
new file mode 100644
index 0000000..0833a2f
--- /dev/null
+++ b/SphygmomanometerTester/Sphygmomanometer/OMRON/Omron.cs
@@ -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 MeasureOver;
+
+ #region 通讯协议
+
+ ///
+ /// 包起始标识
+ ///
+ private const byte StartTx = 0x02;
+
+ ///
+ /// 包结束标识
+ ///
+ private const byte EndTx = 0x03;
+
+ ///
+ /// 生成通讯报文
+ ///
+ /// 数据内容
+ /// 通讯包
+ private static byte[] GetPackage(byte payload) => new[] { StartTx, payload, EndTx };
+
+ ///
+ /// 开始报文
+ ///
+ private static readonly byte[] PackageStart = GetPackage((byte)'S');
+
+ ///
+ /// 结束报文
+ ///
+ private static readonly byte[] PackageStop = GetPackage((byte)'R');
+
+ ///
+ /// 重新开始报文
+ ///
+ private static readonly byte[] PackageRestart = GetPackage((byte)'B');
+
+ ///
+ /// 接受通讯缓冲区
+ ///
+ private readonly byte[] buffer = new byte[384];
+
+ ///
+ /// 接收索引
+ ///
+ private int index;
+
+ ///
+ /// 最后收到数据的时间
+ ///
+ private DateTime lastReceivedTime = DateTime.MinValue;
+
+ ///
+ /// 串口收到数据时触发
+ ///
+ 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);
+ }
+ }
+ }
+ }
+
+ ///
+ /// 当测量完成时触发
+ ///
+ /// 测量结果报文数据
+ 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);
+ }
+
+ ///
+ /// 测量结束时调用
+ ///
+ /// 测量结果
+ private void OnMeasureOver(MeasureResult result)
+ => MeasureOver?.Invoke(this, result);
+
+ #endregion 通讯协议
+ }
+}
\ No newline at end of file
diff --git a/SphygmomanometerTester/Sphygmomanometer/SerialControl.cs b/SphygmomanometerTester/Sphygmomanometer/SerialControl.cs
new file mode 100644
index 0000000..75c2f90
--- /dev/null
+++ b/SphygmomanometerTester/Sphygmomanometer/SerialControl.cs
@@ -0,0 +1,82 @@
+using System;
+using System.IO.Ports;
+using System.Text;
+
+namespace SphygmomanometerTester.Sphygmomanometer
+{
+ public abstract class SerialControl
+ {
+ ///
+ /// 串口对象
+ ///
+ protected readonly SerialPort SerialPort = new SerialPort();
+
+ public bool IsOpen => SerialPort.IsOpen;
+
+ ///
+ /// 打开串口
+ ///
+ /// 端口号
+ ///
+ public void OpenCom(string portName)
+ {
+ if (SerialPort.IsOpen) return;
+ FormMain.Instance.Log("打开串口 " + portName);
+ SerialPort.PortName = portName;
+ SerialPort.Open();
+ }
+
+ ///
+ /// 关闭端口
+ ///
+ public void CloseCom()
+ {
+ if (!SerialPort.IsOpen) return;
+ FormMain.Instance.Log("关闭串口");
+ SerialPort.Close();
+ }
+
+ ///
+ /// 字节到Hex字符串
+ ///
+ /// 缓冲区
+ /// 偏移量
+ /// 字节数
+ /// Hex字符串
+ 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;
+ }
+
+ ///
+ /// 写入数据到串口
+ ///
+ /// 缓冲区
+ /// 偏移量
+ /// 字节数
+ 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);
+ }
+
+ ///
+ /// 从串口读取数据
+ ///
+ /// 缓冲区
+ /// 偏移量
+ /// 字节数
+ /// 读取到的字节数
+ 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;
+ }
+ }
+}
\ No newline at end of file
diff --git a/SphygmomanometerTester/Sphygmomanometer/Sphygmomanometer.cs b/SphygmomanometerTester/Sphygmomanometer/Sphygmomanometer.cs
new file mode 100644
index 0000000..41e6fc1
--- /dev/null
+++ b/SphygmomanometerTester/Sphygmomanometer/Sphygmomanometer.cs
@@ -0,0 +1,74 @@
+using System;
+using System.Threading.Tasks;
+
+namespace SphygmomanometerTester.Sphygmomanometer
+{
+ public abstract class Sphygmomanometer : SerialControl
+ {
+ ///
+ /// 开始测量
+ ///
+ public abstract Task StartMeasure();
+
+ ///
+ /// 提前结束测量
+ ///
+ public abstract Task StopMeasure();
+
+ ///
+ /// 测量结束事件
+ ///
+ public abstract event EventHandler MeasureOver;
+ }
+
+ ///
+ /// 测量结果
+ ///
+ public class MeasureResult : EventArgs
+ {
+ ///
+ /// 用户标识
+ ///
+ public string UserId;
+
+ ///
+ /// 测量时间
+ ///
+ public DateTime MeasureTime;
+
+ ///
+ /// 收缩压
+ ///
+ public int SystolicPressure;
+
+ ///
+ /// 舒张压
+ ///
+ public int DiastolicPressure;
+
+ ///
+ /// 脉搏
+ ///
+ public int Pulse;
+
+ ///
+ /// 消息,如果存在异常时设置,正常情况下为空
+ ///
+ 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;
+ }
+ }
+}
\ No newline at end of file
diff --git a/SphygmomanometerTester/SphygmomanometerTester.csproj b/SphygmomanometerTester/SphygmomanometerTester.csproj
new file mode 100644
index 0000000..515ba84
--- /dev/null
+++ b/SphygmomanometerTester/SphygmomanometerTester.csproj
@@ -0,0 +1,89 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {8C5FDDD2-5EC5-4AD7-AB24-F87665872A95}
+ WinExe
+ SphygmomanometerTester
+ SphygmomanometerTester
+ v4.8
+ 512
+ true
+ true
+
+
+ AnyCPU
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Form
+
+
+ FormMain.cs
+
+
+
+
+
+
+
+
+
+
+ FormMain.cs
+
+
+ ResXFileCodeGenerator
+ Resources.Designer.cs
+ Designer
+
+
+ True
+ Resources.resx
+
+
+ SettingsSingleFileGenerator
+ Settings.Designer.cs
+
+
+ True
+ Settings.settings
+ True
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/SphygmomanometerTester/SphygmomanometerTester.csproj.DotSettings b/SphygmomanometerTester/SphygmomanometerTester.csproj.DotSettings
new file mode 100644
index 0000000..6e7fff8
--- /dev/null
+++ b/SphygmomanometerTester/SphygmomanometerTester.csproj.DotSettings
@@ -0,0 +1,2 @@
+
+ No
\ No newline at end of file