1、单独把光源控制器的控制拿出来控制。

2、优化二维码扫码异常时导致停机的问题
develop
lhiven 9 months ago
parent 4a3e287dc1
commit b339b29b67

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8" />
</startup>
</configuration>

@ -0,0 +1,40 @@
namespace LightControl
{
partial class Form1
{
/// <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.components = new System.ComponentModel.Container();
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(800, 450);
this.Text = "Form1";
}
#endregion
}
}

@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace LightControl
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
}
}

@ -0,0 +1,305 @@
using Rs.Framework;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using static System.Net.Mime.MediaTypeNames;
namespace Rs.MotionPlat.SysConfig
{
public partial class LightConfig : Form
{
SerialPort sp;
public LightConfig()
{
InitializeComponent();
sp = new SerialPort();
sp.BaudRate = 19200;
sp.DataBits= 8;
sp.Parity = Parity.None;
sp.StopBits= StopBits.One;
sp.PortName = "COM2";
sp.DataReceived += Sp_DataReceived;
}
List<byte> reciveData = new List<byte>();
string reciveMsg = string.Empty;
private void Sp_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
byte[] readBuffer=new byte[1024];
int len = sp.BytesToRead;
if (len > 0)
{
sp.Read(readBuffer, 0, len);
reciveData.AddRange(readBuffer.Take(len));
string buf = Encoding.ASCII.GetString(readBuffer, 0, len);
if(buf=="+OK")
{
reciveMsg = Encoding.ASCII.GetString(reciveData.ToArray());
reciveData.Clear();
Invoke(new Action(() => {
txtRunResult.AppendText(reciveMsg + Environment.NewLine);
}));
}
else if (buf.IndexOf("#") > 0)
{
reciveMsg = Encoding.ASCII.GetString(reciveData.ToArray());
reciveData.Clear();
Invoke(new Action(() => {
txtRunResult.AppendText(reciveMsg+Environment.NewLine);
}));
}
}
}
private void btnOpen_Click(object sender, EventArgs e)
{
try
{
if(sp!=null &&sp.IsOpen)
{
sp.Close();
}
sp.Open();
txtRunResult.AppendText("Open serial success!" + Environment.NewLine);
}
catch (Exception)
{
txtRunResult.AppendText("Open serial fail!!!" + Environment.NewLine);
}
}
private void btnLoadParam_Click(object sender, EventArgs e)
{
Task.Run(() => {
if (sp.IsOpen)
{
string msg = "$RD=9999#";
sp.Write(msg);
reciveMsg = "";
Dictionary<string, string> kv = new Dictionary<string, string>();
while (true)
{
if (!string.IsNullOrEmpty(reciveMsg))
{
reciveMsg = reciveMsg.Replace("$", "").Replace("#", "");
string[] items = reciveMsg.Split(',');
foreach (string item in items)
{
string[] keyvalue = item.Split('=');
if (!kv.ContainsKey(keyvalue[0]))
{
kv.Add(keyvalue[0], keyvalue[1]);
}
}
string val = kv[$"TR"];
Control[] ctls = this.Controls.Find($"rbtnTR{val}", true);
if(ctls!=null&& ctls.Length>0)
{
Invoke(new Action(() => {
((RadioButton)ctls[0]).Checked = true;
}));
}
val = kv[$"GR"];
ctls = this.Controls.Find($"rbtnGR{val}", true);
if (ctls != null && ctls.Length > 0)
{
Invoke(new Action(() => {
((RadioButton)ctls[0]).Checked = true;
}));
}
for (int i = 0; i < 4; i++)
{
Invoke(new Action(() => {
val = kv[$"F{i}"];
ctls = this.Controls.Find($"cboxF{i}", true);
if (ctls != null && ctls.Length > 0)
{
((CheckBox)ctls[0]).Checked = val == "1" ? true : false;
}
val = kv[$"L{i}"];
ctls = this.Controls.Find($"txtL{i}", true);
if (ctls != null && ctls.Length > 0)
{
((TextBox)ctls[0]).Text = val;
}
val = kv[$"T{i}"];
ctls = this.Controls.Find($"txtT{i}", true);
if (ctls != null && ctls.Length > 0)
{
((TextBox)ctls[0]).Text = val;
}
val = kv[$"P{i}"];
ctls = this.Controls.Find($"txtP{i}", true);
if (ctls != null && ctls.Length > 0)
{
((TextBox)ctls[0]).Text = val;
}
}));
}
break;
}
}
}
});
}
private void btnSendParam_Click(object sender, EventArgs e)
{
if (sp.IsOpen)
{
string msg = "$SA=1#";
byte[] datas = Encoding.ASCII.GetBytes(msg);
sp.Write(datas, 0, datas.Length);
}
}
private void enable_CheckedChanged(object sender, EventArgs e)
{
Task.Run(() => {
string msg = "";
CheckBox cbox = (CheckBox)sender;
int val = cbox.Checked ? 1 : 0;
msg = $"${cbox.Name.Replace("cbox", "")}={val}#";
if (sp.IsOpen)
{
byte[] datas = Encoding.ASCII.GetBytes(msg);
sp.Write(datas, 0, datas.Length);
}
});
}
private void txtParam_KeyUp(object sender, KeyEventArgs e)
{
Task.Run(() => {
string msg = "";
TextBox txt = (TextBox)sender;
msg = $"${txt.Name.Replace("txt", "")}={txt.Text}#";
if (sp.IsOpen)
{
byte[] datas = Encoding.ASCII.GetBytes(msg);
sp.Write(datas, 0, datas.Length);
}
});
}
private void triggerMode_CheckedChanged(object sender, EventArgs e)
{
Task.Run(() => {
string msg = "";
RadioButton rbtn = (RadioButton)sender;
if(rbtn.Checked)
{
msg = $"$TR={rbtn.Name.GetLastChar()}#";
if (sp.IsOpen)
{
byte[] datas = Encoding.ASCII.GetBytes(msg);
sp.Write(datas, 0, datas.Length);
}
}
});
}
private void outLevel_CheckedChanged(object sender, EventArgs e)
{
Task.Run(() => {
string msg = "";
RadioButton rbtn = (RadioButton)sender;
if (rbtn.Checked)
{
msg = $"$GR={rbtn.Name.GetLastChar()}#";
if (sp.IsOpen)
{
byte[] datas = Encoding.ASCII.GetBytes(msg);
sp.Write(datas, 0, datas.Length);
}
}
});
}
private void btnClose_Click(object sender, EventArgs e)
{
try
{
if (sp != null && sp.IsOpen)
{
sp.Close();
txtRunResult.AppendText("serial closed!" + Environment.NewLine);
}
}
catch (Exception)
{
}
}
protected override void OnClosed(EventArgs e)
{
if (sp != null && sp.IsOpen)
{
sp.Close();
txtRunResult.AppendText("serial closed!" + Environment.NewLine);
}
base.OnClosed(e);
}
private void LightConfig_Load(object sender, EventArgs e)
{
string[] ionames = System.IO.Ports.SerialPort.GetPortNames();
if(ionames!=null && ionames.Length>0)
{
foreach (var item in ionames)
{
comboBox1.Items.Add(item);
}
comboBox1.SelectedIndex = 0;
}
}
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
if(sp!=null && sp.IsOpen)
{
sp.Close();
}
sp.PortName = comboBox1.SelectedItem.ToString();
}
private void btnClose_Click_1(object sender, EventArgs e)
{
if(sp != null && sp.IsOpen)
{
sp.Close();
}
}
private void LightConfig_FormClosing(object sender, FormClosingEventArgs e)
{
if (sp != null && sp.IsOpen)
{
sp.Close();
}
}
}
}

