using A036.Process; using Autofac; using Bro.Common.Helper; using Bro.Common.Interface; using Bro.Common.Model; using Bro.Common.PubSub; using Bro.Common.UI; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using System; using System.Collections.Generic; using System.Data; using System.Diagnostics; using System.Drawing; using System.IO; using System.Linq; using System.Reflection; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; using static Bro.Common.Helper.EnumHelper; namespace A034.Config { public partial class ConfigFrm : Form { private IStationProcess Process { get; set; } = null; IStationConfig _config = null; IStationConfig Config { get => _config; set { _config = value; if (Process != null) { InitialCalibrationMethod(); InitialAllTestMethod(); InitialDevices(); } } } ProcessConfig ProcessConfig { get => Config as ProcessConfig; } Canvas canvasImage = new Canvas(); #region 用户登录 private bool isLogin = false; public bool IsLogin { get => isLogin; set { isLogin = value; tsslLoginStatus.Text = isLogin ? "已登录" : "未登录"; } } private void tsslLoginStatus_Click(object sender, EventArgs e) { if (!IsLogin) { IsLogin = UserLogin(); } } private bool UserLogin() { AdvancedPwdFrm pwdFrm = new AdvancedPwdFrm(); return pwdFrm.ShowDialog() == DialogResult.OK; } #endregion public ConfigFrm() { InitializeComponent(); canvasImage = new Canvas(); canvasImage.IsShowElementList = false; canvasImage.Dock = DockStyle.Fill; plCanvas.Controls.Add(canvasImage); } private void Form1_Load(object sender, EventArgs e) { FillProductionCodes(); //_servicePanel.Dock = DockStyle.Fill; //_servicePanel.OnServiceStateChanged = OnServiceStateChanged; //_servicePanel.GetServiceStatus(); //tabControl1.TabPages["tbService"].Controls.Add(_servicePanel); if (cboProductionCode.Text == "Default") { LoadProcess("Default"); } } private void FillProductionCodes() { List codes = new List(); string configPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Setting.json"); if (File.Exists(configPath)) { using (StreamReader reader = new StreamReader(configPath, System.Text.Encoding.UTF8)) { string dataStr = reader.ReadToEnd(); JObject data = JsonConvert.DeserializeObject(dataStr); if (data.ContainsKey("ProductionCodes")) { codes = JsonConvert.DeserializeObject>(data.Value("ProductionCodes")); } } } if (codes == null || codes.Count == 0) { codes = new List() { "Default" }; } UIHelper.SetCombo(cboProductionCode, codes, "", ""); } //private object OnExceptionUpdate(ISubscriber arg1, object arg2, object arg3) //{ // Exception ex = arg3 as Exception; // RecordException(arg2.ToString() + "\r\n" + ex?.GetExceptionMessage()); // return null; //} private void btnSaveProcess_Click(object sender, EventArgs e) { //if (!OpBeforeSaveConfig()) //{ // return; //} //string msg = ""; //if (Process == null || Process.StationConfig.StationCode != cboStationCode.Text.Trim()) // Process = StationFactory.CreateStationProcess(cboStationCode.Text.Trim(), "xcd", out msg); if (Process == null) Process = new ProcessControl(); if (!IsLogin) { IsLogin = UserLogin(); } if (IsLogin) { Process.SaveStationConfig(propConfig.SelectedObject as IStationConfig); MessageBox.Show(@"Save done"); } else { MessageBox.Show("未通过用户验证,无法保存配置"); } } private void btnLoadProcess_Click(object sender, EventArgs e) { LoadProcess(cboProductionCode.Text); MessageBox.Show(@"Load done"); } private void LoadProcess(string productionCode) { Process = new ProcessControl(productionCode); propConfig.SelectedObject = Config = Process.StationConfig; //InitialService((Process.StationConfig as ProcessConfig).ServicePort); LoadCameras(); (Process as ProcessControl).OnLog = OnProcessLog; } private void btnStartProcess_Click(object sender, EventArgs e) { Process.Open(); MessageBox.Show(@"Start!"); btnStartProcess.Visible = false; btnStopProcess.Visible = true; } private async void OnProcessLog(DateTime dt, string prefix, string msg) { await Task.Run(() => { RecordMsg(dt, prefix, msg); }); } private void btnStopProcess_Click(object sender, EventArgs e) { chkContinueMode.Checked = false; Process.Close(); MessageBox.Show(@"Stop!"); btnStartProcess.Visible = true; btnStopProcess.Visible = false; } #region 标定 Dictionary _calibrationMethodDict = new Dictionary(); MethodInfo _calibrationMethod = null; private void InitialCalibrationMethod() { _calibrationMethodDict.Clear(); Process.GetType().GetMethods().ToList().ForEach(m => { var attr = m.GetCustomAttribute(); if (attr != null && attr.InvokeType == InvokeType.CalibInvoke) { _calibrationMethodDict[attr] = m; } }); UIHelper.SetCombo(cboCalibrationMethod, _calibrationMethodDict.Keys.ToList(), "MethodDesc", "MethodCode"); cboCalibrationMethod.SelectedIndexChanged -= cboCalibrationMethod_SelectedIndexChanged; cboCalibrationMethod.SelectedIndexChanged += cboCalibrationMethod_SelectedIndexChanged; } private void cboCalibrationMethod_SelectedIndexChanged(object sender, EventArgs e) { if (cboCalibrationMethod.SelectedIndex >= 0) { string methodCode = cboCalibrationMethod.SelectedValue.ToString(); _calibrationMethod = _calibrationMethodDict[_calibrationMethodDict.Keys.FirstOrDefault(u => u.MethodCode == methodCode)]; if (Process.StationConfig.ProcessOpConfigDict.Keys.Contains(methodCode)) { propCalibrationConfig.SelectedObject = Process.StationConfig.ProcessOpConfigDict[methodCode]; } else { MessageBox.Show(@"Config of " + methodCode + @" is not found"); } } } private void btnStartCalibration_Click(object sender, EventArgs e) { btnStartCalibration.Enabled = false; IDevice sourceDevice = cboCalibSourceDevices.SelectedItem as IDevice; IDevice executeDevice = cboCalibExecuteDevice.SelectedItem as IDevice; IOperationConfig config = propCalibrationConfig.SelectedObject as IOperationConfig; Task.Run(() => { try { if (config != null) { config.InputPara = null; } _calibrationMethod.Invoke(Process, new object[] { config, executeDevice, sourceDevice }); } catch (Exception ex) { MessageBox.Show(@"Calibration cancel\r\n" + ex.GetExceptionMessage()); return; } finally { if (this.InvokeRequired) { this.Invoke(new Action(() => btnStartCalibration.Enabled = true)); } else { btnStartCalibration.Enabled = true; } } MessageBox.Show(@"Operation Done"); }); } #endregion #region Test Dictionary _allTestMethod = new Dictionary(); MethodInfo _testMethod = null; private void InitialDevices() { List deviceList = new List(); using (var scope = GlobalVar.Container.BeginLifetimeScope()) { deviceList = scope.Resolve>(); } List list = deviceList.Select(u => u as ISimpleDevice).ToList(); UIHelper.SetCombo(cboCalibSourceDevices, new List(list), "Name", "Id"); UIHelper.SetCombo(cboTestSourceDevices, new List(list), "Name", "Id"); UIHelper.SetCombo(cboCalibExecuteDevice, new List(list), "Name", "Id"); UIHelper.SetCombo(cboTestExecuteDevice, new List(list), "Name", "Id"); } private void InitialAllTestMethod() { _allTestMethod.Clear(); Process.GetType().GetMethods().ToList().ForEach(m => { var attr = m.GetCustomAttribute(); if (attr != null && attr.InvokeType == InvokeType.TestInvoke) { _allTestMethod[attr] = m; } }); UIHelper.SetCombo(cboTestMethod, _allTestMethod.Keys.ToList(), "MethodDesc", "MethodCode"); cboTestMethod.SelectedIndexChanged -= cboTestMethod_SelectedIndexChanged; cboTestMethod.SelectedIndexChanged += cboTestMethod_SelectedIndexChanged; } private void cboTestMethod_SelectedIndexChanged(object sender, EventArgs e) { if (cboTestMethod.SelectedIndex >= 0) { string methodCode = cboTestMethod.SelectedValue.ToString(); var attr = _allTestMethod.Keys.FirstOrDefault(u => u.MethodCode == methodCode); if (attr == null) return; _testMethod = _allTestMethod[attr]; if (Process.StationConfig.ProcessOpConfigDict.Keys.Contains(methodCode)) { propGridTestMethod.SelectedObject = Process.StationConfig.ProcessOpConfigDict[methodCode]; } else { MessageBox.Show(@"Config of " + methodCode + @" is not found"); } } } private void btnManualTrigger_Click(object sender, EventArgs e) { IDevice sourceDevice = cboTestSourceDevices.SelectedItem as IDevice; IDevice executeDevice = cboTestExecuteDevice.SelectedItem as IDevice; new Task((m) => { MethodInfo method = m as MethodInfo; int invokeTimes = 1; if (!int.TryParse(txtInvokeTimes.Text.Trim(), out invokeTimes)) { invokeTimes = 1; } ProcessResponse response = null; if (invokeTimes == 1) { try { Stopwatch sw = new Stopwatch(); sw.Start(); response = method.Invoke(Process, new object[] { propGridTestMethod.SelectedObject as IOperationConfig, executeDevice, sourceDevice }) as ProcessResponse; sw.Stop(); //RecordMsg($"{method.Name}调用耗时:{sw.ElapsedMilliseconds}ms"); (Process as ProcessControl).LogAsync(DateTime.Now, $"{method.Name}调用耗时:{sw.ElapsedMilliseconds}ms", ""); } catch (Exception ex) { MessageBox.Show("Method cancel\r\n\r\n" + ex.InnerException.GetExceptionMessage()); return; } MessageBox.Show("Method done\r\n" + JsonConvert.SerializeObject(response, new JsonSerializerSettings() { TypeNameHandling = TypeNameHandling.None })); } else { for (int i = 0; i < invokeTimes; i++) { try { response = method.Invoke(Process, new object[] { propGridTestMethod.SelectedObject as IOperationConfig }) as ProcessResponse; } catch (Exception ex) { RecordMsg(DateTime.Now, $"Method Cancel,Time:{i + 1}", ex.InnerException.GetExceptionMessage()); } RecordMsg(DateTime.Now, $"Method Done", JsonConvert.SerializeObject(response, new JsonSerializerSettings() { TypeNameHandling = TypeNameHandling.None })); Thread.Sleep(250); } } }, _testMethod).Start(); } #endregion private void ConfigFrm_FormClosing(object sender, FormClosingEventArgs e) { try { Process.Close(); (Process as ProcessControl).OnLog = null; Thread.Sleep(500); } catch (Exception) { } } #region 日志和显示 public void RecordMsg(DateTime dt, string prefix, string msg, bool isLog = false) { if (this.InvokeRequired) { this.Invoke(new Action(RecordMsg), dt, prefix, msg, isLog); } else { if (isLog) { LogAsync(dt, prefix, msg); } txtError.AppendText($"{dt.ToString("HH:mm:ss.fff")}\t{prefix}\t{msg}\r\n"); while (txtError.Lines.Length > 1000) { txtError.Lines = txtError.Lines.Skip(500).ToArray(); } } } private void btnClearError_Click(object sender, EventArgs e) { txtError.Clear(); } static object lockObj = new object(); public async void LogAsync(DateTime dt, string prefix, string msg) { await Task.Run(() => { string logPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "ExLog_" + DateTime.Today.ToString("yyyyMMdd") + ".txt"); lock (lockObj) { using (StreamWriter writer = new StreamWriter(logPath, true)) { writer.WriteLine($"{dt.ToString("HH:mm:ss")}\t{prefix}\t{msg}"); writer.WriteLine(); writer.Flush(); writer.Close(); } } }); } private void LoadCameras() { cboCameras.DataSource = null; List cameras = new List() { new { Desc = "All", Id = "" } }; (Config as ProcessConfig).CameraConfigCollection.ForEach(c => { cameras.Add(new { Desc = c.Name, Id = c.Id }); }); UIHelper.SetCombo(cboCameras, cameras, "Desc", "Id"); cboCameras.SelectedIndex = 0; (Process as ProcessControl).OnBitmapOutput -= UpdateImage; (Process as ProcessControl).OnBitmapOutput += UpdateImage; } private static object _imgLock = new object(); private void UpdateImage(string cameraId, Bitmap image) { if (this.InvokeRequired) { this.Invoke(new Action(() => UpdateImage(cameraId, image))); } else { //lock (_imgLock) { try { if (string.IsNullOrWhiteSpace(cboCameras.SelectedValue?.ToString())) { canvasImage.LoadImage(image); } else { if (cboCameras.SelectedValue.ToString() == cameraId) { canvasImage.LoadImage(image); } } } catch (Exception) { } _imgShowedHandle.Set(); } } } #endregion #region advanced使用 private void btnNewConfig_Click(object sender, EventArgs e) { Config = new ProcessConfig(); propConfig.SelectedObject = Config; } private void btnLoadLocal_Click(object sender, EventArgs e) { if (Process == null) { MessageBox.Show("流程不能为空,请先载入流程"); return; } if ((Process as ProcessControl).ProcessState == DeviceState.DSOpen) { MessageBox.Show("流程执行中,请先停止流程"); return; } OpenFileDialog ofd = new OpenFileDialog(); ofd.Multiselect = false; ofd.Filter = "JSON配置文件|*.json"; if (ofd.ShowDialog() == DialogResult.OK) { Process = new ProcessControl(cboProductionCode.Text, ofd.FileName); MessageBox.Show("流程载入配置文件成功"); } } #region 配置修改备份 string _oldConfigStr = ""; /// /// 保存配置前检查 /// /// true: 可以继续保存配置 false:不再保存配置 private bool OpBeforeSaveConfig() { //if (string.IsNullOrWhiteSpace(_oldConfigStr)) // return true; string newConfigStr = JsonConvert.SerializeObject(propConfig.SelectedObject); if (newConfigStr == _oldConfigStr) { return true; } else { Process.SaveStationConfig(propConfig.SelectedObject as ProcessConfig); return true; } } #endregion private void btnAdvanced_Click(object sender, EventArgs e) { AdvancedPwdFrm pFrm = new AdvancedPwdFrm(); if (pFrm.ShowDialog() == DialogResult.OK) { plBasic.Visible = false; plAdvanced.Visible = true; } else { plBasic.Visible = true; plAdvanced.Visible = false; } } private void btnExitAdvanced_Click(object sender, EventArgs e) { plAdvanced.Visible = false; plBasic.Visible = true; } private void propConfig_SelectedObjectsChanged(object sender, EventArgs e) { if (propConfig.SelectedObject != null) { _oldConfigStr = JsonConvert.SerializeObject(propConfig.SelectedObject); } } #endregion #region 取像操作 float FrameRate { set { if (this.InvokeRequired) { this.Invoke(new Action(() => lblFrameRate.Text = value.ToString() + " ms")); } else { lblFrameRate.Text = value.ToString() + " ms"; } } } AutoResetEvent _imgShowedHandle = new AutoResetEvent(false); private void btnSnap_Click(object sender, EventArgs e) { if (string.IsNullOrWhiteSpace(cboCameras.SelectedValue.ToString())) { MessageBox.Show("请先选择操作相机"); return; } PubSubCenter.GetInstance().Publish(PubTag.DeviceOperation.ToString(), cboCameras.SelectedValue.ToString(), "Snap"); //string folderPath = ""; //FolderBrowserDialog fbd = new FolderBrowserDialog(); //if (fbd.ShowDialog() == DialogResult.OK) //{ // folderPath = fbd.SelectedPath; //} //else //{ // return; //} //Task.Run(() => //{ // DirectoryInfo dir = new DirectoryInfo(folderPath); // dir.GetFiles("*.jpg").Select(u => u.FullName).ToList().ForEach(f => // { // //Task.Run(() => // //{ // UpdateImage("", (Bitmap)Image.FromFile(f)); // //}); // //Task.Run(() => // //{ // List list = new List(); // Random r = new Random((int)DateTime.Now.Ticks); // for (int i = 0; i < 10; i++) // { // list.Add(new PointIndicator(r.Next(2448), r.Next(2048))); // } // UpdateVisionResult("", list); // //}); // //Thread.Sleep(10); // }); //}); } private void chkContinueMode_CheckedChanged(object sender, EventArgs e) { if (!chkContinueMode.Checked) { cboCameras.Enabled = true; lblFrameRate.Text = ""; return; } if (string.IsNullOrWhiteSpace(cboCameras.SelectedValue.ToString())) { MessageBox.Show("请先选择操作相机"); return; } cboCameras.Enabled = false; string cameraId = cboCameras.SelectedValue.ToString(); Task.Run(() => { Stopwatch sw = new Stopwatch(); sw.Start(); while (chkContinueMode.Checked) { try { sw.Stop(); FrameRate = sw.ElapsedMilliseconds; sw.Restart(); PubSubCenter.GetInstance().Publish(PubTag.DeviceOperation.ToString(), cameraId, "Snap", false); _imgShowedHandle.WaitOne(3000); } catch (Exception) { } } }); } private void chkHardwareTrigger_CheckedChanged(object sender, EventArgs e) { //if (cboCameras.SelectedIndex > 0) //{ // var cameraConfig = ProcessConfig.CameraConfigs.FirstOrDefault(u => u.ID == cboCameras.SelectedValue.ToString()); // if (cameraConfig != null) // { // cameraConfig.IsHardwareTrigger = chkHardwareTrigger.Checked; // } //} } private void cboCameras_SelectedIndexChanged(object sender, EventArgs e) { if (cboCameras.SelectedIndex > 0) { var cameraConfig = ProcessConfig.CameraConfigCollection.FirstOrDefault(u => u.Id == cboCameras.SelectedValue.ToString()); if (cameraConfig == null) { MessageBox.Show("未能获取正确的相机配置"); return; } //else //{ // chkHardwareTrigger.Checked = cameraConfig.IsHardwareTrigger; //} } } #endregion #region 服务 //CtrlServicePanel _servicePanel = new CtrlServicePanel(); //private void InitialService(int port) //{ // _servicePanel.Port = port; // _servicePanel.OnLogBroadcast = OnServiceLogBroadcast; // _servicePanel.OnBitmapBroadcast = OnServiceImageBroadcast; //} //private void OnServiceImageBroadcast(string cameraId, string imagePath) //{ // UpdateImage(cameraId, new Bitmap(imagePath)); //} //private void OnServiceLogBroadcast(DateTime dt, string prefix, string msg) //{ // RecordMsg(dt, prefix, msg); //} //private void OnServiceStateChanged(bool isServiceRunning) //{ // if (this.InvokeRequired) // { // this.Invoke(new Action(() => // { // btnStartProcess.Enabled = btnStopProcess.Enabled = !isServiceRunning; // })); // } // else // { // btnStartProcess.Enabled = btnStopProcess.Enabled = !isServiceRunning; // } //} #endregion private void tabControl1_SelectedIndexChanged(object sender, EventArgs e) { if (tabControl1.SelectedTab.Name != "tbLog") { chkContinueMode.Checked = false; } } private void button1_Click(object sender, EventArgs e) { //(Process as ProcessControl).Robot_Monitor_FullTrayFull(new OperationConfigBase() { InputPara = new List() { 1 } }, new HikCameraDriver { Id = "3680EBF8-D9F8-4E14-8B0D-6E53BE3BB96D" }); //var list = (Process.StationConfig as ProcessConfig).StorageCells; //list.Clear(); //for (int i = 0; i < 20000; i++) //{ // list.Add(new Bro.Common.RMQBus.CellInfo() { CellCode = Guid.NewGuid().ToString() }); //} MessageBox.Show("Done"); } } }