谱仪数据处理逻辑
上传逻辑
This commit is contained in:
parent
47c339f1b3
commit
d21391fb0c
486
Form1.Designer.cs
generated
486
Form1.Designer.cs
generated
@ -22,333 +22,273 @@ partial class Form1
|
|||||||
|
|
||||||
#region Windows Form Designer generated code
|
#region Windows Form Designer generated code
|
||||||
|
|
||||||
|
private System.Windows.Forms.GroupBox groupBoxGPS;
|
||||||
|
private System.Windows.Forms.ComboBox comboBoxGPSPort;
|
||||||
|
private System.Windows.Forms.Label labelGPSPort;
|
||||||
|
private System.Windows.Forms.GroupBox groupBoxSpectrometer;
|
||||||
|
private System.Windows.Forms.NumericUpDown numericUpDownRefreshInterval;
|
||||||
|
private System.Windows.Forms.Label labelRefreshInterval;
|
||||||
|
private System.Windows.Forms.ComboBox comboBoxSpectrometerPort;
|
||||||
|
private System.Windows.Forms.Label labelSpectrometerPort;
|
||||||
|
private System.Windows.Forms.GroupBox groupBoxMQTT;
|
||||||
|
private System.Windows.Forms.TextBox textBoxDeviceSecret;
|
||||||
|
private System.Windows.Forms.Label labelDeviceSecret;
|
||||||
|
private System.Windows.Forms.TextBox textBoxDeviceName;
|
||||||
|
private System.Windows.Forms.Label labelDeviceName;
|
||||||
|
private System.Windows.Forms.TextBox textBoxTopicRoot;
|
||||||
|
private System.Windows.Forms.Label labelTopicRoot;
|
||||||
|
private System.Windows.Forms.TextBox textBoxProductKey;
|
||||||
|
private System.Windows.Forms.Label labelProductKey;
|
||||||
|
private System.Windows.Forms.Button buttonStartStop;
|
||||||
|
private System.Windows.Forms.TextBox textBoxLog;
|
||||||
|
private System.Windows.Forms.Label labelLog;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Required method for Designer support - do not modify
|
/// Required method for Designer support - do not modify
|
||||||
/// the contents of this method with the code editor.
|
/// the contents of this method with the code editor.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void InitializeComponent()
|
private void InitializeComponent()
|
||||||
{
|
{
|
||||||
this.groupBox1 = new System.Windows.Forms.GroupBox();
|
this.groupBoxGPS = new System.Windows.Forms.GroupBox();
|
||||||
this.cmbPort1 = new System.Windows.Forms.ComboBox();
|
this.comboBoxGPSPort = new System.Windows.Forms.ComboBox();
|
||||||
this.cmbBaud1 = new System.Windows.Forms.ComboBox();
|
this.labelGPSPort = new System.Windows.Forms.Label();
|
||||||
this.btnConnect1 = new System.Windows.Forms.Button();
|
this.groupBoxSpectrometer = new System.Windows.Forms.GroupBox();
|
||||||
this.lblPort1 = new System.Windows.Forms.Label();
|
this.numericUpDownRefreshInterval = new System.Windows.Forms.NumericUpDown();
|
||||||
this.lblBaud1 = new System.Windows.Forms.Label();
|
this.labelRefreshInterval = new System.Windows.Forms.Label();
|
||||||
this.groupBox2 = new System.Windows.Forms.GroupBox();
|
this.comboBoxSpectrometerPort = new System.Windows.Forms.ComboBox();
|
||||||
this.cmbPort2 = new System.Windows.Forms.ComboBox();
|
this.labelSpectrometerPort = new System.Windows.Forms.Label();
|
||||||
this.cmbBaud2 = new System.Windows.Forms.ComboBox();
|
this.groupBoxMQTT = new System.Windows.Forms.GroupBox();
|
||||||
this.btnConnect2 = new System.Windows.Forms.Button();
|
this.textBoxDeviceSecret = new System.Windows.Forms.TextBox();
|
||||||
this.lblPort2 = new System.Windows.Forms.Label();
|
this.labelDeviceSecret = new System.Windows.Forms.Label();
|
||||||
this.lblBaud2 = new System.Windows.Forms.Label();
|
this.textBoxDeviceName = new System.Windows.Forms.TextBox();
|
||||||
this.groupBox3 = new System.Windows.Forms.GroupBox();
|
this.labelDeviceName = new System.Windows.Forms.Label();
|
||||||
this.txtUrl = new System.Windows.Forms.TextBox();
|
this.textBoxTopicRoot = new System.Windows.Forms.TextBox();
|
||||||
this.lblUrl = new System.Windows.Forms.Label();
|
this.labelTopicRoot = new System.Windows.Forms.Label();
|
||||||
this.btnStartUpload = new System.Windows.Forms.Button();
|
this.textBoxProductKey = new System.Windows.Forms.TextBox();
|
||||||
this.btnStopUpload = new System.Windows.Forms.Button();
|
this.labelProductKey = new System.Windows.Forms.Label();
|
||||||
this.groupBox4 = new System.Windows.Forms.GroupBox();
|
this.buttonStartStop = new System.Windows.Forms.Button();
|
||||||
this.txtLog = new System.Windows.Forms.TextBox();
|
this.textBoxLog = new System.Windows.Forms.TextBox();
|
||||||
this.btnClearLog = new System.Windows.Forms.Button();
|
this.labelLog = new System.Windows.Forms.Label();
|
||||||
this.btnSaveLog = new System.Windows.Forms.Button();
|
this.groupBoxGPS.SuspendLayout();
|
||||||
this.statusStrip1 = new System.Windows.Forms.StatusStrip();
|
this.groupBoxSpectrometer.SuspendLayout();
|
||||||
this.toolStripStatusLabel1 = new System.Windows.Forms.ToolStripStatusLabel();
|
((System.ComponentModel.ISupportInitialize)(this.numericUpDownRefreshInterval)).BeginInit();
|
||||||
this.groupBox1.SuspendLayout();
|
this.groupBoxMQTT.SuspendLayout();
|
||||||
this.groupBox2.SuspendLayout();
|
|
||||||
this.groupBox3.SuspendLayout();
|
|
||||||
this.groupBox4.SuspendLayout();
|
|
||||||
this.statusStrip1.SuspendLayout();
|
|
||||||
this.SuspendLayout();
|
this.SuspendLayout();
|
||||||
//
|
//
|
||||||
// groupBox1
|
// groupBoxGPS
|
||||||
//
|
//
|
||||||
this.groupBox1.Controls.Add(this.lblBaud1);
|
this.groupBoxGPS.Controls.Add(this.comboBoxGPSPort);
|
||||||
this.groupBox1.Controls.Add(this.lblPort1);
|
this.groupBoxGPS.Controls.Add(this.labelGPSPort);
|
||||||
this.groupBox1.Controls.Add(this.btnConnect1);
|
this.groupBoxGPS.Location = new System.Drawing.Point(12, 12);
|
||||||
this.groupBox1.Controls.Add(this.cmbBaud1);
|
this.groupBoxGPS.Name = "groupBoxGPS";
|
||||||
this.groupBox1.Controls.Add(this.cmbPort1);
|
this.groupBoxGPS.Size = new System.Drawing.Size(200, 80);
|
||||||
this.groupBox1.Location = new System.Drawing.Point(12, 12);
|
this.groupBoxGPS.TabIndex = 0;
|
||||||
this.groupBox1.Name = "groupBox1";
|
this.groupBoxGPS.TabStop = false;
|
||||||
this.groupBox1.Size = new System.Drawing.Size(200, 120);
|
this.groupBoxGPS.Text = "GPS设置";
|
||||||
this.groupBox1.TabIndex = 0;
|
|
||||||
this.groupBox1.TabStop = false;
|
|
||||||
this.groupBox1.Text = "串口1";
|
|
||||||
//
|
//
|
||||||
// cmbPort1
|
// comboBoxGPSPort
|
||||||
//
|
//
|
||||||
this.cmbPort1.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
|
this.comboBoxGPSPort.FormattingEnabled = true;
|
||||||
this.cmbPort1.FormattingEnabled = true;
|
this.comboBoxGPSPort.Location = new System.Drawing.Point(70, 30);
|
||||||
this.cmbPort1.Location = new System.Drawing.Point(60, 25);
|
this.comboBoxGPSPort.Name = "comboBoxGPSPort";
|
||||||
this.cmbPort1.Name = "cmbPort1";
|
this.comboBoxGPSPort.Size = new System.Drawing.Size(121, 28);
|
||||||
this.cmbPort1.Size = new System.Drawing.Size(121, 23);
|
this.comboBoxGPSPort.TabIndex = 1;
|
||||||
this.cmbPort1.TabIndex = 0;
|
|
||||||
//
|
//
|
||||||
// cmbBaud1
|
// labelGPSPort
|
||||||
//
|
//
|
||||||
this.cmbBaud1.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
|
this.labelGPSPort.AutoSize = true;
|
||||||
this.cmbBaud1.FormattingEnabled = true;
|
this.labelGPSPort.Location = new System.Drawing.Point(6, 33);
|
||||||
this.cmbBaud1.Items.AddRange(new object[] {
|
this.labelGPSPort.Name = "labelGPSPort";
|
||||||
"9600",
|
this.labelGPSPort.Size = new System.Drawing.Size(54, 20);
|
||||||
"19200",
|
this.labelGPSPort.TabIndex = 0;
|
||||||
"38400",
|
this.labelGPSPort.Text = "串口:";
|
||||||
"57600",
|
|
||||||
"115200"});
|
|
||||||
this.cmbBaud1.Location = new System.Drawing.Point(60, 54);
|
|
||||||
this.cmbBaud1.Name = "cmbBaud1";
|
|
||||||
this.cmbBaud1.Size = new System.Drawing.Size(121, 23);
|
|
||||||
this.cmbBaud1.TabIndex = 1;
|
|
||||||
//
|
//
|
||||||
// btnConnect1
|
// groupBoxSpectrometer
|
||||||
//
|
//
|
||||||
this.btnConnect1.Location = new System.Drawing.Point(60, 83);
|
this.groupBoxSpectrometer.Controls.Add(this.numericUpDownRefreshInterval);
|
||||||
this.btnConnect1.Name = "btnConnect1";
|
this.groupBoxSpectrometer.Controls.Add(this.labelRefreshInterval);
|
||||||
this.btnConnect1.Size = new System.Drawing.Size(75, 23);
|
this.groupBoxSpectrometer.Controls.Add(this.comboBoxSpectrometerPort);
|
||||||
this.btnConnect1.TabIndex = 2;
|
this.groupBoxSpectrometer.Controls.Add(this.labelSpectrometerPort);
|
||||||
this.btnConnect1.Text = "连接";
|
this.groupBoxSpectrometer.Location = new System.Drawing.Point(230, 12);
|
||||||
this.btnConnect1.UseVisualStyleBackColor = true;
|
this.groupBoxSpectrometer.Name = "groupBoxSpectrometer";
|
||||||
this.btnConnect1.Click += new System.EventHandler(this.btnConnect1_Click);
|
this.groupBoxSpectrometer.Size = new System.Drawing.Size(250, 80);
|
||||||
|
this.groupBoxSpectrometer.TabIndex = 1;
|
||||||
|
this.groupBoxSpectrometer.TabStop = false;
|
||||||
|
this.groupBoxSpectrometer.Text = "谱仪设置";
|
||||||
//
|
//
|
||||||
// lblPort1
|
// numericUpDownRefreshInterval
|
||||||
//
|
//
|
||||||
this.lblPort1.AutoSize = true;
|
this.numericUpDownRefreshInterval.Location = new System.Drawing.Point(190, 50);
|
||||||
this.lblPort1.Location = new System.Drawing.Point(15, 28);
|
this.numericUpDownRefreshInterval.Maximum = new decimal(new int[] { 60, 0, 0, 0 });
|
||||||
this.lblPort1.Name = "lblPort1";
|
this.numericUpDownRefreshInterval.Minimum = new decimal(new int[] { 1, 0, 0, 0 });
|
||||||
this.lblPort1.Size = new System.Drawing.Size(32, 15);
|
this.numericUpDownRefreshInterval.Name = "numericUpDownRefreshInterval";
|
||||||
this.lblPort1.TabIndex = 3;
|
this.numericUpDownRefreshInterval.Size = new System.Drawing.Size(50, 27);
|
||||||
this.lblPort1.Text = "端口";
|
this.numericUpDownRefreshInterval.TabIndex = 3;
|
||||||
|
this.numericUpDownRefreshInterval.Value = new decimal(new int[] { 1, 0, 0, 0 });
|
||||||
//
|
//
|
||||||
// lblBaud1
|
// labelRefreshInterval
|
||||||
//
|
//
|
||||||
this.lblBaud1.AutoSize = true;
|
this.labelRefreshInterval.AutoSize = true;
|
||||||
this.lblBaud1.Location = new System.Drawing.Point(15, 57);
|
this.labelRefreshInterval.Location = new System.Drawing.Point(6, 52);
|
||||||
this.lblBaud1.Name = "lblBaud1";
|
this.labelRefreshInterval.Name = "labelRefreshInterval";
|
||||||
this.lblBaud1.Size = new System.Drawing.Size(44, 15);
|
this.labelRefreshInterval.Size = new System.Drawing.Size(178, 20);
|
||||||
this.lblBaud1.TabIndex = 4;
|
this.labelRefreshInterval.TabIndex = 2;
|
||||||
this.lblBaud1.Text = "波特率";
|
this.labelRefreshInterval.Text = "刷新间隔(秒):";
|
||||||
//
|
//
|
||||||
// groupBox2
|
// comboBoxSpectrometerPort
|
||||||
//
|
//
|
||||||
this.groupBox2.Controls.Add(this.lblBaud2);
|
this.comboBoxSpectrometerPort.FormattingEnabled = true;
|
||||||
this.groupBox2.Controls.Add(this.lblPort2);
|
this.comboBoxSpectrometerPort.Location = new System.Drawing.Point(70, 20);
|
||||||
this.groupBox2.Controls.Add(this.btnConnect2);
|
this.comboBoxSpectrometerPort.Name = "comboBoxSpectrometerPort";
|
||||||
this.groupBox2.Controls.Add(this.cmbBaud2);
|
this.comboBoxSpectrometerPort.Size = new System.Drawing.Size(121, 28);
|
||||||
this.groupBox2.Controls.Add(this.cmbPort2);
|
this.comboBoxSpectrometerPort.TabIndex = 1;
|
||||||
this.groupBox2.Location = new System.Drawing.Point(230, 12);
|
|
||||||
this.groupBox2.Name = "groupBox2";
|
|
||||||
this.groupBox2.Size = new System.Drawing.Size(200, 120);
|
|
||||||
this.groupBox2.TabIndex = 1;
|
|
||||||
this.groupBox2.TabStop = false;
|
|
||||||
this.groupBox2.Text = "串口2";
|
|
||||||
//
|
//
|
||||||
// cmbPort2
|
// labelSpectrometerPort
|
||||||
//
|
//
|
||||||
this.cmbPort2.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
|
this.labelSpectrometerPort.AutoSize = true;
|
||||||
this.cmbPort2.FormattingEnabled = true;
|
this.labelSpectrometerPort.Location = new System.Drawing.Point(6, 23);
|
||||||
this.cmbPort2.Location = new System.Drawing.Point(60, 25);
|
this.labelSpectrometerPort.Name = "labelSpectrometerPort";
|
||||||
this.cmbPort2.Name = "cmbPort2";
|
this.labelSpectrometerPort.Size = new System.Drawing.Size(54, 20);
|
||||||
this.cmbPort2.Size = new System.Drawing.Size(121, 23);
|
this.labelSpectrometerPort.TabIndex = 0;
|
||||||
this.cmbPort2.TabIndex = 0;
|
this.labelSpectrometerPort.Text = "串口:";
|
||||||
//
|
//
|
||||||
// cmbBaud2
|
// groupBoxMQTT
|
||||||
//
|
//
|
||||||
this.cmbBaud2.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
|
this.groupBoxMQTT.Controls.Add(this.textBoxDeviceSecret);
|
||||||
this.cmbBaud2.FormattingEnabled = true;
|
this.groupBoxMQTT.Controls.Add(this.labelDeviceSecret);
|
||||||
this.cmbBaud2.Items.AddRange(new object[] {
|
this.groupBoxMQTT.Controls.Add(this.textBoxDeviceName);
|
||||||
"9600",
|
this.groupBoxMQTT.Controls.Add(this.labelDeviceName);
|
||||||
"19200",
|
this.groupBoxMQTT.Controls.Add(this.textBoxTopicRoot);
|
||||||
"38400",
|
this.groupBoxMQTT.Controls.Add(this.labelTopicRoot);
|
||||||
"57600",
|
this.groupBoxMQTT.Controls.Add(this.textBoxProductKey);
|
||||||
"115200"});
|
this.groupBoxMQTT.Controls.Add(this.labelProductKey);
|
||||||
this.cmbBaud2.Location = new System.Drawing.Point(60, 54);
|
this.groupBoxMQTT.Location = new System.Drawing.Point(500, 12);
|
||||||
this.cmbBaud2.Name = "cmbBaud2";
|
this.groupBoxMQTT.Name = "groupBoxMQTT";
|
||||||
this.cmbBaud2.Size = new System.Drawing.Size(121, 23);
|
this.groupBoxMQTT.Size = new System.Drawing.Size(300, 150);
|
||||||
this.cmbBaud2.TabIndex = 1;
|
this.groupBoxMQTT.TabIndex = 2;
|
||||||
|
this.groupBoxMQTT.TabStop = false;
|
||||||
|
this.groupBoxMQTT.Text = "MQTT设置";
|
||||||
//
|
//
|
||||||
// btnConnect2
|
// textBoxDeviceSecret
|
||||||
//
|
//
|
||||||
this.btnConnect2.Location = new System.Drawing.Point(60, 83);
|
this.textBoxDeviceSecret.Location = new System.Drawing.Point(100, 115);
|
||||||
this.btnConnect2.Name = "btnConnect2";
|
this.textBoxDeviceSecret.Name = "textBoxDeviceSecret";
|
||||||
this.btnConnect2.Size = new System.Drawing.Size(75, 23);
|
this.textBoxDeviceSecret.Size = new System.Drawing.Size(190, 27);
|
||||||
this.btnConnect2.TabIndex = 2;
|
this.textBoxDeviceSecret.TabIndex = 7;
|
||||||
this.btnConnect2.Text = "连接";
|
this.textBoxDeviceSecret.Text = "1031a49a4f61c29a086f79b41ed971c7";
|
||||||
this.btnConnect2.UseVisualStyleBackColor = true;
|
|
||||||
this.btnConnect2.Click += new System.EventHandler(this.btnConnect2_Click);
|
|
||||||
//
|
//
|
||||||
// lblPort2
|
// labelDeviceSecret
|
||||||
//
|
//
|
||||||
this.lblPort2.AutoSize = true;
|
this.labelDeviceSecret.AutoSize = true;
|
||||||
this.lblPort2.Location = new System.Drawing.Point(15, 28);
|
this.labelDeviceSecret.Location = new System.Drawing.Point(6, 118);
|
||||||
this.lblPort2.Name = "lblPort2";
|
this.labelDeviceSecret.Name = "labelDeviceSecret";
|
||||||
this.lblPort2.Size = new System.Drawing.Size(32, 15);
|
this.labelDeviceSecret.Size = new System.Drawing.Size(88, 20);
|
||||||
this.lblPort2.TabIndex = 3;
|
this.labelDeviceSecret.TabIndex = 6;
|
||||||
this.lblPort2.Text = "端口";
|
this.labelDeviceSecret.Text = "设备密钥:";
|
||||||
//
|
//
|
||||||
// lblBaud2
|
// textBoxDeviceName
|
||||||
//
|
//
|
||||||
this.lblBaud2.AutoSize = true;
|
this.textBoxDeviceName.Location = new System.Drawing.Point(100, 85);
|
||||||
this.lblBaud2.Location = new System.Drawing.Point(15, 57);
|
this.textBoxDeviceName.Name = "textBoxDeviceName";
|
||||||
this.lblBaud2.Name = "lblBaud2";
|
this.textBoxDeviceName.Size = new System.Drawing.Size(190, 27);
|
||||||
this.lblBaud2.Size = new System.Drawing.Size(44, 15);
|
this.textBoxDeviceName.TabIndex = 5;
|
||||||
this.lblBaud2.TabIndex = 4;
|
this.textBoxDeviceName.Text = "PubDevice";
|
||||||
this.lblBaud2.Text = "波特率";
|
|
||||||
//
|
//
|
||||||
// groupBox3
|
// labelDeviceName
|
||||||
//
|
//
|
||||||
this.groupBox3.Controls.Add(this.btnStopUpload);
|
this.labelDeviceName.AutoSize = true;
|
||||||
this.groupBox3.Controls.Add(this.btnStartUpload);
|
this.labelDeviceName.Location = new System.Drawing.Point(6, 88);
|
||||||
this.groupBox3.Controls.Add(this.lblUrl);
|
this.labelDeviceName.Name = "labelDeviceName";
|
||||||
this.groupBox3.Controls.Add(this.txtUrl);
|
this.labelDeviceName.Size = new System.Drawing.Size(88, 20);
|
||||||
this.groupBox3.Location = new System.Drawing.Point(450, 12);
|
this.labelDeviceName.TabIndex = 4;
|
||||||
this.groupBox3.Name = "groupBox3";
|
this.labelDeviceName.Text = "设备名称:";
|
||||||
this.groupBox3.Size = new System.Drawing.Size(320, 120);
|
|
||||||
this.groupBox3.TabIndex = 2;
|
|
||||||
this.groupBox3.TabStop = false;
|
|
||||||
this.groupBox3.Text = "数据上传";
|
|
||||||
//
|
//
|
||||||
// txtUrl
|
// textBoxTopicRoot
|
||||||
//
|
//
|
||||||
this.txtUrl.Location = new System.Drawing.Point(15, 40);
|
this.textBoxTopicRoot.Location = new System.Drawing.Point(100, 55);
|
||||||
this.txtUrl.Name = "txtUrl";
|
this.textBoxTopicRoot.Name = "textBoxTopicRoot";
|
||||||
this.txtUrl.Size = new System.Drawing.Size(290, 23);
|
this.textBoxTopicRoot.Size = new System.Drawing.Size(190, 27);
|
||||||
this.txtUrl.TabIndex = 0;
|
this.textBoxTopicRoot.TabIndex = 3;
|
||||||
this.txtUrl.Text = "http://localhost:8080/api/data";
|
this.textBoxTopicRoot.Text = "a10inDdCRS6";
|
||||||
//
|
//
|
||||||
// lblUrl
|
// labelTopicRoot
|
||||||
//
|
//
|
||||||
this.lblUrl.AutoSize = true;
|
this.labelTopicRoot.AutoSize = true;
|
||||||
this.lblUrl.Location = new System.Drawing.Point(15, 22);
|
this.labelTopicRoot.Location = new System.Drawing.Point(6, 58);
|
||||||
this.lblUrl.Name = "lblUrl";
|
this.labelTopicRoot.Name = "labelTopicRoot";
|
||||||
this.lblUrl.Size = new System.Drawing.Size(56, 15);
|
this.labelTopicRoot.Size = new System.Drawing.Size(88, 20);
|
||||||
this.lblUrl.TabIndex = 1;
|
this.labelTopicRoot.TabIndex = 2;
|
||||||
this.lblUrl.Text = "上传地址";
|
this.labelTopicRoot.Text = "主题根路径:";
|
||||||
//
|
//
|
||||||
// btnStartUpload
|
// textBoxProductKey
|
||||||
//
|
//
|
||||||
this.btnStartUpload.Location = new System.Drawing.Point(15, 80);
|
this.textBoxProductKey.Location = new System.Drawing.Point(100, 25);
|
||||||
this.btnStartUpload.Name = "btnStartUpload";
|
this.textBoxProductKey.Name = "textBoxProductKey";
|
||||||
this.btnStartUpload.Size = new System.Drawing.Size(75, 23);
|
this.textBoxProductKey.Size = new System.Drawing.Size(190, 27);
|
||||||
this.btnStartUpload.TabIndex = 2;
|
this.textBoxProductKey.TabIndex = 1;
|
||||||
this.btnStartUpload.Text = "开始上传";
|
this.textBoxProductKey.Text = "gfcq950RDqt";
|
||||||
this.btnStartUpload.UseVisualStyleBackColor = true;
|
|
||||||
this.btnStartUpload.Click += new System.EventHandler(this.btnStartUpload_Click);
|
|
||||||
//
|
//
|
||||||
// btnStopUpload
|
// labelProductKey
|
||||||
//
|
//
|
||||||
this.btnStopUpload.Location = new System.Drawing.Point(110, 80);
|
this.labelProductKey.AutoSize = true;
|
||||||
this.btnStopUpload.Name = "btnStopUpload";
|
this.labelProductKey.Location = new System.Drawing.Point(6, 28);
|
||||||
this.btnStopUpload.Size = new System.Drawing.Size(75, 23);
|
this.labelProductKey.Name = "labelProductKey";
|
||||||
this.btnStopUpload.TabIndex = 3;
|
this.labelProductKey.Size = new System.Drawing.Size(88, 20);
|
||||||
this.btnStopUpload.Text = "停止上传";
|
this.labelProductKey.TabIndex = 0;
|
||||||
this.btnStopUpload.UseVisualStyleBackColor = true;
|
this.labelProductKey.Text = "产品密钥:";
|
||||||
this.btnStopUpload.Click += new System.EventHandler(this.btnStopUpload_Click);
|
|
||||||
//
|
//
|
||||||
// groupBox4
|
// buttonStartStop
|
||||||
//
|
//
|
||||||
this.groupBox4.Controls.Add(this.btnSaveLog);
|
this.buttonStartStop.Font = new System.Drawing.Font("Microsoft YaHei UI", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point);
|
||||||
this.groupBox4.Controls.Add(this.btnClearLog);
|
this.buttonStartStop.Location = new System.Drawing.Point(12, 110);
|
||||||
this.groupBox4.Controls.Add(this.txtLog);
|
this.buttonStartStop.Name = "buttonStartStop";
|
||||||
this.groupBox4.Location = new System.Drawing.Point(12, 150);
|
this.buttonStartStop.Size = new System.Drawing.Size(120, 50);
|
||||||
this.groupBox4.Name = "groupBox4";
|
this.buttonStartStop.TabIndex = 3;
|
||||||
this.groupBox4.Size = new System.Drawing.Size(758, 270);
|
this.buttonStartStop.Text = "开始";
|
||||||
this.groupBox4.TabIndex = 3;
|
this.buttonStartStop.UseVisualStyleBackColor = true;
|
||||||
this.groupBox4.TabStop = false;
|
this.buttonStartStop.Click += new System.EventHandler(this.buttonStartStop_Click);
|
||||||
this.groupBox4.Text = "数据日志";
|
|
||||||
//
|
//
|
||||||
// txtLog
|
// textBoxLog
|
||||||
//
|
//
|
||||||
this.txtLog.Location = new System.Drawing.Point(15, 22);
|
this.textBoxLog.Location = new System.Drawing.Point(12, 200);
|
||||||
this.txtLog.Multiline = true;
|
this.textBoxLog.Multiline = true;
|
||||||
this.txtLog.Name = "txtLog";
|
this.textBoxLog.Name = "textBoxLog";
|
||||||
this.txtLog.ReadOnly = true;
|
this.textBoxLog.ReadOnly = true;
|
||||||
this.txtLog.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
|
this.textBoxLog.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
|
||||||
this.txtLog.Size = new System.Drawing.Size(728, 210);
|
this.textBoxLog.Size = new System.Drawing.Size(788, 250);
|
||||||
this.txtLog.TabIndex = 0;
|
this.textBoxLog.TabIndex = 4;
|
||||||
//
|
//
|
||||||
// btnClearLog
|
// labelLog
|
||||||
//
|
//
|
||||||
this.btnClearLog.Location = new System.Drawing.Point(15, 238);
|
this.labelLog.AutoSize = true;
|
||||||
this.btnClearLog.Name = "btnClearLog";
|
this.labelLog.Location = new System.Drawing.Point(12, 177);
|
||||||
this.btnClearLog.Size = new System.Drawing.Size(75, 23);
|
this.labelLog.Name = "labelLog";
|
||||||
this.btnClearLog.TabIndex = 1;
|
this.labelLog.Size = new System.Drawing.Size(69, 20);
|
||||||
this.btnClearLog.Text = "清空日志";
|
this.labelLog.TabIndex = 5;
|
||||||
this.btnClearLog.UseVisualStyleBackColor = true;
|
this.labelLog.Text = "数据日志";
|
||||||
this.btnClearLog.Click += new System.EventHandler(this.btnClearLog_Click);
|
|
||||||
//
|
|
||||||
// btnSaveLog
|
|
||||||
//
|
|
||||||
this.btnSaveLog.Location = new System.Drawing.Point(110, 238);
|
|
||||||
this.btnSaveLog.Name = "btnSaveLog";
|
|
||||||
this.btnSaveLog.Size = new System.Drawing.Size(75, 23);
|
|
||||||
this.btnSaveLog.TabIndex = 2;
|
|
||||||
this.btnSaveLog.Text = "保存日志";
|
|
||||||
this.btnSaveLog.UseVisualStyleBackColor = true;
|
|
||||||
this.btnSaveLog.Click += new System.EventHandler(this.btnSaveLog_Click);
|
|
||||||
//
|
|
||||||
// statusStrip1
|
|
||||||
//
|
|
||||||
this.statusStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
|
||||||
this.toolStripStatusLabel1});
|
|
||||||
this.statusStrip1.Location = new System.Drawing.Point(0, 428);
|
|
||||||
this.statusStrip1.Name = "statusStrip1";
|
|
||||||
this.statusStrip1.Size = new System.Drawing.Size(784, 22);
|
|
||||||
this.statusStrip1.TabIndex = 4;
|
|
||||||
this.statusStrip1.Text = "statusStrip1";
|
|
||||||
//
|
|
||||||
// toolStripStatusLabel1
|
|
||||||
//
|
|
||||||
this.toolStripStatusLabel1.Name = "toolStripStatusLabel1";
|
|
||||||
this.toolStripStatusLabel1.Size = new System.Drawing.Size(32, 17);
|
|
||||||
this.toolStripStatusLabel1.Text = "就绪";
|
|
||||||
//
|
//
|
||||||
// Form1
|
// Form1
|
||||||
//
|
//
|
||||||
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
|
this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 20F);
|
||||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||||
this.ClientSize = new System.Drawing.Size(784, 450);
|
this.ClientSize = new System.Drawing.Size(820, 470);
|
||||||
this.Controls.Add(this.statusStrip1);
|
this.Controls.Add(this.labelLog);
|
||||||
this.Controls.Add(this.groupBox4);
|
this.Controls.Add(this.textBoxLog);
|
||||||
this.Controls.Add(this.groupBox3);
|
this.Controls.Add(this.buttonStartStop);
|
||||||
this.Controls.Add(this.groupBox2);
|
this.Controls.Add(this.groupBoxMQTT);
|
||||||
this.Controls.Add(this.groupBox1);
|
this.Controls.Add(this.groupBoxSpectrometer);
|
||||||
this.Name = "Form1";
|
this.Controls.Add(this.groupBoxGPS);
|
||||||
this.Text = "串口数据采集与上传系统";
|
this.Text = "串口数据采集与MQTT发送";
|
||||||
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.Form1_FormClosing);
|
this.groupBoxGPS.ResumeLayout(false);
|
||||||
this.Load += new System.EventHandler(this.Form1_Load);
|
this.groupBoxGPS.PerformLayout();
|
||||||
this.groupBox1.ResumeLayout(false);
|
this.groupBoxSpectrometer.ResumeLayout(false);
|
||||||
this.groupBox1.PerformLayout();
|
this.groupBoxSpectrometer.PerformLayout();
|
||||||
this.groupBox2.ResumeLayout(false);
|
((System.ComponentModel.ISupportInitialize)(this.numericUpDownRefreshInterval)).EndInit();
|
||||||
this.groupBox2.PerformLayout();
|
this.groupBoxMQTT.ResumeLayout(false);
|
||||||
this.groupBox3.ResumeLayout(false);
|
this.groupBoxMQTT.PerformLayout();
|
||||||
this.groupBox3.PerformLayout();
|
|
||||||
this.groupBox4.ResumeLayout(false);
|
|
||||||
this.groupBox4.PerformLayout();
|
|
||||||
this.statusStrip1.ResumeLayout(false);
|
|
||||||
this.statusStrip1.PerformLayout();
|
|
||||||
this.ResumeLayout(false);
|
this.ResumeLayout(false);
|
||||||
this.PerformLayout();
|
this.PerformLayout();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
private System.Windows.Forms.GroupBox groupBox1;
|
|
||||||
private System.Windows.Forms.ComboBox cmbPort1;
|
|
||||||
private System.Windows.Forms.ComboBox cmbBaud1;
|
|
||||||
private System.Windows.Forms.Button btnConnect1;
|
|
||||||
private System.Windows.Forms.Label lblPort1;
|
|
||||||
private System.Windows.Forms.Label lblBaud1;
|
|
||||||
private System.Windows.Forms.GroupBox groupBox2;
|
|
||||||
private System.Windows.Forms.ComboBox cmbPort2;
|
|
||||||
private System.Windows.Forms.ComboBox cmbBaud2;
|
|
||||||
private System.Windows.Forms.Button btnConnect2;
|
|
||||||
private System.Windows.Forms.Label lblPort2;
|
|
||||||
private System.Windows.Forms.Label lblBaud2;
|
|
||||||
private System.Windows.Forms.GroupBox groupBox3;
|
|
||||||
private System.Windows.Forms.TextBox txtUrl;
|
|
||||||
private System.Windows.Forms.Label lblUrl;
|
|
||||||
private System.Windows.Forms.Button btnStartUpload;
|
|
||||||
private System.Windows.Forms.Button btnStopUpload;
|
|
||||||
private System.Windows.Forms.GroupBox groupBox4;
|
|
||||||
private System.Windows.Forms.TextBox txtLog;
|
|
||||||
private System.Windows.Forms.Button btnClearLog;
|
|
||||||
private System.Windows.Forms.Button btnSaveLog;
|
|
||||||
private System.Windows.Forms.StatusStrip statusStrip1;
|
|
||||||
private System.Windows.Forms.ToolStripStatusLabel toolStripStatusLabel1;
|
|
||||||
}
|
}
|
||||||
|
751
Form1.cs
751
Form1.cs
@ -1,461 +1,592 @@
|
|||||||
|
using System;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Data;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.IO;
|
||||||
using System.IO.Ports;
|
using System.IO.Ports;
|
||||||
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Text.Json;
|
using System.Threading;
|
||||||
using System.Text.RegularExpressions;
|
using System.Threading.Tasks;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using uPLibrary.Networking.M2Mqtt;
|
||||||
|
using uPLibrary.Networking.M2Mqtt.Messages;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using aiot_paho_csharp;
|
||||||
|
|
||||||
namespace sscom_sender
|
namespace sscom_sender
|
||||||
{
|
{
|
||||||
public partial class Form1 : Form
|
public partial class Form1 : Form
|
||||||
{
|
{
|
||||||
// 串口对象
|
private SerialPort gpsPort;
|
||||||
private SerialPort? serialPort1;
|
private SerialPort spectrometerPort;
|
||||||
private SerialPort? serialPort2;
|
private MqttClient mqttClient;
|
||||||
|
private bool isRunning = false;
|
||||||
// 数据缓冲区
|
private string logFileName;
|
||||||
private StringBuilder buffer1 = new StringBuilder();
|
|
||||||
private StringBuilder buffer2 = new StringBuilder();
|
|
||||||
|
|
||||||
// 数据队列
|
// 数据队列
|
||||||
private ConcurrentQueue<DataPacket> dataQueue = new ConcurrentQueue<DataPacket>();
|
private ConcurrentQueue<GPSData> gpsDataQueue = new ConcurrentQueue<GPSData>();
|
||||||
|
private ConcurrentQueue<SpectrometerData> spectrometerDataQueue = new ConcurrentQueue<SpectrometerData>();
|
||||||
|
private ConcurrentQueue<string> logQueue = new ConcurrentQueue<string>();
|
||||||
|
|
||||||
// 线程控制
|
// 线程控制
|
||||||
private CancellationTokenSource? uploadCancellationTokenSource;
|
private CancellationTokenSource cancellationTokenSource;
|
||||||
private CancellationTokenSource? logCancellationTokenSource;
|
private Task gpsTask;
|
||||||
private Task? uploadTask;
|
private Task spectrometerTask;
|
||||||
private Task? logTask;
|
private Task mqttTask;
|
||||||
|
private Task logTask;
|
||||||
|
|
||||||
// HTTP客户端
|
// 数据缓冲区
|
||||||
private readonly HttpClient httpClient = new HttpClient();
|
private StringBuilder gpsBuffer = new StringBuilder();
|
||||||
|
private StringBuilder spectrometerBuffer = new StringBuilder();
|
||||||
// 日志文件路径
|
|
||||||
private readonly string logFilePath = Path.Combine(Application.StartupPath, "data_log.txt");
|
|
||||||
|
|
||||||
// 线程安全的日志队列
|
|
||||||
private ConcurrentQueue<string> logQueue = new ConcurrentQueue<string>();
|
|
||||||
|
|
||||||
public Form1()
|
public Form1()
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
InitializeForm();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Form1_Load(object sender, EventArgs e)
|
private void InitializeForm()
|
||||||
{
|
{
|
||||||
// 初始化串口列表
|
// 初始化串口列表
|
||||||
RefreshPortList();
|
RefreshSerialPorts();
|
||||||
|
|
||||||
// 设置默认波特率
|
// 创建日志文件名
|
||||||
cmbBaud1.SelectedIndex = 4; // 115200
|
logFileName = Path.Combine(Application.StartupPath, "logs", $"log_{DateTime.Now:yyyyMMdd_HHmmss}.txt");
|
||||||
cmbBaud2.SelectedIndex = 4; // 115200
|
Directory.CreateDirectory(Path.GetDirectoryName(logFileName));
|
||||||
|
|
||||||
// 启动日志线程
|
|
||||||
StartLogThread();
|
|
||||||
|
|
||||||
UpdateStatus("系统已启动");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RefreshPortList()
|
private void RefreshSerialPorts()
|
||||||
{
|
{
|
||||||
string[] ports = SerialPort.GetPortNames();
|
string[] ports = SerialPort.GetPortNames();
|
||||||
|
comboBoxGPSPort.Items.Clear();
|
||||||
cmbPort1.Items.Clear();
|
comboBoxSpectrometerPort.Items.Clear();
|
||||||
cmbPort2.Items.Clear();
|
|
||||||
|
|
||||||
foreach (string port in ports)
|
foreach (string port in ports)
|
||||||
{
|
{
|
||||||
cmbPort1.Items.Add(port);
|
comboBoxGPSPort.Items.Add(port);
|
||||||
cmbPort2.Items.Add(port);
|
comboBoxSpectrometerPort.Items.Add(port);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ports.Length > 0)
|
if (ports.Length > 0)
|
||||||
{
|
{
|
||||||
cmbPort1.SelectedIndex = 0;
|
comboBoxGPSPort.SelectedIndex = 0;
|
||||||
if (ports.Length > 1)
|
if (ports.Length > 1)
|
||||||
cmbPort2.SelectedIndex = 1;
|
comboBoxSpectrometerPort.SelectedIndex = 1;
|
||||||
else
|
else
|
||||||
cmbPort2.SelectedIndex = 0;
|
comboBoxSpectrometerPort.SelectedIndex = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void btnConnect1_Click(object sender, EventArgs e)
|
private void buttonStartStop_Click(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
if (serialPort1?.IsOpen == true)
|
if (!isRunning)
|
||||||
{
|
{
|
||||||
// 断开连接
|
StartDataCollection();
|
||||||
serialPort1.Close();
|
|
||||||
btnConnect1.Text = "连接";
|
|
||||||
UpdateStatus("串口1已断开");
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// 建立连接
|
StopDataCollection();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void StartDataCollection()
|
||||||
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
serialPort1 = new SerialPort(
|
// 初始化串口
|
||||||
cmbPort1.Text,
|
InitializeSerialPorts();
|
||||||
int.Parse(cmbBaud1.Text),
|
|
||||||
Parity.None,
|
|
||||||
8,
|
|
||||||
StopBits.One);
|
|
||||||
|
|
||||||
serialPort1.DataReceived += SerialPort1_DataReceived;
|
// 启动线程
|
||||||
serialPort1.Open();
|
cancellationTokenSource = new CancellationTokenSource();
|
||||||
|
var token = cancellationTokenSource.Token;
|
||||||
|
|
||||||
btnConnect1.Text = "断开";
|
gpsTask = Task.Run(() => GPSDataReader(token), token);
|
||||||
UpdateStatus($"串口1已连接: {cmbPort1.Text}");
|
spectrometerTask = Task.Run(() => SpectrometerDataReader(token), token);
|
||||||
|
mqttTask = Task.Run(() => MQTTDataSender(token), token);
|
||||||
|
logTask = Task.Run(() => LogWriter(token), token);
|
||||||
|
|
||||||
|
isRunning = true;
|
||||||
|
buttonStartStop.Text = "停止";
|
||||||
|
buttonStartStop.BackColor = Color.Red;
|
||||||
|
|
||||||
|
LogMessage("数据采集已启动");
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
MessageBox.Show($"串口1连接失败: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
MessageBox.Show($"启动失败: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void btnConnect2_Click(object sender, EventArgs e)
|
private void StopDataCollection()
|
||||||
{
|
{
|
||||||
if (serialPort2?.IsOpen == true)
|
|
||||||
{
|
|
||||||
// 断开连接
|
|
||||||
serialPort2.Close();
|
|
||||||
btnConnect2.Text = "连接";
|
|
||||||
UpdateStatus("串口2已断开");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// 建立连接
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
serialPort2 = new SerialPort(
|
isRunning = false;
|
||||||
cmbPort2.Text,
|
cancellationTokenSource?.Cancel();
|
||||||
int.Parse(cmbBaud2.Text),
|
|
||||||
Parity.None,
|
|
||||||
8,
|
|
||||||
StopBits.One);
|
|
||||||
|
|
||||||
serialPort2.DataReceived += SerialPort2_DataReceived;
|
// 立即更新UI状态
|
||||||
serialPort2.Open();
|
buttonStartStop.Text = "开始";
|
||||||
|
buttonStartStop.BackColor = SystemColors.Control;
|
||||||
|
LogMessage("正在停止数据采集...");
|
||||||
|
|
||||||
btnConnect2.Text = "断开";
|
// 异步等待任务完成,避免阻塞UI线程
|
||||||
UpdateStatus($"串口2已连接: {cmbPort2.Text}");
|
Task.Run(() =>
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 给任务一些时间优雅退出
|
||||||
|
var tasks = new[] { gpsTask, spectrometerTask, mqttTask, logTask }.Where(t => t != null).ToArray();
|
||||||
|
if (tasks.Length > 0)
|
||||||
|
{
|
||||||
|
Task.WaitAll(tasks, 2000); // 减少等待时间到2秒
|
||||||
|
}
|
||||||
|
|
||||||
|
// 关闭串口
|
||||||
|
try { gpsPort?.Close(); } catch { }
|
||||||
|
try { spectrometerPort?.Close(); } catch { }
|
||||||
|
|
||||||
|
// 断开MQTT
|
||||||
|
try { mqttClient?.Disconnect(); } catch { }
|
||||||
|
|
||||||
|
// 在UI线程上更新状态
|
||||||
|
this.Invoke(new Action(() =>
|
||||||
|
{
|
||||||
|
LogMessage("数据采集已停止");
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
MessageBox.Show($"串口2连接失败: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
this.Invoke(new Action(() =>
|
||||||
|
{
|
||||||
|
LogMessage($"停止时发生错误: {ex.Message}");
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LogMessage($"停止时发生错误: {ex.Message}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SerialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
|
private void InitializeSerialPorts()
|
||||||
{
|
{
|
||||||
if (serialPort1?.IsOpen == true)
|
// GPS串口
|
||||||
|
if (comboBoxGPSPort.SelectedItem != null)
|
||||||
{
|
{
|
||||||
string data = serialPort1.ReadExisting();
|
gpsPort = new SerialPort(comboBoxGPSPort.SelectedItem.ToString(), 115200, Parity.None, 8, StopBits.One);
|
||||||
ProcessSerialData(data, 1, buffer1);
|
gpsPort.DataReceived += GPSPort_DataReceived;
|
||||||
|
gpsPort.Open();
|
||||||
|
|
||||||
|
// 发送GPS初始化命令
|
||||||
|
gpsPort.WriteLine("bestposa com1 1");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 谱仪串口
|
||||||
|
if (comboBoxSpectrometerPort.SelectedItem != null)
|
||||||
|
{
|
||||||
|
|
||||||
|
spectrometerPort = new SerialPort(comboBoxSpectrometerPort.SelectedItem.ToString(), 115200, Parity.None, 8, StopBits.One);
|
||||||
|
spectrometerPort.DataReceived += SpectrometerPort_DataReceived;
|
||||||
|
spectrometerPort.Open();
|
||||||
|
if (!spectrometerPort.IsOpen) {
|
||||||
|
LogMessage("谱仪端口打开失败");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
LogMessage("谱仪端口已打开");
|
||||||
|
// 发送谱仪开始命令
|
||||||
|
spectrometerPort.DiscardInBuffer();
|
||||||
|
spectrometerPort.Write("$start\r\n");
|
||||||
|
spectrometerPort.ReadTimeout = 1500;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SerialPort2_DataReceived(object sender, SerialDataReceivedEventArgs e)
|
private void InitializeMQTT()
|
||||||
{
|
{
|
||||||
if (serialPort2?.IsOpen == true)
|
try
|
||||||
{
|
{
|
||||||
string data = serialPort2.ReadExisting();
|
string productKey = textBoxProductKey.Text;
|
||||||
ProcessSerialData(data, 2, buffer2);
|
string topicRoot = textBoxTopicRoot.Text;
|
||||||
|
string deviceName = textBoxDeviceName.Text;
|
||||||
|
string deviceSecret = textBoxDeviceSecret.Text;
|
||||||
|
|
||||||
|
MqttSign sign = new MqttSign();
|
||||||
|
sign.calculate(productKey, deviceName, deviceSecret);
|
||||||
|
|
||||||
|
string broker = productKey + ".iot-as-mqtt.cn-shanghai.aliyuncs.com";
|
||||||
|
mqttClient = new MqttClient(broker, 1883, true, null, null, MqttSslProtocols.TLSv1_2);
|
||||||
|
mqttClient.Connect(sign.getClientid(), sign.getUsername(), sign.getPassword());
|
||||||
|
|
||||||
|
LogMessage($"MQTT已连接到: {broker}");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LogMessage($"MQTT连接失败: {ex.Message},将继续进行数据采集和日志记录");
|
||||||
|
mqttClient = null; // 确保mqttClient为null,避免后续使用
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ProcessSerialData(string data, int portNumber, StringBuilder buffer)
|
private void GPSPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
|
||||||
{
|
{
|
||||||
// 将数据添加到缓冲区
|
try
|
||||||
buffer.Append(data);
|
{
|
||||||
|
string data = gpsPort.ReadExisting();
|
||||||
|
gpsBuffer.Append(data);
|
||||||
|
|
||||||
// 查找完整的数据包(以换行符结束)
|
// 处理完整的行
|
||||||
string bufferContent = buffer.ToString();
|
string bufferContent = gpsBuffer.ToString();
|
||||||
string[] lines = bufferContent.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
|
string[] lines = bufferContent.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
|
||||||
|
|
||||||
if (lines.Length > 0)
|
|
||||||
{
|
|
||||||
// 处理完整的行
|
|
||||||
for (int i = 0; i < lines.Length - 1; i++)
|
|
||||||
{
|
|
||||||
ProcessCompleteDataLine(lines[i], portNumber);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查最后一行是否完整
|
|
||||||
if (bufferContent.EndsWith("\r") || bufferContent.EndsWith("\n"))
|
if (bufferContent.EndsWith("\r") || bufferContent.EndsWith("\n"))
|
||||||
{
|
{
|
||||||
ProcessCompleteDataLine(lines[lines.Length - 1], portNumber);
|
gpsBuffer.Clear();
|
||||||
buffer.Clear();
|
foreach (string line in lines)
|
||||||
|
{
|
||||||
|
ProcessGPSData(line);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// 保留不完整的最后一行
|
gpsBuffer.Clear();
|
||||||
buffer.Clear();
|
for (int i = 0; i < lines.Length - 1; i++)
|
||||||
buffer.Append(lines[lines.Length - 1]);
|
{
|
||||||
|
ProcessGPSData(lines[i]);
|
||||||
}
|
}
|
||||||
|
gpsBuffer.Append(lines[lines.Length - 1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LogMessage($"GPS数据接收错误: {ex.Message}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ProcessCompleteDataLine(string line, int portNumber)
|
private void SpectrometerPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(line)) return;
|
try
|
||||||
|
{
|
||||||
|
string data = spectrometerPort.ReadExisting();
|
||||||
|
// LogMessage($"谱仪原始数据: {data}");
|
||||||
|
spectrometerBuffer.Append(data);
|
||||||
|
|
||||||
var dataPacket = new DataPacket
|
// 处理完整的行
|
||||||
|
string bufferContent = spectrometerBuffer.ToString();
|
||||||
|
string[] lines = bufferContent.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
|
||||||
|
|
||||||
|
if (bufferContent.EndsWith("\r") || bufferContent.EndsWith("\n"))
|
||||||
{
|
{
|
||||||
PortNumber = portNumber,
|
spectrometerBuffer.Clear();
|
||||||
RawData = line,
|
foreach (string line in lines)
|
||||||
|
{
|
||||||
|
ProcessSpectrometerData(line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
spectrometerBuffer.Clear();
|
||||||
|
for (int i = 0; i < lines.Length - 1; i++)
|
||||||
|
{
|
||||||
|
ProcessSpectrometerData(lines[i]);
|
||||||
|
}
|
||||||
|
spectrometerBuffer.Append(lines[lines.Length - 1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LogMessage($"谱仪数据接收错误: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ProcessGPSData(string data)
|
||||||
|
{
|
||||||
|
LogMessage($"GPS原始数据: {data}");
|
||||||
|
if (data.StartsWith("#BESTPOSA"))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
string[] parts = data.Split(',');
|
||||||
|
// 查找WGS84标识的位置
|
||||||
|
// LogMessage($"GPS数据部分数量: {parts.Length}");
|
||||||
|
int wgs84Index = -1;
|
||||||
|
for (int i = 0; i < parts.Length; i++)
|
||||||
|
{
|
||||||
|
// LogMessage($"GPS数据部分: {parts[i]}");
|
||||||
|
if (parts[i].Contains("WGS84"))
|
||||||
|
{
|
||||||
|
wgs84Index = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// LogMessage($"WGS84索引: {wgs84Index}");
|
||||||
|
|
||||||
|
// WGS84后面的两个字段是经纬度
|
||||||
|
if (wgs84Index >= 0 && parts.Length > wgs84Index + 2)
|
||||||
|
{
|
||||||
|
double lat = double.Parse(parts[wgs84Index + 1]);
|
||||||
|
double lng = double.Parse(parts[wgs84Index + 2]);
|
||||||
|
|
||||||
|
GPSData gpsData = new GPSData
|
||||||
|
{
|
||||||
|
Latitude = lat,
|
||||||
|
Longitude = lng,
|
||||||
Timestamp = DateTime.Now
|
Timestamp = DateTime.Now
|
||||||
};
|
};
|
||||||
|
|
||||||
// 如果是串口1且数据格式匹配BESTPOS,提取经纬度
|
gpsDataQueue.Enqueue(gpsData);
|
||||||
if (portNumber == 1 && line.Contains("BESTPOSA"))
|
LogMessage($"GPS数据: 纬度={lat:F8}, 经度={lng:F8}");
|
||||||
{
|
|
||||||
var coordinates = ExtractCoordinates(line);
|
|
||||||
if (coordinates != null)
|
|
||||||
{
|
|
||||||
dataPacket.Latitude = coordinates.Value.Latitude;
|
|
||||||
dataPacket.Longitude = coordinates.Value.Longitude;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 添加到队列
|
|
||||||
dataQueue.Enqueue(dataPacket);
|
|
||||||
|
|
||||||
// 添加到日志显示
|
|
||||||
string logMessage = $"[{dataPacket.Timestamp:yyyy-MM-dd HH:mm:ss}] 串口{portNumber}: {line}";
|
|
||||||
if (dataPacket.Latitude.HasValue && dataPacket.Longitude.HasValue)
|
|
||||||
{
|
|
||||||
logMessage += $" [经度: {dataPacket.Longitude:F8}, 纬度: {dataPacket.Latitude:F8}]";
|
|
||||||
}
|
|
||||||
|
|
||||||
AddLogMessage(logMessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
private (double Latitude, double Longitude)? ExtractCoordinates(string data)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// BESTPOS数据格式解析
|
|
||||||
// #BESTPOSA,COM1,14394,98.0,UNKNOWN,1,1699.000,1700908,2,18;INSUFFICIENT_OBS,NONE,纬度,经度,高度,undulation,datum,lat_std,lon_std,hgt_std,stn_id,diff_age,sol_age,#obs,#L1,#L2,reserved,ext_sol_stat,galileo_beidou_sig_mask,gps_glonass_sig_mask*checksum
|
|
||||||
string[] parts = data.Split(',');
|
|
||||||
if (parts.Length >= 14)
|
|
||||||
{
|
|
||||||
if (double.TryParse(parts[11], out double latitude) &&
|
|
||||||
double.TryParse(parts[12], out double longitude))
|
|
||||||
{
|
|
||||||
return (latitude, longitude);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
AddLogMessage($"坐标解析错误: {ex.Message}");
|
LogMessage($"GPS数据解析错误: {ex.Message}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void btnStartUpload_Click(object sender, EventArgs e)
|
private void ProcessSpectrometerData(string data)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(txtUrl.Text))
|
LogMessage($"谱仪原始数据: {data}");
|
||||||
{
|
if (data.Equals("ok")) {
|
||||||
MessageBox.Show("请输入上传地址", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
LogMessage("谱仪已准备好");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
uploadCancellationTokenSource = new CancellationTokenSource();
|
|
||||||
uploadTask = Task.Run(() => UploadWorker(uploadCancellationTokenSource.Token));
|
|
||||||
|
|
||||||
btnStartUpload.Enabled = false;
|
|
||||||
btnStopUpload.Enabled = true;
|
|
||||||
UpdateStatus("数据上传已启动");
|
|
||||||
}
|
|
||||||
|
|
||||||
private void btnStopUpload_Click(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
uploadCancellationTokenSource?.Cancel();
|
|
||||||
btnStartUpload.Enabled = true;
|
|
||||||
btnStopUpload.Enabled = false;
|
|
||||||
UpdateStatus("数据上传已停止");
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task UploadWorker(CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
while (!cancellationToken.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (dataQueue.TryDequeue(out DataPacket? packet))
|
string[] parts = data.Split(' ');
|
||||||
|
// 检查是否为完整的反馈格式:16个字段(日期 时间 + 14个数值)
|
||||||
|
if (parts.Length == 16)
|
||||||
{
|
{
|
||||||
await UploadData(packet);
|
// 验证日期格式 xxxx.xx.xx
|
||||||
}
|
if (!System.Text.RegularExpressions.Regex.IsMatch(parts[0], @"^\d{4}\.\d{2}\.\d{2}$"))
|
||||||
else
|
return;
|
||||||
{
|
|
||||||
await Task.Delay(100, cancellationToken); // 等待100ms
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (OperationCanceledException)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Invoke(() => AddLogMessage($"上传错误: {ex.Message}"));
|
|
||||||
await Task.Delay(5000, cancellationToken); // 错误后等待5秒
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task UploadData(DataPacket packet)
|
// 验证时间格式 xx:xx:xx
|
||||||
{
|
if (!System.Text.RegularExpressions.Regex.IsMatch(parts[1], @"^\d{2}:\d{2}:\d{2}$"))
|
||||||
try
|
return;
|
||||||
{
|
|
||||||
var jsonData = JsonSerializer.Serialize(packet);
|
|
||||||
var content = new StringContent(jsonData, Encoding.UTF8, "application/json");
|
|
||||||
|
|
||||||
var response = await httpClient.PostAsync(txtUrl.Text, content);
|
// 解析时间戳 (xxxx.xx.xx xx:xx:xx)
|
||||||
|
string dateStr = parts[0];
|
||||||
|
string timeStr = parts[1];
|
||||||
|
|
||||||
if (response.IsSuccessStatusCode)
|
SpectrometerData spectData = new SpectrometerData
|
||||||
{
|
{
|
||||||
Invoke(() => AddLogMessage($"数据上传成功: 串口{packet.PortNumber}"));
|
Timestamp = DateTime.Now, // 使用当前时间,也可以解析返回的时间
|
||||||
}
|
RealTime = double.Parse(parts[2]), // aaaaaaa.aa 实时间
|
||||||
else
|
DeadTime = double.Parse(parts[3]), // bbbbbbb.bb 死时间
|
||||||
{
|
DoseRate = double.Parse(parts[14]), // JJJJJJ.JJ 环境总辐射剂量率值(第15个字段)
|
||||||
Invoke(() => AddLogMessage($"数据上传失败: {response.StatusCode} - 串口{packet.PortNumber}"));
|
TotalCountRate = double.Parse(parts[15]) // cccccccccc.cc γ谱的全谱计数率(第16个字段)
|
||||||
|
};
|
||||||
|
|
||||||
|
spectrometerDataQueue.Enqueue(spectData);
|
||||||
|
LogMessage($"谱仪数据: 时间={dateStr} {timeStr}, 剂量率={spectData.DoseRate:F2} nSv/h, 全谱计数率={spectData.TotalCountRate:F2} cps");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Invoke(() => AddLogMessage($"上传异常: {ex.Message}"));
|
LogMessage($"谱仪数据解析错误: {ex.Message}, 数据: {data}");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private async void GPSDataReader(CancellationToken token)
|
||||||
|
{
|
||||||
|
while (!token.IsCancellationRequested && isRunning)
|
||||||
|
{
|
||||||
|
await Task.Delay(1000, token);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void StartLogThread()
|
private async void SpectrometerDataReader(CancellationToken token)
|
||||||
{
|
{
|
||||||
logCancellationTokenSource = new CancellationTokenSource();
|
while (!token.IsCancellationRequested && isRunning)
|
||||||
logTask = Task.Run(() => LogWorker(logCancellationTokenSource.Token));
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task LogWorker(CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
while (!cancellationToken.IsCancellationRequested)
|
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var logsToWrite = new List<string>();
|
LogMessage("尝试读取谱仪数据");
|
||||||
|
if (spectrometerPort != null && spectrometerPort.IsOpen)
|
||||||
// 批量获取日志
|
|
||||||
while (logQueue.TryDequeue(out string? logMessage))
|
|
||||||
{
|
{
|
||||||
logsToWrite.Add(logMessage);
|
// spectrometerPort.DiscardInBuffer();
|
||||||
if (logsToWrite.Count >= 10) break; // 批量写入,最多10条
|
// spectrometerPort.Write("$start\r\n");
|
||||||
|
// await Task.Delay(50, token); // 等待刷新完成
|
||||||
|
// // spectrometerPort.ReadTimeout = 1500;
|
||||||
|
// // string response = spectrometerPort.ReadLine();
|
||||||
|
// // LogMessage($"谱仪原始数据: {response}");
|
||||||
|
// spectrometerPort.DiscardInBuffer();
|
||||||
|
// spectrometerPort.Write("$start\r");
|
||||||
|
// await Task.Delay(50, token); // 等待刷新完成
|
||||||
|
// spectrometerPort.ReadTimeout = 1500;
|
||||||
|
// response = spectrometerPort.ReadLine();
|
||||||
|
// LogMessage($"谱仪原始数据: {response}");
|
||||||
|
|
||||||
|
// response = spectrometerPort.ReadLine();
|
||||||
|
// LogMessage($"谱仪原始数据: {response}");
|
||||||
|
// spectrometerPort.DiscardInBuffer();
|
||||||
|
// spectrometerPort.Write("$start\r\n\r\n");
|
||||||
|
// spectrometerPort.ReadTimeout = 1500;
|
||||||
|
// response = spectrometerPort.ReadLine();
|
||||||
|
// LogMessage($"谱仪原始数据: {response}");
|
||||||
|
// await Task.Delay(50, token); // 等待刷新完成
|
||||||
|
LogMessage("谱仪端口已打开");
|
||||||
|
// 先发送刷新指令
|
||||||
|
spectrometerPort.Write("$refresh\r\n");
|
||||||
|
await Task.Delay(500, token); // 等待刷新完成
|
||||||
|
|
||||||
|
// 再发送获取结果指令
|
||||||
|
spectrometerPort.Write("$getSperesult\r\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (logsToWrite.Count > 0)
|
int interval = (int)(numericUpDownRefreshInterval.Value * 1000);
|
||||||
{
|
await Task.Delay(interval, token);
|
||||||
await File.AppendAllLinesAsync(logFilePath, logsToWrite, cancellationToken);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
await Task.Delay(1000, cancellationToken); // 等待1秒
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (OperationCanceledException)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
// 日志写入错误,避免无限循环
|
LogMessage($"谱仪数据读取错误: {ex.Message}");
|
||||||
|
await Task.Delay(5000, token);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async void MQTTDataSender(CancellationToken token)
|
||||||
|
{
|
||||||
|
// 在数据发送线程中初始化MQTT连接
|
||||||
|
InitializeMQTT();
|
||||||
|
|
||||||
|
while (!token.IsCancellationRequested && isRunning)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (spectrometerDataQueue.TryDequeue(out SpectrometerData spectData))
|
||||||
|
{
|
||||||
|
// 查找最近的GPS数据
|
||||||
|
GPSData nearestGPS = FindNearestGPSData(spectData.Timestamp);
|
||||||
|
|
||||||
|
if (nearestGPS != null)
|
||||||
|
{
|
||||||
|
var mqttData = new
|
||||||
|
{
|
||||||
|
OptTime = spectData.Timestamp.ToString("yyyy-MM-dd HH:mm:ss.fff"),
|
||||||
|
PointLat = nearestGPS.Latitude.ToString("F8"),
|
||||||
|
PointLng = nearestGPS.Longitude.ToString("F8"),
|
||||||
|
Value = spectData.DoseRate / 1000000000.0 // 转换为合适的单位
|
||||||
|
};
|
||||||
|
|
||||||
|
string json = JsonConvert.SerializeObject(mqttData);
|
||||||
|
string topic = $"/{textBoxTopicRoot.Text}/{textBoxDeviceName.Text}/user/update";
|
||||||
|
|
||||||
|
if (mqttClient != null && mqttClient.IsConnected)
|
||||||
|
{
|
||||||
|
mqttClient.Publish(topic, Encoding.UTF8.GetBytes(json));
|
||||||
|
LogMessage($"MQTT发送: {json}");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LogMessage($"MQTT未连接,数据记录: {json}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await Task.Delay(100, token);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LogMessage($"MQTT发送错误: {ex.Message}");
|
||||||
|
await Task.Delay(5000, token);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private GPSData FindNearestGPSData(DateTime targetTime)
|
||||||
|
{
|
||||||
|
GPSData nearest = null;
|
||||||
|
TimeSpan minDiff = TimeSpan.MaxValue;
|
||||||
|
|
||||||
|
var gpsDataList = gpsDataQueue.ToArray();
|
||||||
|
foreach (var gpsData in gpsDataList)
|
||||||
|
{
|
||||||
|
TimeSpan diff = Math.Abs((gpsData.Timestamp - targetTime).Ticks) == (gpsData.Timestamp - targetTime).Ticks ?
|
||||||
|
gpsData.Timestamp - targetTime : targetTime - gpsData.Timestamp;
|
||||||
|
|
||||||
|
if (diff < minDiff)
|
||||||
|
{
|
||||||
|
minDiff = diff;
|
||||||
|
nearest = gpsData;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nearest;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async void LogWriter(CancellationToken token)
|
||||||
|
{
|
||||||
|
while (!token.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (logQueue.TryDequeue(out string logMessage))
|
||||||
|
{
|
||||||
|
await File.AppendAllTextAsync(logFileName, logMessage + Environment.NewLine, token);
|
||||||
|
}
|
||||||
|
|
||||||
|
await Task.Delay(100, token);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
// 避免日志写入错误导致的无限循环
|
||||||
Console.WriteLine($"日志写入错误: {ex.Message}");
|
Console.WriteLine($"日志写入错误: {ex.Message}");
|
||||||
await Task.Delay(5000, cancellationToken);
|
await Task.Delay(1000, token);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AddLogMessage(string message)
|
private void LogMessage(string message)
|
||||||
{
|
{
|
||||||
// 添加到界面显示
|
string logEntry = $"[{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}] {message}";
|
||||||
if (InvokeRequired)
|
|
||||||
|
// 添加到日志队列
|
||||||
|
logQueue.Enqueue(logEntry);
|
||||||
|
|
||||||
|
// 更新UI
|
||||||
|
if (textBoxLog.InvokeRequired)
|
||||||
{
|
{
|
||||||
Invoke(() => AddLogMessage(message));
|
textBoxLog.Invoke(new Action(() => {
|
||||||
return;
|
textBoxLog.AppendText(logEntry + Environment.NewLine);
|
||||||
|
textBoxLog.ScrollToCaret();
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
else
|
||||||
txtLog.AppendText(message + Environment.NewLine);
|
|
||||||
txtLog.SelectionStart = txtLog.Text.Length;
|
|
||||||
txtLog.ScrollToCaret();
|
|
||||||
|
|
||||||
// 添加到日志文件队列
|
|
||||||
logQueue.Enqueue(message);
|
|
||||||
|
|
||||||
// 限制界面显示的行数
|
|
||||||
if (txtLog.Lines.Length > 1000)
|
|
||||||
{
|
{
|
||||||
var lines = txtLog.Lines.Skip(500).ToArray();
|
textBoxLog.AppendText(logEntry + Environment.NewLine);
|
||||||
txtLog.Text = string.Join(Environment.NewLine, lines);
|
textBoxLog.ScrollToCaret();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateStatus(string message)
|
protected override void OnFormClosing(FormClosingEventArgs e)
|
||||||
{
|
{
|
||||||
if (InvokeRequired)
|
if (isRunning)
|
||||||
{
|
{
|
||||||
Invoke(() => UpdateStatus(message));
|
StopDataCollection();
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
base.OnFormClosing(e);
|
||||||
toolStripStatusLabel1.Text = message;
|
|
||||||
AddLogMessage($"[系统] {message}");
|
|
||||||
}
|
|
||||||
|
|
||||||
private void btnClearLog_Click(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
txtLog.Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void btnSaveLog_Click(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
using (var saveDialog = new SaveFileDialog())
|
|
||||||
{
|
|
||||||
saveDialog.Filter = "文本文件|*.txt|所有文件|*.*";
|
|
||||||
saveDialog.FileName = $"log_{DateTime.Now:yyyyMMdd_HHmmss}.txt";
|
|
||||||
|
|
||||||
if (saveDialog.ShowDialog() == DialogResult.OK)
|
|
||||||
{
|
|
||||||
File.WriteAllText(saveDialog.FileName, txtLog.Text);
|
|
||||||
MessageBox.Show("日志保存成功", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
MessageBox.Show($"保存失败: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
|
public class GPSData
|
||||||
{
|
{
|
||||||
// 停止所有线程
|
public double Latitude { get; set; }
|
||||||
uploadCancellationTokenSource?.Cancel();
|
public double Longitude { get; set; }
|
||||||
logCancellationTokenSource?.Cancel();
|
|
||||||
|
|
||||||
// 关闭串口
|
|
||||||
serialPort1?.Close();
|
|
||||||
serialPort2?.Close();
|
|
||||||
|
|
||||||
// 释放资源
|
|
||||||
httpClient.Dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 数据包类
|
|
||||||
public class DataPacket
|
|
||||||
{
|
|
||||||
public int PortNumber { get; set; }
|
|
||||||
public string RawData { get; set; } = string.Empty;
|
|
||||||
public DateTime Timestamp { get; set; }
|
public DateTime Timestamp { get; set; }
|
||||||
public double? Latitude { get; set; }
|
}
|
||||||
public double? Longitude { get; set; }
|
|
||||||
|
public class SpectrometerData
|
||||||
|
{
|
||||||
|
public DateTime Timestamp { get; set; }
|
||||||
|
public double RealTime { get; set; }
|
||||||
|
public double DeadTime { get; set; }
|
||||||
|
public double DoseRate { get; set; }
|
||||||
|
public double TotalCountRate { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
56
MqttSign.cs
Normal file
56
MqttSign.cs
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
using System;
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
|
||||||
|
namespace aiot_paho_csharp
|
||||||
|
{
|
||||||
|
class CryptoUtil
|
||||||
|
{
|
||||||
|
public static String hmacSha256(String plainText, String key)
|
||||||
|
{
|
||||||
|
var encoding = new System.Text.UTF8Encoding();
|
||||||
|
byte[] plainTextBytes = encoding.GetBytes(plainText);
|
||||||
|
byte[] keyBytes = encoding.GetBytes(key);
|
||||||
|
|
||||||
|
HMACSHA256 hmac = new HMACSHA256(keyBytes);
|
||||||
|
byte[] sign = hmac.ComputeHash(plainTextBytes);
|
||||||
|
return BitConverter.ToString(sign).Replace("-", string.Empty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public class MqttSign
|
||||||
|
{
|
||||||
|
private String username = "";
|
||||||
|
|
||||||
|
private String password = "";
|
||||||
|
|
||||||
|
private String clientid = "";
|
||||||
|
|
||||||
|
public String getUsername() { return this.username; }
|
||||||
|
|
||||||
|
public String getPassword() { return this.password; }
|
||||||
|
|
||||||
|
public String getClientid() { return this.clientid; }
|
||||||
|
|
||||||
|
public bool calculate(String productKey, String deviceName, String deviceSecret)
|
||||||
|
{
|
||||||
|
if (productKey == null || deviceName == null || deviceSecret == null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//MQTT用户名
|
||||||
|
this.username = deviceName + "&" + productKey;
|
||||||
|
|
||||||
|
//MQTT密码
|
||||||
|
String timestamp = Convert.ToInt64((DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalMilliseconds).ToString();
|
||||||
|
String plainPasswd = "clientId" + productKey + "." + deviceName + "deviceName" +
|
||||||
|
deviceName + "productKey" + productKey + "timestamp" + timestamp;
|
||||||
|
this.password = CryptoUtil.hmacSha256(plainPasswd, deviceSecret);
|
||||||
|
|
||||||
|
//MQTT ClientId
|
||||||
|
this.clientid = productKey + "." + deviceName + "|" + "timestamp=" + timestamp +
|
||||||
|
",_v=paho-c#-1.0.0,securemode=2,signmethod=hmacsha256|";
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
94
readme.txt
Normal file
94
readme.txt
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
我希望用C#写一个GUI应用,能够打开2个串口,然后读取数据,然后能够整理数据,把数据发送到配置好的网址上,并且能够在界面上看到数据记录,然后也能把数据写到一个log文件中。
|
||||||
|
一个串口是GPS的,数据格式是这样的。要提取WGS84后面的经纬度信息。这个串口打开,发送bestposa com1 1 \r\n后就有数据传输进来:
|
||||||
|
#BESTPOSA,COM1,14394,98.0,UNKNOWN,1,1699.000,1700908,2,18;INSUFFICIENT_OBS,NONE,0.00000000000,0.00000000000,0.0000,0.0000,WGS84,0.0000,0.0000,0.0000,"",0.000,0.000,0,0,0,0,0,00,00,00*fcf220b4
|
||||||
|
另一个串口是谱仪数据,文档如下:
|
||||||
|
航空γ谱仪通信协议
|
||||||
|
通信方式
|
||||||
|
采用RS232串口通信,115200,n,8,1。
|
||||||
|
操作指令
|
||||||
|
开始测量指令
|
||||||
|
指令格式:$start[回车][换行]
|
||||||
|
反馈格式:ok[回车][换行]
|
||||||
|
谱数据刷新指令(刷新的回复要忽略)
|
||||||
|
指令格式:$refresh[回车][换行]
|
||||||
|
反馈格式:0 0 0 0 0 0 0 0 0 0 0 0 0 (很长的一个序列)[回车][换行]
|
||||||
|
清空测量指令
|
||||||
|
指令格式:$clear[回车][换行]
|
||||||
|
反馈格式:ok[回车][换行]
|
||||||
|
谱分析指令
|
||||||
|
指令格式:$getSperesult[回车][换行]
|
||||||
|
反馈格式:xxxx.xx.xx xx:xx:xx aaaaaaa.aa bbbbbbb.bb 1111111.11 2222222.12 3333333.33 4444444.44 5555555.55 6666666.66 7777777.77 8888888.88 9999999.99 0000000.00 JJJJJJ.JJ cccccccccc.cc [回车][换行]
|
||||||
|
“aaaaaaa.aa bbbbbbb.bb”表示实时间和死时间,单位:s(秒);
|
||||||
|
“1111111.11 … …0000000.00”表示十种核素计数率,单位:cps;
|
||||||
|
“JJJJJJ.JJ”表示环境总辐射剂量率值,单位:nSv/h;
|
||||||
|
“cccccccccc.cc”表示γ谱的全谱计数率cps;
|
||||||
|
“xxxx.xx.xx xx:xx:xx”表示返回该帧时间;
|
||||||
|
1111111.11 (核素40K,单位cps)
|
||||||
|
2222222.22 (核素208Tl,单位cps)
|
||||||
|
3333333.33 (核素214Bi,单位cps)
|
||||||
|
4444444.44 (核素214Pb,单位cps)
|
||||||
|
5555555.55 (核素226Ra,单位cps)
|
||||||
|
6666666.66 (核素232Th,单位cps)
|
||||||
|
7777777.77 (核素60Co,单位cps)
|
||||||
|
8888888.88 (核素131I,单位cps)
|
||||||
|
9999999.99 (核素137Cs,单位cps)
|
||||||
|
0000000.00 (核素192Ir,单位cps)
|
||||||
|
|
||||||
|
这个需要打开串口的时候先开始,然后就进入一个循环,刷新一次,解析一次,得到数据,这样反复。我希望能选择刷新的频率。
|
||||||
|
|
||||||
|
两个串口的数据分别放到两个队列里,每次要从谱仪队列里读取数据,然后从GPS队列里读取时间最近的数据,两个合并起来,组成这样的格式:{"OptTime":"2020-11-30 13:16:24.178","PointLat":"23.10606","PointLng":"113.213425","Value":1.9334545697802241E-07}。
|
||||||
|
|
||||||
|
然后通过mqtt发送出去。
|
||||||
|
|
||||||
|
这是大致的发布代码:
|
||||||
|
String productKey = "gfcq950RDqt";
|
||||||
|
String topicRoot = "a10inDdCRS6";
|
||||||
|
String deviceName = "PubDevice";
|
||||||
|
String deviceSecret = "1031a49a4f61c29a086f79b41ed971c7";
|
||||||
|
|
||||||
|
//计算Mqtt建联参数
|
||||||
|
MqttSign sign = new MqttSign();
|
||||||
|
sign.calculate(productKey, deviceName, deviceSecret);
|
||||||
|
|
||||||
|
Console.WriteLine("username: " + sign.getUsername());
|
||||||
|
Console.WriteLine("password: " + sign.getPassword());
|
||||||
|
Console.WriteLine("clientid: " + sign.getClientid());
|
||||||
|
|
||||||
|
//使用Paho链接阿里云物联网平台
|
||||||
|
int port = 443;
|
||||||
|
String broker = productKey + ".iot-as-mqtt.cn-shanghai.aliyuncs.com";
|
||||||
|
|
||||||
|
MqttClient mqttClient = new MqttClient(broker, port, true, MqttSslProtocols.TLSv1_2, null, null);
|
||||||
|
mqttClient.Connect(sign.getClientid(), sign.getUsername(), sign.getPassword());
|
||||||
|
|
||||||
|
Console.WriteLine("broker: " + broker + " Connected");
|
||||||
|
|
||||||
|
// //Paho Mqtt 消息订阅
|
||||||
|
// String topicReply = "/" + topicRoot + "/" + deviceName + "/user/get";
|
||||||
|
|
||||||
|
// mqttClient.MqttMsgPublishReceived += MqttPostProperty_MqttMsgPublishReceived;
|
||||||
|
// mqttClient.Subscribe(new string[] { topicReply }, new byte[] { MqttMsgBase.QOS_LEVEL_AT_MOST_ONCE });
|
||||||
|
// Console.WriteLine("subscribe: " + topicReply);
|
||||||
|
|
||||||
|
//Paho Mqtt 消息发布
|
||||||
|
String topic = "/" + topicRoot + "/" + deviceName + "/user/update";
|
||||||
|
String message = "{\"id\":\"1\",\"version\":\"1.0\",\"params\":{\"LightSwitch\":0}}";
|
||||||
|
mqttClient.Publish(topic, Encoding.UTF8.GetBytes(message));
|
||||||
|
Console.WriteLine("publish: " + message);
|
||||||
|
|
||||||
|
while(true) {
|
||||||
|
Thread.Sleep(2000);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Paho Mqtt 断开连接
|
||||||
|
mqttClient.Disconnect();
|
||||||
|
|
||||||
|
另外,我希望是2个串口接收数据分别分配一个线程,上传分配一个线程。数据读取后放到一个队列里,上传线程去读取队列数据。
|
||||||
|
还要有一个日志线程,把数据写入到日志里。
|
||||||
|
软件要有个简单的文本框来展示串口收到的数据
|
||||||
|
日志要自动创建文件,每次打开的时候,日志的名字应该是当前的时间。
|
||||||
|
|
||||||
|
要有个按钮可以一键开始和结束。
|
||||||
|
|
||||||
|
另外,接收数据的时候很可能每次收到的是不完整的数据。
|
||||||
|
我已经创建好了模板程序。
|
@ -1,4 +1,4 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>WinExe</OutputType>
|
<OutputType>WinExe</OutputType>
|
||||||
@ -10,7 +10,9 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<PackageReference Include="M2Mqtt" Version="4.3.0" />
|
||||||
<PackageReference Include="System.IO.Ports" Version="8.0.0" />
|
<PackageReference Include="System.IO.Ports" Version="8.0.0" />
|
||||||
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
@ -1,24 +0,0 @@
|
|||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
|
||||||
# Visual Studio Version 17
|
|
||||||
VisualStudioVersion = 17.5.2.0
|
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "sscom-sender", "sscom-sender.csproj", "{F03C6C53-8989-99E6-D747-EC03449AD20F}"
|
|
||||||
EndProject
|
|
||||||
Global
|
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
|
||||||
Debug|Any CPU = Debug|Any CPU
|
|
||||||
Release|Any CPU = Release|Any CPU
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
|
||||||
{F03C6C53-8989-99E6-D747-EC03449AD20F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{F03C6C53-8989-99E6-D747-EC03449AD20F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{F03C6C53-8989-99E6-D747-EC03449AD20F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{F03C6C53-8989-99E6-D747-EC03449AD20F}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
|
||||||
HideSolutionNode = FALSE
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
|
||||||
SolutionGuid = {707867E8-3EF5-4E83-A851-9053BE677857}
|
|
||||||
EndGlobalSection
|
|
||||||
EndGlobal
|
|
Loading…
x
Reference in New Issue
Block a user