@ -0,0 +1,700 @@
namespace Rs.MotionPlat.SysConfig
{
partial class LightConfig
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.groupBox1 = new System.Windows.Forms.GroupBox();
this.btnLoadParam = new System.Windows.Forms.Button();
this.btnOpen = new System.Windows.Forms.Button();
this.btnSendParam = new System.Windows.Forms.Button();
this.groupBox3 = new System.Windows.Forms.GroupBox();
this.rbtnGR1 = new System.Windows.Forms.RadioButton();
this.rbtnGR0 = new System.Windows.Forms.RadioButton();
this.groupBox2 = new System.Windows.Forms.GroupBox();
this.rbtnTR7 = new System.Windows.Forms.RadioButton();
this.rbtnTR5 = new System.Windows.Forms.RadioButton();
this.rbtnTR3 = new System.Windows.Forms.RadioButton();
this.rbtnTR1 = new System.Windows.Forms.RadioButton();
this.rbtnTR15 = new System.Windows.Forms.RadioButton();
this.rbtnTR6 = new System.Windows.Forms.RadioButton();
this.rbtnTR4 = new System.Windows.Forms.RadioButton();
this.rbtnTR2 = new System.Windows.Forms.RadioButton();
this.rbtnTR0 = new System.Windows.Forms.RadioButton();
this.panelEx2 = new System.Windows.Forms.Panel();
this.txtL0 = new System.Windows.Forms.TextBox();
this.label1 = new System.Windows.Forms.Label();
this.txtP3 = new System.Windows.Forms.TextBox();
this.label2 = new System.Windows.Forms.Label();
this.txtP2 = new System.Windows.Forms.TextBox();
this.label7 = new System.Windows.Forms.Label();
this.txtP1 = new System.Windows.Forms.TextBox();
this.label3 = new System.Windows.Forms.Label();
this.txtP0 = new System.Windows.Forms.TextBox();
this.label8 = new System.Windows.Forms.Label();
this.txtT3 = new System.Windows.Forms.TextBox();
this.label4 = new System.Windows.Forms.Label();
this.txtT2 = new System.Windows.Forms.TextBox();
this.label9 = new System.Windows.Forms.Label();
this.txtT1 = new System.Windows.Forms.TextBox();
this.label5 = new System.Windows.Forms.Label();
this.txtT0 = new System.Windows.Forms.TextBox();
this.cboxF0 = new System.Windows.Forms.CheckBox();
this.txtL3 = new System.Windows.Forms.TextBox();
this.cboxF1 = new System.Windows.Forms.CheckBox();
this.cboxF3 = new System.Windows.Forms.CheckBox();
this.txtL1 = new System.Windows.Forms.TextBox();
this.txtL2 = new System.Windows.Forms.TextBox();
this.cboxF2 = new System.Windows.Forms.CheckBox();
this.panelEx1 = new System.Windows.Forms.Panel();
this.groupBox4 = new System.Windows.Forms.GroupBox();
this.txtRunResult = new System.Windows.Forms.RichTextBox();
this.btnClose = new System.Windows.Forms.Button();
this.comboBox1 = new System.Windows.Forms.ComboBox();
this.label6 = new System.Windows.Forms.Label();
this.groupBox1.SuspendLayout();
this.groupBox3.SuspendLayout();
this.groupBox2.SuspendLayout();
this.panelEx2.SuspendLayout();
this.panelEx1.SuspendLayout();
this.groupBox4.SuspendLayout();
this.SuspendLayout();
//
// groupBox1
//
this.groupBox1.Controls.Add(this.groupBox3);
this.groupBox1.Controls.Add(this.groupBox2);
this.groupBox1.Controls.Add(this.panelEx2);
this.groupBox1.Dock = System.Windows.Forms.DockStyle.Top;
this.groupBox1.ForeColor = System.Drawing.Color.White;
this.groupBox1.Location = new System.Drawing.Point(0, 0);
this.groupBox1.Name = "groupBox1";
this.groupBox1.Size = new System.Drawing.Size(592, 468);
this.groupBox1.TabIndex = 0;
this.groupBox1.TabStop = false;
this.groupBox1.Text = "控制器参数";
//
// btnLoadParam
//
this.btnLoadParam.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.btnLoadParam.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(56)))), ((int)(((byte)(56)))), ((int)(((byte)(56)))));
this.btnLoadParam.FlatAppearance.BorderColor = System.Drawing.Color.White;
this.btnLoadParam.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btnLoadParam.ForeColor = System.Drawing.Color.White;
this.btnLoadParam.Location = new System.Drawing.Point(147, 25);
this.btnLoadParam.Name = "btnLoadParam";
this.btnLoadParam.Size = new System.Drawing.Size(100, 30);
this.btnLoadParam.TabIndex = 9;
this.btnLoadParam.Text = "加载参数";
this.btnLoadParam.UseVisualStyleBackColor = false;
this.btnLoadParam.Click += new System.EventHandler(this.btnLoadParam_Click);
//
// btnOpen
//
this.btnOpen.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.btnOpen.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(56)))), ((int)(((byte)(56)))), ((int)(((byte)(56)))));
this.btnOpen.FlatAppearance.BorderColor = System.Drawing.Color.White;
this.btnOpen.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btnOpen.ForeColor = System.Drawing.Color.White;
this.btnOpen.Location = new System.Drawing.Point(13, 25);
this.btnOpen.Name = "btnOpen";
this.btnOpen.Size = new System.Drawing.Size(100, 30);
this.btnOpen.TabIndex = 9;
this.btnOpen.Text = "打开";
this.btnOpen.UseVisualStyleBackColor = false;
this.btnOpen.Click += new System.EventHandler(this.btnOpen_Click);
//
// btnSendParam
//
this.btnSendParam.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.btnSendParam.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(56)))), ((int)(((byte)(56)))), ((int)(((byte)(56)))));
this.btnSendParam.FlatAppearance.BorderColor = System.Drawing.Color.White;
this.btnSendParam.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btnSendParam.ForeColor = System.Drawing.Color.White;
this.btnSendParam.Location = new System.Drawing.Point(300, 25);
this.btnSendParam.Name = "btnSendParam";
this.btnSendParam.Size = new System.Drawing.Size(100, 30);
this.btnSendParam.TabIndex = 9;
this.btnSendParam.Text = "发送";
this.btnSendParam.UseVisualStyleBackColor = false;
this.btnSendParam.Click += new System.EventHandler(this.btnSendParam_Click);
//
// groupBox3
//
this.groupBox3.Controls.Add(this.rbtnGR1);
this.groupBox3.Controls.Add(this.rbtnGR0);
this.groupBox3.Dock = System.Windows.Forms.DockStyle.Top;
this.groupBox3.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(224)))), ((int)(((byte)(224)))), ((int)(((byte)(224)))));
this.groupBox3.Location = new System.Drawing.Point(3, 402);
this.groupBox3.Name = "groupBox3";
this.groupBox3.Size = new System.Drawing.Size(586, 57);
this.groupBox3.TabIndex = 8;
this.groupBox3.TabStop = false;
this.groupBox3.Text = "输出电平";
//
// rbtnGR1
//
this.rbtnGR1.AutoSize = true;
this.rbtnGR1.Location = new System.Drawing.Point(164, 20);
this.rbtnGR1.Name = "rbtnGR1";
this.rbtnGR1.Size = new System.Drawing.Size(83, 16);
this.rbtnGR1.TabIndex = 0;
this.rbtnGR1.TabStop = true;
this.rbtnGR1.Text = "上升沿脉冲";
this.rbtnGR1.UseVisualStyleBackColor = true;
this.rbtnGR1.CheckedChanged += new System.EventHandler(this.outLevel_CheckedChanged);
//
// rbtnGR0
//
this.rbtnGR0.AutoSize = true;
this.rbtnGR0.Location = new System.Drawing.Point(12, 21);
this.rbtnGR0.Name = "rbtnGR0";
this.rbtnGR0.Size = new System.Drawing.Size(83, 16);
this.rbtnGR0.TabIndex = 0;
this.rbtnGR0.TabStop = true;
this.rbtnGR0.Text = "下降沿脉冲";
this.rbtnGR0.UseVisualStyleBackColor = true;
this.rbtnGR0.CheckedChanged += new System.EventHandler(this.outLevel_CheckedChanged);
//
// groupBox2
//
this.groupBox2.Controls.Add(this.rbtnTR7);
this.groupBox2.Controls.Add(this.rbtnTR5);
this.groupBox2.Controls.Add(this.rbtnTR3);
this.groupBox2.Controls.Add(this.rbtnTR1);
this.groupBox2.Controls.Add(this.rbtnTR15);
this.groupBox2.Controls.Add(this.rbtnTR6);
this.groupBox2.Controls.Add(this.rbtnTR4);
this.groupBox2.Controls.Add(this.rbtnTR2);
this.groupBox2.Controls.Add(this.rbtnTR0);
this.groupBox2.Dock = System.Windows.Forms.DockStyle.Top;
this.groupBox2.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(224)))), ((int)(((byte)(224)))), ((int)(((byte)(224)))));
this.groupBox2.Location = new System.Drawing.Point(3, 260);
this.groupBox2.Name = "groupBox2";
this.groupBox2.Size = new System.Drawing.Size(586, 142);
this.groupBox2.TabIndex = 7;
this.groupBox2.TabStop = false;
this.groupBox2.Text = "触发模式";
//
// rbtnTR7
//
this.rbtnTR7.AutoSize = true;
this.rbtnTR7.Location = new System.Drawing.Point(164, 86);
this.rbtnTR7.Name = "rbtnTR7";
this.rbtnTR7.Size = new System.Drawing.Size(107, 16);
this.rbtnTR7.TabIndex = 0;
this.rbtnTR7.TabStop = true;
this.rbtnTR7.Text = "内部上升沿触发";
this.rbtnTR7.UseVisualStyleBackColor = true;
this.rbtnTR7.CheckedChanged += new System.EventHandler(this.triggerMode_CheckedChanged);
//
// rbtnTR5
//
this.rbtnTR5.AutoSize = true;
this.rbtnTR5.Location = new System.Drawing.Point(164, 64);
this.rbtnTR5.Name = "rbtnTR5";
this.rbtnTR5.Size = new System.Drawing.Size(131, 16);
this.rbtnTR5.TabIndex = 0;
this.rbtnTR5.TabStop = true;
this.rbtnTR5.Text = "内部跟随高电平触发";
this.rbtnTR5.UseVisualStyleBackColor = true;
this.rbtnTR5.CheckedChanged += new System.EventHandler(this.triggerMode_CheckedChanged);
//
// rbtnTR3
//
this.rbtnTR3.AutoSize = true;
this.rbtnTR3.Location = new System.Drawing.Point(164, 42);
this.rbtnTR3.Name = "rbtnTR3";
this.rbtnTR3.Size = new System.Drawing.Size(107, 16);
this.rbtnTR3.TabIndex = 0;
this.rbtnTR3.TabStop = true;
this.rbtnTR3.Text = "外部上升沿触发";
this.rbtnTR3.UseVisualStyleBackColor = true;
this.rbtnTR3.CheckedChanged += new System.EventHandler(this.triggerMode_CheckedChanged);
//
// rbtnTR1
//
this.rbtnTR1.AutoSize = true;
this.rbtnTR1.Location = new System.Drawing.Point(164, 20);
this.rbtnTR1.Name = "rbtnTR1";
this.rbtnTR1.Size = new System.Drawing.Size(131, 16);
this.rbtnTR1.TabIndex = 0;
this.rbtnTR1.TabStop = true;
this.rbtnTR1.Text = "外部跟随高电平触发";
this.rbtnTR1.UseVisualStyleBackColor = true;
this.rbtnTR1.CheckedChanged += new System.EventHandler(this.triggerMode_CheckedChanged);
//
// rbtnTR15
//
this.rbtnTR15.AutoSize = true;
this.rbtnTR15.Location = new System.Drawing.Point(12, 109);
this.rbtnTR15.Name = "rbtnTR15";
this.rbtnTR15.Size = new System.Drawing.Size(71, 16);
this.rbtnTR15.TabIndex = 0;
this.rbtnTR15.TabStop = true;
this.rbtnTR15.Text = "常亮模式";
this.rbtnTR15.UseVisualStyleBackColor = true;
this.rbtnTR15.CheckedChanged += new System.EventHandler(this.triggerMode_CheckedChanged);
//
// rbtnTR6
//
this.rbtnTR6.AutoSize = true;
this.rbtnTR6.Location = new System.Drawing.Point(12, 87);
this.rbtnTR6.Name = "rbtnTR6";
this.rbtnTR6.Size = new System.Drawing.Size(107, 16);
this.rbtnTR6.TabIndex = 0;
this.rbtnTR6.TabStop = true;
this.rbtnTR6.Text = "内部下降沿触发";
this.rbtnTR6.UseVisualStyleBackColor = true;
this.rbtnTR6.CheckedChanged += new System.EventHandler(this.triggerMode_CheckedChanged);
//
// rbtnTR4
//
this.rbtnTR4.AutoSize = true;
this.rbtnTR4.Location = new System.Drawing.Point(12, 65);
this.rbtnTR4.Name = "rbtnTR4";
this.rbtnTR4.Size = new System.Drawing.Size(131, 16);
this.rbtnTR4.TabIndex = 0;
this.rbtnTR4.TabStop = true;
this.rbtnTR4.Text = "内部跟随低电平触发";
this.rbtnTR4.UseVisualStyleBackColor = true;
this.rbtnTR4.CheckedChanged += new System.EventHandler(this.triggerMode_CheckedChanged);
//
// rbtnTR2
//
this.rbtnTR2.AutoSize = true;
this.rbtnTR2.Location = new System.Drawing.Point(12, 43);
this.rbtnTR2.Name = "rbtnTR2";
this.rbtnTR2.Size = new System.Drawing.Size(107, 16);
this.rbtnTR2.TabIndex = 0;
this.rbtnTR2.TabStop = true;
this.rbtnTR2.Text = "外部下降沿触发";
this.rbtnTR2.UseVisualStyleBackColor = true;
this.rbtnTR2.CheckedChanged += new System.EventHandler(this.triggerMode_CheckedChanged);
//
// rbtnTR0
//
this.rbtnTR0.AutoSize = true;
this.rbtnTR0.Location = new System.Drawing.Point(12, 21);
this.rbtnTR0.Name = "rbtnTR0";
this.rbtnTR0.Size = new System.Drawing.Size(131, 16);
this.rbtnTR0.TabIndex = 0;
this.rbtnTR0.TabStop = true;
this.rbtnTR0.Text = "外部跟随低电平触发";
this.rbtnTR0.UseVisualStyleBackColor = true;
this.rbtnTR0.CheckedChanged += new System.EventHandler(this.triggerMode_CheckedChanged);
//
// panelEx2
//
this.panelEx2.Controls.Add(this.btnLoadParam);
this.panelEx2.Controls.Add(this.comboBox1);
this.panelEx2.Controls.Add(this.btnClose);
this.panelEx2.Controls.Add(this.txtL0);
this.panelEx2.Controls.Add(this.btnOpen);
this.panelEx2.Controls.Add(this.label1);
this.panelEx2.Controls.Add(this.btnSendParam);
this.panelEx2.Controls.Add(this.txtP3);
this.panelEx2.Controls.Add(this.label2);
this.panelEx2.Controls.Add(this.txtP2);
this.panelEx2.Controls.Add(this.label7);
this.panelEx2.Controls.Add(this.txtP1);
this.panelEx2.Controls.Add(this.label6);
this.panelEx2.Controls.Add(this.label3);
this.panelEx2.Controls.Add(this.txtP0);
this.panelEx2.Controls.Add(this.label8);
this.panelEx2.Controls.Add(this.txtT3);
this.panelEx2.Controls.Add(this.label4);
this.panelEx2.Controls.Add(this.txtT2);
this.panelEx2.Controls.Add(this.label9);
this.panelEx2.Controls.Add(this.txtT1);
this.panelEx2.Controls.Add(this.label5);
this.panelEx2.Controls.Add(this.txtT0);
this.panelEx2.Controls.Add(this.cboxF0);
this.panelEx2.Controls.Add(this.txtL3);
this.panelEx2.Controls.Add(this.cboxF1);
this.panelEx2.Controls.Add(this.cboxF3);
this.panelEx2.Controls.Add(this.txtL1);
this.panelEx2.Controls.Add(this.txtL2);
this.panelEx2.Controls.Add(this.cboxF2);
this.panelEx2.Dock = System.Windows.Forms.DockStyle.Top;
this.panelEx2.Location = new System.Drawing.Point(3, 17);
this.panelEx2.Name = "panelEx2";
this.panelEx2.Size = new System.Drawing.Size(586, 243);
this.panelEx2.TabIndex = 6;
//
// txtL0
//
this.txtL0.Location = new System.Drawing.Point(150, 100);
this.txtL0.Name = "txtL0";
this.txtL0.Size = new System.Drawing.Size(51, 21);
this.txtL0.TabIndex = 2;
this.txtL0.KeyUp += new System.Windows.Forms.KeyEventHandler(this.txtParam_KeyUp);
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(10, 103);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(41, 12);
this.label1.TabIndex = 0;
this.label1.Text = "通道1:";
//
// txtP3
//
this.txtP3.Location = new System.Drawing.Point(349, 216);
this.txtP3.Name = "txtP3";
this.txtP3.Size = new System.Drawing.Size(51, 21);
this.txtP3.TabIndex = 2;
this.txtP3.KeyUp += new System.Windows.Forms.KeyEventHandler(this.txtParam_KeyUp);
//
// label2
//
this.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(66, 78);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(29, 12);
this.label2.TabIndex = 0;
this.label2.Text = "启用";
//
// txtP2
//
this.txtP2.Location = new System.Drawing.Point(349, 177);
this.txtP2.Name = "txtP2";
this.txtP2.Size = new System.Drawing.Size(51, 21);
this.txtP2.TabIndex = 2;
this.txtP2.KeyUp += new System.Windows.Forms.KeyEventHandler(this.txtParam_KeyUp);
//
// label7
//
this.label7.AutoSize = true;
this.label7.Location = new System.Drawing.Point(10, 142);
this.label7.Name = "label7";
this.label7.Size = new System.Drawing.Size(41, 12);
this.label7.TabIndex = 0;
this.label7.Text = "通道2:";
//
// txtP1
//
this.txtP1.Location = new System.Drawing.Point(349, 139);
this.txtP1.Name = "txtP1";
this.txtP1.Size = new System.Drawing.Size(51, 21);
this.txtP1.TabIndex = 2;
this.txtP1.KeyUp += new System.Windows.Forms.KeyEventHandler(this.txtParam_KeyUp);
//
// label3
//
this.label3.AutoSize = true;
this.label3.Location = new System.Drawing.Point(155, 78);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(29, 12);
this.label3.TabIndex = 0;
this.label3.Text = "亮度";
//
// txtP0
//
this.txtP0.Location = new System.Drawing.Point(349, 100);
this.txtP0.Name = "txtP0";
this.txtP0.Size = new System.Drawing.Size(51, 21);
this.txtP0.TabIndex = 2;
this.txtP0.KeyUp += new System.Windows.Forms.KeyEventHandler(this.txtParam_KeyUp);
//
// label8
//
this.label8.AutoSize = true;
this.label8.Location = new System.Drawing.Point(10, 180);
this.label8.Name = "label8";
this.label8.Size = new System.Drawing.Size(41, 12);
this.label8.TabIndex = 0;
this.label8.Text = "通道3:";
//
// txtT3
//
this.txtT3.Location = new System.Drawing.Point(244, 216);
this.txtT3.Name = "txtT3";
this.txtT3.Size = new System.Drawing.Size(51, 21);
this.txtT3.TabIndex = 2;
this.txtT3.KeyUp += new System.Windows.Forms.KeyEventHandler(this.txtParam_KeyUp);
//
// label4
//
this.label4.AutoSize = true;
this.label4.Location = new System.Drawing.Point(242, 78);
this.label4.Name = "label4";
this.label4.Size = new System.Drawing.Size(53, 12);
this.label4.TabIndex = 0;
this.label4.Text = "发光时间";
//
// txtT2
//
this.txtT2.Location = new System.Drawing.Point(244, 177);
this.txtT2.Name = "txtT2";
this.txtT2.Size = new System.Drawing.Size(51, 21);
this.txtT2.TabIndex = 2;
this.txtT2.KeyUp += new System.Windows.Forms.KeyEventHandler(this.txtParam_KeyUp);
//
// label9
//
this.label9.AutoSize = true;
this.label9.Location = new System.Drawing.Point(10, 219);
this.label9.Name = "label9";
this.label9.Size = new System.Drawing.Size(41, 12);
this.label9.TabIndex = 0;
this.label9.Text = "通道4:";
//
// txtT1
//
this.txtT1.Location = new System.Drawing.Point(244, 139);
this.txtT1.Name = "txtT1";
this.txtT1.Size = new System.Drawing.Size(51, 21);
this.txtT1.TabIndex = 2;
this.txtT1.KeyUp += new System.Windows.Forms.KeyEventHandler(this.txtParam_KeyUp);
//
// label5
//
this.label5.AutoSize = true;
this.label5.Location = new System.Drawing.Point(347, 78);
this.label5.Name = "label5";
this.label5.Size = new System.Drawing.Size(53, 12);
this.label5.TabIndex = 0;
this.label5.Text = "输出时间";
//
// txtT0
//
this.txtT0.Location = new System.Drawing.Point(244, 100);
this.txtT0.Name = "txtT0";
this.txtT0.Size = new System.Drawing.Size(51, 21);
this.txtT0.TabIndex = 2;
this.txtT0.KeyUp += new System.Windows.Forms.KeyEventHandler(this.txtParam_KeyUp);
//
// cboxF0
//
this.cboxF0.AutoSize = true;
this.cboxF0.Location = new System.Drawing.Point(72, 103);
this.cboxF0.Name = "cboxF0";
this.cboxF0.Size = new System.Drawing.Size(15, 14);
this.cboxF0.TabIndex = 1;
this.cboxF0.UseVisualStyleBackColor = true;
this.cboxF0.CheckedChanged += new System.EventHandler(this.enable_CheckedChanged);
//
// txtL3
//
this.txtL3.Location = new System.Drawing.Point(150, 216);
this.txtL3.Name = "txtL3";
this.txtL3.Size = new System.Drawing.Size(51, 21);
this.txtL3.TabIndex = 2;
this.txtL3.KeyUp += new System.Windows.Forms.KeyEventHandler(this.txtParam_KeyUp);
//
// cboxF1
//
this.cboxF1.AutoSize = true;
this.cboxF1.Location = new System.Drawing.Point(72, 142);
this.cboxF1.Name = "cboxF1";
this.cboxF1.Size = new System.Drawing.Size(15, 14);
this.cboxF1.TabIndex = 1;
this.cboxF1.UseVisualStyleBackColor = true;
this.cboxF1.CheckedChanged += new System.EventHandler(this.enable_CheckedChanged);
//
// cboxF3
//
this.cboxF3.AutoSize = true;
this.cboxF3.Location = new System.Drawing.Point(72, 219);
this.cboxF3.Name = "cboxF3";
this.cboxF3.Size = new System.Drawing.Size(15, 14);
this.cboxF3.TabIndex = 1;
this.cboxF3.UseVisualStyleBackColor = true;
this.cboxF3.CheckedChanged += new System.EventHandler(this.enable_CheckedChanged);
//
// txtL1
//
this.txtL1.Location = new System.Drawing.Point(150, 139);
this.txtL1.Name = "txtL1";
this.txtL1.Size = new System.Drawing.Size(51, 21);
this.txtL1.TabIndex = 2;
this.txtL1.KeyUp += new System.Windows.Forms.KeyEventHandler(this.txtParam_KeyUp);
//
// txtL2
//
this.txtL2.Location = new System.Drawing.Point(150, 177);
this.txtL2.Name = "txtL2";
this.txtL2.Size = new System.Drawing.Size(51, 21);
this.txtL2.TabIndex = 2;
this.txtL2.KeyUp += new System.Windows.Forms.KeyEventHandler(this.txtParam_KeyUp);
//
// cboxF2
//
this.cboxF2.AutoSize = true;
this.cboxF2.Location = new System.Drawing.Point(72, 180);
this.cboxF2.Name = "cboxF2";
this.cboxF2.Size = new System.Drawing.Size(15, 14);
this.cboxF2.TabIndex = 1;
this.cboxF2.UseVisualStyleBackColor = true;
this.cboxF2.CheckedChanged += new System.EventHandler(this.enable_CheckedChanged);
//
// panelEx1
//
this.panelEx1.Controls.Add(this.groupBox4);
this.panelEx1.Controls.Add(this.groupBox1);
this.panelEx1.Dock = System.Windows.Forms.DockStyle.Left;
this.panelEx1.Location = new System.Drawing.Point(0, 0);
this.panelEx1.Name = "panelEx1";
this.panelEx1.Size = new System.Drawing.Size(592, 744);
this.panelEx1.TabIndex = 1;
//
// groupBox4
//
this.groupBox4.Controls.Add(this.txtRunResult);
this.groupBox4.Dock = System.Windows.Forms.DockStyle.Fill;
this.groupBox4.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(224)))), ((int)(((byte)(224)))), ((int)(((byte)(224)))));
this.groupBox4.Location = new System.Drawing.Point(0, 468);
this.groupBox4.Name = "groupBox4";
this.groupBox4.Size = new System.Drawing.Size(592, 276);
this.groupBox4.TabIndex = 1;
this.groupBox4.TabStop = false;
this.groupBox4.Text = "Result";
//
// txtRunResult
//
this.txtRunResult.BackColor = System.Drawing.Color.Black;
this.txtRunResult.Dock = System.Windows.Forms.DockStyle.Fill;
this.txtRunResult.ForeColor = System.Drawing.Color.Lime;
this.txtRunResult.Location = new System.Drawing.Point(3, 17);
this.txtRunResult.Name = "txtRunResult";
this.txtRunResult.Size = new System.Drawing.Size(586, 256);
this.txtRunResult.TabIndex = 2;
this.txtRunResult.Text = "";
//
// btnClose
//
this.btnClose.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.btnClose.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(56)))), ((int)(((byte)(56)))), ((int)(((byte)(56)))));
this.btnClose.FlatAppearance.BorderColor = System.Drawing.Color.White;
this.btnClose.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btnClose.ForeColor = System.Drawing.Color.White;
this.btnClose.Location = new System.Drawing.Point(445, 25);
this.btnClose.Name = "btnClose";
this.btnClose.Size = new System.Drawing.Size(100, 30);
this.btnClose.TabIndex = 9;
this.btnClose.Text = "关闭";
this.btnClose.UseVisualStyleBackColor = false;
this.btnClose.Click += new System.EventHandler(this.btnClose_Click_1);
//
// comboBox1
//
this.comboBox1.FormattingEnabled = true;
this.comboBox1.ItemHeight = 12;
this.comboBox1.Location = new System.Drawing.Point(56, 0);
this.comboBox1.Name = "comboBox1";
this.comboBox1.Size = new System.Drawing.Size(229, 20);
this.comboBox1.TabIndex = 10;
this.comboBox1.SelectedIndexChanged += new System.EventHandler(this.comboBox1_SelectedIndexChanged);
//
// label6
//
this.label6.AutoSize = true;
this.label6.Location = new System.Drawing.Point(12, 3);
this.label6.Name = "label6";
this.label6.Size = new System.Drawing.Size(35, 12);
this.label6.TabIndex = 0;
this.label6.Text = "串口:";
//
// LightConfig
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(11)))), ((int)(((byte)(16)))), ((int)(((byte)(36)))));
this.ClientSize = new System.Drawing.Size(600, 744);
this.Controls.Add(this.panelEx1);
this.Name = "LightConfig";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "LightConfig";
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.LightConfig_FormClosing);
this.Load += new System.EventHandler(this.LightConfig_Load);
this.groupBox1.ResumeLayout(false);
this.groupBox3.ResumeLayout(false);
this.groupBox3.PerformLayout();
this.groupBox2.ResumeLayout(false);
this.groupBox2.PerformLayout();
this.panelEx2.ResumeLayout(false);
this.panelEx2.PerformLayout();
this.panelEx1.ResumeLayout(false);
this.groupBox4.ResumeLayout(false);
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.GroupBox groupBox1;
private System.Windows.Forms.Panel panelEx1;
private System.Windows.Forms.Label label5;
private System.Windows.Forms.Label label4;
private System.Windows.Forms.Label label3;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.CheckBox cboxF0;
private System.Windows.Forms.TextBox txtP3;
private System.Windows.Forms.TextBox txtP2;
private System.Windows.Forms.TextBox txtP1;
private System.Windows.Forms.TextBox txtP0;
private System.Windows.Forms.TextBox txtT3;
private System.Windows.Forms.TextBox txtT2;
private System.Windows.Forms.TextBox txtT1;
private System.Windows.Forms.TextBox txtT0;
private System.Windows.Forms.TextBox txtL3;
private System.Windows.Forms.CheckBox cboxF3;
private System.Windows.Forms.TextBox txtL2;
private System.Windows.Forms.CheckBox cboxF2;
private System.Windows.Forms.TextBox txtL1;
private System.Windows.Forms.CheckBox cboxF1;
private System.Windows.Forms.TextBox txtL0;
private System.Windows.Forms.Label label9;
private System.Windows.Forms.Label label8;
private System.Windows.Forms.Label label7;
private System.Windows.Forms.GroupBox groupBox3;
private System.Windows.Forms.RadioButton rbtnGR1;
private System.Windows.Forms.RadioButton rbtnGR0;
private System.Windows.Forms.GroupBox groupBox2;
private System.Windows.Forms.RadioButton rbtnTR7;
private System.Windows.Forms.RadioButton rbtnTR5;
private System.Windows.Forms.RadioButton rbtnTR3;
private System.Windows.Forms.RadioButton rbtnTR1;
private System.Windows.Forms.RadioButton rbtnTR15;
private System.Windows.Forms.RadioButton rbtnTR6;
private System.Windows.Forms.RadioButton rbtnTR4;
private System.Windows.Forms.RadioButton rbtnTR2;
private System.Windows.Forms.RadioButton rbtnTR0;
private System.Windows.Forms.Panel panelEx2;
private System.Windows.Forms.Button btnSendParam;
private System.Windows.Forms.Button btnLoadParam;
private System.Windows.Forms.Button btnOpen;
private System.Windows.Forms.GroupBox groupBox4;
private System.Windows.Forms.RichTextBox txtRunResult;
private System.Windows.Forms.Button btnClose;
private System.Windows.Forms.ComboBox comboBox1;
private System.Windows.Forms.Label label6;
}
}

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

