添加项目文件。

This commit is contained in:
2023-03-15 11:11:28 +08:00
parent 5cd2a3329a
commit 3211d1431b
19 changed files with 2295 additions and 0 deletions

View 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

View 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>

View 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;
}
}

View 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 - -
}
}

View 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>

View 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());
}
}
}

View 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")]

View 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;
}
}
}
}

View 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>

View 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;
}
}
}
}

View 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>

View 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 - -
}
}

View File

@ -0,0 +1,6 @@
namespace SphygmomanometerTester.Sphygmomanometer.MaiBoBo
{
public class RBP_9000c : MaiBoBo
{
}
}

View File

@ -0,0 +1,6 @@
namespace SphygmomanometerTester.Sphygmomanometer.MaiBoBo
{
public class RBP_9001 : MaiBoBo
{
}
}

View 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
}
}

View 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;
}
}
}

View 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;
}
}
}

View 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>

View File

@ -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>