using MV485.Dlg; using MV485.helper; using MV485.model; using MV485.util; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; using Path = System.IO.Path; namespace MV485.uc { /// /// UCDeviceConfig.xaml 的交互逻辑 /// public partial class UCDeviceConfig : UserControl { private static readonly string LogFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Documents", "config_log.txt"); private RWBasicConfig _rwBaseConfig = null; private List _logEntries = new List(); private BasicConfig _readConfig; public UCDeviceConfig() { InitializeComponent(); InitLoad(); LoadConfigLog(); } //初始化加载 private void LoadSerialPorts() { Dispatcher.BeginInvoke(new Action(() => { cmbPortNames.ItemsSource = SerialHelper.GetSerialPortsWithDetails(); if (cmbPortNames.Items.Count > 0) cmbPortNames.SelectedIndex = 0; var portName = ConfigManager.Instance.GetConfigValue(ConfigKey.ConfigPortName, ""); cmbPortNames.SelectedValue = portName; })); } private void InitLoad() { //与设备通信的参数 cmbBaudrate.ItemsSource = SerialHelper.BaudRates; var baudrates = ConfigManager.Instance.GetConfigValue(ConfigKey.ConfigBaudrate, "9600"); cmbBaudrate.SelectedValue = baudrates; cmbDevId.ItemsSource = Enumerable.Range(1, 247).ToList(); var devId = ConfigManager.Instance.GetConfigValue(ConfigKey.ConfigDevId, "1"); cmbDevId.Text = devId; //从设备读取或要设置的参数 cmbDevBaudrate.ItemsSource = SerialHelper.BaudRates; cmbDevAddress.ItemsSource = Enumerable.Range(1, 247).ToList(); LoadSerialPorts(); InitConfiView(); } private void btnRefreshPorts_Click(object sender, RoutedEventArgs e) { LoadSerialPorts(); AppendLog("串口列表已刷新"); } private void CmbPortNames_SelectionChanged(object sender, SelectionChangedEventArgs e) { //var portName = cmbPortNames.SelectedValue.ToString(); //ConfigManager.Instance.UpdateConfig(ConfigKey.ConfigPortName, portName); } private async void BtnReadConfig_Click(object sender, RoutedEventArgs e) { //串口号 if(cmbPortNames.SelectedItem == null) { MessageBox.Show(Application.Current.MainWindow, "请选择串口", "提示", MessageBoxButton.OK, MessageBoxImage.Warning); return; } var portName = cmbPortNames.SelectedValue.ToString(); ConfigManager.Instance.UpdateConfig(ConfigKey.ConfigPortName, portName); //波特率 if(cmbBaudrate.SelectedItem == null) { MessageBox.Show(Application.Current.MainWindow, "请选择波特率", "提示", MessageBoxButton.OK, MessageBoxImage.Warning); return; } var sBaudrate = cmbBaudrate.SelectedValue.ToString(); ConfigManager.Instance.UpdateConfig(ConfigKey.ConfigBaudrate, sBaudrate); if(!byte.TryParse(cmbDevId.Text,out byte devid) || devid < 0 || devid > 247){ MessageBox.Show(Application.Current.MainWindow, "请输入正确的设备地址", "提示", MessageBoxButton.OK, MessageBoxImage.Warning); return; } ConfigManager.Instance.UpdateConfig(ConfigKey.ConfigDevId, devid.ToString()); //开始读取RS485设备的参数 _rwBaseConfig = new RWBasicConfig(); int baudrate = int.Parse(sBaudrate); //显示等待串口 string titleInfo = "正在读取设备的基本参数"; WaitWindow waitWindow = new WaitWindow(titleInfo) { Owner = Application.Current.MainWindow, WindowStartupLocation = WindowStartupLocation.CenterOwner }; waitWindow.Show(); InitConfiView(); try { _rwBaseConfig = new RWBasicConfig(); _rwBaseConfig.RWLog += _rwBaseConfig_RWLog; _rwBaseConfig.SerialConnected += _rwBaseConfig_SerialConnected; _rwBaseConfig.SerialStatusChanged += _rwBaseConfig_SerialStatusChanged; BasicConfig basicConfig = await Task.Run(() => _rwBaseConfig.ReadBasicConfig(portName, baudrate, devid)); _readConfig = basicConfig; //记录读取的配置 if (basicConfig != null) { LoadViewWithBasicConfig(basicConfig); cmbDevBaudrate.IsEnabled = true; cmbDevAddress.IsEnabled = true; txtResult.Text = "已成功读取设备参数"; txtResult.Foreground = Brushes.Green; AppendLog("已成功读取设备参数"); } else { txtResult.Text = "读取设备参数失败"; txtResult.Foreground = Brushes.Red; AppendLog("读取设备参数失败"); } } catch { } finally { waitWindow.Close(); } } //根据配置值加载页面 private void LoadViewWithBasicConfig(BasicConfig config) { InitConfiView(); txtDevType.Text = config.DeviceType; txtDevSn.Text = config.DeviceSn; txtFireware.Text = config.FireWare; txtParty.Text = config.ParityName; txtDataBits.Text = config.DataBitsName; txtStopBits.Text = config.StopbitsName; cmbDevBaudrate.SelectedValue = config.BaudRate.ToString(); cmbDevAddress.Text = config.DeviceAddress.ToString(); btnSetConifg.IsEnabled = true; //cmbDevBaudrate.IsEnabled = true; //cmbDevAddress.IsEnabled = true; } private void InitConfiView() { txtDevType.Text = ""; txtDevSn.Text = ""; txtFireware.Text = ""; txtParty.Text = ""; txtDataBits.Text = ""; txtStopBits.Text = ""; cmbDevBaudrate.SelectedItem = null; cmbDevAddress.Text = ""; cmbDevBaudrate.IsEnabled = false; cmbDevAddress.IsEnabled = false; txtResult.Text = ""; btnSetConifg.IsEnabled = false; } private void _rwBaseConfig_RWLog(string message) { AppendLog(message); } private void _rwBaseConfig_SerialConnected(bool obj) { //throw new NotImplementedException(); } private void _rwBaseConfig_SerialStatusChanged(bool obj) { //throw new NotImplementedException(); } private void TextBox_PreviewTextInput(object sender, TextCompositionEventArgs e) { if (e.Text.All(char.IsDigit)) { e.Handled = false; // 如果是数字,允许输入 } else { // 如果当前输入的字符不是数字,并且是中文输入法的拼音或候选字,禁止输入 e.Handled = true; } } private async void BtnSetConifg_Click(object sender, RoutedEventArgs e) { if (!LicenseMana.mIsLicensed) { MessageBox.Show(Application.Current.MainWindow, "软件未注册,不能使用此功能。", "提示", MessageBoxButton.OK, MessageBoxImage.Information); return; } //bool isRead = _rwBaseConfig?.IsRead ?? false; //if (!isRead) if(_readConfig == null) { MessageBox.Show(Application.Current.MainWindow, "请先读取参数", "提示", MessageBoxButton.OK, MessageBoxImage.Warning); return; } if(cmbDevBaudrate.SelectedItem == null) { MessageBox.Show(Application.Current.MainWindow, "请选择波特率", "提示", MessageBoxButton.OK, MessageBoxImage.Warning); return; } var sBaudrate = cmbBaudrate.SelectedValue.ToString(); if (!byte.TryParse(cmbDevAddress.Text, out byte devAddress) || devAddress < 0 || devAddress > 247) { MessageBox.Show(Application.Current.MainWindow, "请输入正确的设备地址", "提示", MessageBoxButton.OK, MessageBoxImage.Warning); return; } string sBaudRate = cmbDevBaudrate.SelectedValue.ToString(); int baudRate = int.Parse(sBaudRate); BasicConfig writeConfig = new BasicConfig() { BaudRate = baudRate, DeviceAddress = devAddress }; //判断是否有变化 if(_readConfig.BaudRate == writeConfig.BaudRate && _readConfig.DeviceAddress == writeConfig.DeviceAddress) { MessageBox.Show(Application.Current.MainWindow, "设置值与读取值无变化,设置无效", "提示", MessageBoxButton.OK, MessageBoxImage.Warning); return; } //显示等待串口 string titleInfo = "正在设置设备的基本参数"; WaitWindow waitWindow = new WaitWindow(titleInfo) { Owner = Application.Current.MainWindow, WindowStartupLocation = WindowStartupLocation.CenterOwner }; waitWindow.Show(); //InitConfiView(); //btnSetConifg.IsEnabled = false; try { bool blSuccess= await Task.Run(() => _rwBaseConfig.WriteBasicConfig(_readConfig,writeConfig)); //bool blSuccess = await _rwBaseConfig.WriteBasicConfig(_readConfig, writeConfig); if (blSuccess) { cmbDevBaudrate.IsEnabled = true; cmbDevAddress.IsEnabled = true; txtResult.Text = "已成功设置设备参数"; txtResult.Foreground = Brushes.Green; AppendLog("已成功设置设备参数"); //自动回填读参数列表 if (chkFillReadParams.IsChecked == true) { if(_readConfig.BaudRate != writeConfig.BaudRate) { cmbBaudrate.SelectedValue = writeConfig.BaudRate.ToString(); AppendLog($"回填波特率{_readConfig.BaudRate}->{writeConfig.BaudRate}"); } if(_readConfig.DeviceAddress != writeConfig.DeviceAddress) { cmbDevId.Text = writeConfig.DeviceAddress.ToString(); AppendLog($"回填设备地址{_readConfig.DeviceAddress}->{writeConfig.DeviceAddress}"); } _readConfig.BaudRate = writeConfig.BaudRate; _readConfig.DeviceAddress = writeConfig.DeviceAddress; btnSetConifg.IsEnabled = true; } else { cmbDevBaudrate.IsEnabled = false; cmbDevAddress.IsEnabled = false; btnSetConifg.IsEnabled = false; _readConfig = null; } } else { txtResult.Text = "设置设备参数失败"; txtResult.Foreground = Brushes.Red; AppendLog("设置设备参数失败"); btnSetConifg.IsEnabled = true; } } catch { } finally { waitWindow.Close(); } } private void btnClearLog_Click(object sender, RoutedEventArgs e) { _logEntries.Clear(); lvLogs.ItemsSource = null; File.WriteAllText(LogFilePath, ""); AppendLog("日志已清空"); } private void AppendLog(string message) { Dispatcher.Invoke(() => { var logEntry = new LogEntry { Time = DateTime.Now.ToString("HH:mm:ss.fff"), Message = message }; _logEntries.Add(logEntry); lvLogs.ItemsSource = null; lvLogs.ItemsSource = _logEntries; lvLogs.ScrollIntoView(logEntry); // 确保 Logs 目录存在 Directory.CreateDirectory(Path.GetDirectoryName(LogFilePath)); //File.AppendAllText("config_log.txt", $"{logEntry.Time} - {logEntry.Message}\n"); // 追加日志 File.AppendAllText(LogFilePath, $"{logEntry.Time} - {logEntry.Message}\n"); }); } //读取并加载日志 private void LoadConfigLog() { Dispatcher.BeginInvoke(new Action(() => { LoadLogs(); })); } private void LoadLogs() { if (!File.Exists(LogFilePath)) return; _logEntries.Clear(); // 先清空已有的日志记录 //var lines = File.ReadAllLines("config_log.txt"); var lines = File.ReadAllLines(LogFilePath); foreach (var line in lines) { var parts = line.Split(new[] { " - " }, 2, StringSplitOptions.None); if (parts.Length == 2) { _logEntries.Add(new LogEntry { Time = parts[0], Message = parts[1] }); } } // 更新 ListView lvLogs.ItemsSource = null; lvLogs.ItemsSource = _logEntries; // 滚动到最后一条 if (_logEntries.Count > 0) { lvLogs.ScrollIntoView(_logEntries[_logEntries.Count - 1]); } } private void UserControl_SizeChanged(object sender, SizeChangedEventArgs e) { double totalWidth = lvLogs.ActualWidth; double timeColumnWidth = 120; // 时间列固定宽度 double minMessageWidth = 200; // 消息列的最小宽度 double newMessageWidth = Math.Max(minMessageWidth, totalWidth - timeColumnWidth - 40); // 计算新宽度 ((GridView)lvLogs.View).Columns[1].Width = newMessageWidth; } private void MenuItem_CopyMessage_Click(object sender, RoutedEventArgs e) { if (lvLogs.SelectedItem is LogEntry logEntry) { if (!LicenseMana.mIsLicensed) { MessageBox.Show(Application.Current.MainWindow, "软件未注册,不能使用此功能。", "提示", MessageBoxButton.OK, MessageBoxImage.Information); return; } Clipboard.SetText(logEntry.Message); } } //----------------------------------------------------------------------------- } }