@ -0,0 +1,93 @@
<?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>{F361C146-D5E4-4310-A35C-1217FB07FE6C}</ProjectGuid>
<OutputType>WinExe</OutputType>
<RootNamespace>LightControl</RootNamespace>
<AssemblyName>LightControl</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="Rs.Framework, Version=2.20.24.1, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>bin\Debug\Rs.Framework.dll</HintPath>
</Reference>
<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="Form1.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Form1.Designer.cs">
<DependentUpon>Form1.cs</DependentUpon>
</Compile>
<Compile Include="LightConfig.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="LightConfig.designer.cs">
<DependentUpon>LightConfig.cs</DependentUpon>
</Compile>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<EmbeddedResource Include="LightConfig.resx">
<DependentUpon>LightConfig.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
<SubType>Designer</SubType>
</EmbeddedResource>
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
<Compile Include="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

@ -0,0 +1,23 @@
using Rs.MotionPlat.SysConfig;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace LightControl
{
internal static class Program
{
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new LightConfig());
}
}
}

@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// 有关程序集的一般信息由以下
// 控制。更改这些特性值可修改
// 与程序集关联的信息。
[assembly: AssemblyTitle("LightControl")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("LightControl")]
[assembly: AssemblyCopyright("Copyright © 2024")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// 将 ComVisible 设置为 false 会使此程序集中的类型
//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
//请将此类型的 ComVisible 特性设置为 true。
[assembly: ComVisible(false)]
// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
[assembly: Guid("f361c146-d5e4-4310-a35c-1217fb07fe6c")]
// 程序集的版本信息由下列四个值组成:
//
// 主版本
// 次版本
// 生成号
// 修订号
//
//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值
//通过使用 "*",如下所示:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

@ -0,0 +1,71 @@
//------------------------------------------------------------------------------
// <auto-generated>
// 此代码由工具生成。
// 运行时版本: 4.0.30319.42000
//
// 对此文件的更改可能导致不正确的行为,如果
// 重新生成代码,则所做更改将丢失。
// </auto-generated>
//------------------------------------------------------------------------------
namespace LightControl.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("LightControl.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;
}
}
}
}

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

@ -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 LightControl.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;
}
}
}
}

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

@ -5,6 +5,8 @@ VisualStudioVersion = 17.4.33403.182
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Rs.SkyLine", "Rs.SkyLine\Rs.SkyLine.csproj", "{983F6B3C-E08A-42F0-8A34-2E6590636811}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LightControl", "LightControl\LightControl.csproj", "{F361C146-D5E4-4310-A35C-1217FB07FE6C}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -15,6 +17,10 @@ Global
{983F6B3C-E08A-42F0-8A34-2E6590636811}.Debug|Any CPU.Build.0 = Debug|Any CPU
{983F6B3C-E08A-42F0-8A34-2E6590636811}.Release|Any CPU.ActiveCfg = Release|Any CPU
{983F6B3C-E08A-42F0-8A34-2E6590636811}.Release|Any CPU.Build.0 = Release|Any CPU
{F361C146-D5E4-4310-A35C-1217FB07FE6C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F361C146-D5E4-4310-A35C-1217FB07FE6C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F361C146-D5E4-4310-A35C-1217FB07FE6C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F361C146-D5E4-4310-A35C-1217FB07FE6C}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

@ -428,6 +428,10 @@ namespace Rs.MotionPlat.Flow
public const int = 1097;
/// <summary>
/// 上相机拍照超时
/// </summary>
public const int = 1098;

@ -169,73 +169,80 @@ namespace Rs.MotionPlat.Flow.Camera
VisionResult vr = new VisionResult();
vr.SourceImage = image;
HObject searchImg = new HObject();
if (upCameraScanBarCodeModel.SearchRegion.IsInitialized())
HOperatorSet.ReduceDomain(image, upCameraScanBarCodeModel.SearchRegion, out searchImg);
else
searchImg = image;
if(bNeedLocation)
try
{
HOperatorSet.GetShapeModelContours(out HObject modelContours, upCameraScanBarCodeModel.ModelID, 1);
HOperatorSet.FindShapeModel(searchImg, upCameraScanBarCodeModel.ModelID,
AngleTool.Deg2Rad(double.Parse(upCameraScanBarCodeModel.AngleStart)),
AngleTool.Deg2Rad(Math.Abs((double.Parse(upCameraScanBarCodeModel.AngleExtent) - double.Parse(upCameraScanBarCodeModel.AngleStart)))),
new HTuple(double.Parse(upCameraScanBarCodeModel.Score)),
1,
0.5,
"least_squares",
0,
0.9,
out HTuple row, out HTuple column, out HTuple angle, out HTuple score);
if (score.Length > 0)
if (upCameraScanBarCodeModel.SearchRegion.IsInitialized())
HOperatorSet.ReduceDomain(image, upCameraScanBarCodeModel.SearchRegion, out searchImg);
else
searchImg = image;
if (bNeedLocation)
{
vr.OffsetX = (column.D - upCameraScanBarCodeModel.ModelMatchResult[1].D) * GlobalVar.UpCameraMmPerPixel;
vr.OffsetY = -1 * (row.D - upCameraScanBarCodeModel.ModelMatchResult[0].D) * GlobalVar.UpCameraMmPerPixel;
vr.OffsetR = AngleTool.Rad2Deg((angle.D - upCameraScanBarCodeModel.ModelMatchResult[2].D));
vr.SourceImage = image;
vr.SearchModelOK = true;
//if (Math.Abs(vr.OffsetX) < GlobalVar.TurnoverTrayLocateXRange
// && Math.Abs(vr.OffsetY) < GlobalVar.TurnoverTrayLocateYRange
// && Math.Abs(vr.OffsetR) < GlobalVar.TurnoverTrayLocateRRange)
//{
// vr.SearchModelOK = true;
//}
HOperatorSet.GetShapeModelContours(out HObject modelContours, upCameraScanBarCodeModel.ModelID, 1);
HOperatorSet.FindShapeModel(searchImg, upCameraScanBarCodeModel.ModelID,
AngleTool.Deg2Rad(double.Parse(upCameraScanBarCodeModel.AngleStart)),
AngleTool.Deg2Rad(Math.Abs((double.Parse(upCameraScanBarCodeModel.AngleExtent) - double.Parse(upCameraScanBarCodeModel.AngleStart)))),
new HTuple(double.Parse(upCameraScanBarCodeModel.Score)),
1,
0.5,
"least_squares",
0,
0.9,
out HTuple row, out HTuple column, out HTuple angle, out HTuple score);
if (score.Length > 0)
{
vr.OffsetX = (column.D - upCameraScanBarCodeModel.ModelMatchResult[1].D) * GlobalVar.UpCameraMmPerPixel;
vr.OffsetY = -1 * (row.D - upCameraScanBarCodeModel.ModelMatchResult[0].D) * GlobalVar.UpCameraMmPerPixel;
vr.OffsetR = AngleTool.Rad2Deg((angle.D - upCameraScanBarCodeModel.ModelMatchResult[2].D));
vr.SourceImage = image;
vr.SearchModelOK = true;
//if (Math.Abs(vr.OffsetX) < GlobalVar.TurnoverTrayLocateXRange
// && Math.Abs(vr.OffsetY) < GlobalVar.TurnoverTrayLocateYRange
// && Math.Abs(vr.OffsetR) < GlobalVar.TurnoverTrayLocateRRange)
//{
// vr.SearchModelOK = true;
//}
}
else
{
vr.SearchModelOK = false;
}
}
else
{
vr.SearchModelOK = false;
vr.SearchModelOK = true;
}
}
else
{
vr.SearchModelOK = true;
}
if(bNeedScanBarcode)
{
//只有定位成功的才去扫二维码
if (vr.SearchModelOK && !GlobalVar.EnableScanBarCodeByDownCamera)
if (bNeedScanBarcode)
{
string sn = FindCode(image, upCameraScanBarCodeModel.BarCodeRegion);
if (string.IsNullOrEmpty(sn))
//只有定位成功的才去扫二维码
if (vr.SearchModelOK && !GlobalVar.EnableScanBarCodeByDownCamera)
{
vr.ScanBarCodeOK = false;
}
else
{
if(GlobalVar.ImageSaveDays>0)
string sn = FindCode(image, upCameraScanBarCodeModel.BarCodeRegion);
if (string.IsNullOrEmpty(sn))
{
string dirname = $"{GlobalVar.ImageSavePath}/{DateTime.Now.ToString("yyyyMMdd")}/scanbarcode";
if (!Directory.Exists(dirname))
vr.ScanBarCodeOK = false;
}
else
{
if (GlobalVar.ImageSaveDays > 0)
{
Directory.CreateDirectory(dirname);
string dirname = $"{GlobalVar.ImageSavePath}/{DateTime.Now.ToString("yyyyMMdd")}/scanbarcode";
if (!Directory.Exists(dirname))
{
Directory.CreateDirectory(dirname);
}
HOperatorSet.WriteImage(image, "bmp", 0, $"{dirname}//{sn}_{DateTime.Now.ToString("yyyyMMddHHmmssfff")}_{slotIndex}");
}
HOperatorSet.WriteImage(image, "bmp", 0, $"{dirname}//{sn}_{DateTime.Now.ToString("yyyyMMddHHmmssfff")}_{slotIndex}");
vr.ScanBarCodeOK = true;
vr.SN = sn;
}
vr.ScanBarCodeOK = true;
vr.SN = sn;
}
}
}
catch (Exception ex)
{
LogHelper.Debug($"TurnoverTrayDumpProductOK:{ex.Message}");
}
return vr;
}
@ -336,7 +343,7 @@ namespace Rs.MotionPlat.Flow.Camera
}
catch (Exception ex)
{
LogHelper.Error(ex.Message, ex);
LogHelper.Debug(ex.Message, ex);
return "";
}
}

@ -64,6 +64,10 @@ namespace Rs.MotionPlat.Flow.SubFlow
Stopwatch timeout = new Stopwatch();
string logInfo = string.Empty;
Stopwatch scanBarCodeWait= new Stopwatch();
/// <summary>
/// 重扫次数
/// </summary>
int reTakePicNum = 0;
//double targetLoadX=0.0,targetLoadY=0.0;
bool exit = true;
//ManualResetEvent grabFinishedEvent = new ManualResetEvent(true);
@ -271,9 +275,20 @@ namespace Rs.MotionPlat.Flow.SubFlow
}
else
{
//拍照超时
MessageQueue.Instance.Warn(GetClassName() + "上相机拍照超时,重新拍照");
step = EUpCameraScanBarCodeFlowStep.;
if(reTakePicNum<6)
{
reTakePicNum++;
//拍照超时
MessageQueue.Instance.Warn(GetClassName() + "上相机拍照超时,重新拍照");
step = EUpCameraScanBarCodeFlowStep.;
}
else
{
alarmEntity = AlarmCollection.Get(AlarmConstID.);
AlarmMessageBox.ShowDialog(alarmEntity, ETipButton.Retry, null);
reTakePicNum = 0;
step = EUpCameraScanBarCodeFlowStep.;
}
}
break;
case EUpCameraScanBarCodeFlowStep.:
@ -281,27 +296,45 @@ namespace Rs.MotionPlat.Flow.SubFlow
vReslutList.Clear();
GC.Collect();
int slotIndex = 0;
foreach (var img in grabImages)
try
{
int sIndex = 0;
if (!isReverse)
{
sIndex = startSlotIndex + slotIndex;
}
else
foreach (var img in grabImages)
{
sIndex = startSlotIndex - slotIndex;
}
VisionResult vr = new VisionResult();
if (TurnoverTrayManager.Instance.Slot(sIndex).IsHasProduct)
{
vr = VisionManager.TurnoverTrayDumpProductOK(img, GlobalVar.EnableTurnoverTrayRecheck, true, sIndex);
int sIndex = 0;
if (!isReverse)
{
sIndex = startSlotIndex + slotIndex;
}
else
{
sIndex = startSlotIndex - slotIndex;
}
VisionResult vr = new VisionResult();
if (TurnoverTrayManager.Instance.Slot(sIndex).IsHasProduct)
{
vr = VisionManager.TurnoverTrayDumpProductOK(img, GlobalVar.EnableTurnoverTrayRecheck, true, sIndex);
if(vr!=null && vr.ScanBarCodeOK)
{
logInfo = GetClassName()+$"穴位:{sIndex} SN={vr.SN}";
LogHelper.Debug(logInfo);
}
}
else
{
logInfo = GetClassName() + $"穴位:{sIndex} 无产品";
LogHelper.Debug(logInfo);
}
vr.SlotIndex = sIndex;
vReslutList.Add(vr);
slotIndex++;
}
vr.SlotIndex = sIndex;
vReslutList.Add(vr);
slotIndex++;
exit = true;
}
catch (Exception ex)
{
logInfo = GetClassName()+$"{ex.Message}";
LogHelper.Debug(logInfo);
}
exit = true;
//grabFinishedEvent.Set();
break;
}

@ -31,6 +31,6 @@ using System.Runtime.InteropServices;
//
//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值
//通过使用 "*",如下所示:
[assembly: AssemblyVersion("3.20.24.59")]
[assembly: AssemblyVersion("3.20.24.61")]
//[assembly: AssemblyVersion("1.0.0.0")]
//[assembly: AssemblyFileVersion("1.0.0.0")]

Loading…
Cancel
Save