private void btnSaveBoardConfig_Click(object sender, RoutedEventArgs e)
        {
            if (!ValidInteger(tbBatteryRefVoltage, 1, 10000, "参考电压"))
            {
                return;
            }
            if (!ValidInteger(tbBatteryMinValue, 1, 10000, "最低电量读数"))
            {
                return;
            }
            if (!ValidInteger(tbBatteryMaxValue, 1, 10000, "最高电量读数"))
            {
                return;
            }
            if (!ValidInteger(tbBatteryCheckSec, 1, 255, "电量检测间距"))
            {
                return;
            }
            if (!ValidInteger(tbBatteryAlarmSec, 10, 255, "电量警报间距"))
            {
                return;
            }
            if (!ValidInteger(tbMaxServo, 1, 32, "舵机数目"))
            {
                return;
            }
            if (!ValidInteger(tbMp3Volume, 0, 30, "MP3音量"))
            {
                return;
            }
            if (!ValidInteger(tbTouchDetectPeriod, 1000, 5000, "触摸连击感应时间"))
            {
                return;
            }
            if (!ValidInteger(tbTouchReleasePeriod, 1000, 5000, "触摸感应间距"))
            {
                return;
            }
            if (!ValidInteger(tbMpuCheckFreq, 10, 100, "探测灵敏度"))
            {
                return;
            }
            if (!ValidInteger(tbMpuPositionCheckFreq, 20, 100, "姿态灵敏度"))
            {
                return;
            }

            if (!ValidInteger(tbPsxCheckMs, 10, 255, "PS2 按键侦测间距"))
            {
                return;
            }
            if (!ValidInteger(tbPsxNoEventMs, 10, 255, "PS2 按键無效间距"))
            {
                return;
            }
            if (!ValidInteger(tbPsxIgnoreRepeatMs, 50, 2000, "PS2 连按间距"))
            {
                return;
            }

            if (!ValidInteger(tbRouterTimeout, 10, 255, "等待时间"))
            {
                return;
            }
            if (!ValidInteger(tbServerPort, 0, 65535, "网路设定网页 连接埠"))
            {
                return;
            }
            if (!ValidInteger(tbUdpRxPort, 0, 65535, "群控 接收埠"))
            {
                return;
            }
            if (!ValidInteger(tbUdpTxPort, 0, 65535, "群控 发出埠"))
            {
                return;
            }

            try
            {
                UBT.config.batteryRefVoltage = (UInt16)int.Parse(tbBatteryRefVoltage.Text);
                UBT.config.batteryMinValue   = (UInt16)int.Parse(tbBatteryMinValue.Text);
                UBT.config.batteryMaxValue   = (UInt16)int.Parse(tbBatteryMaxValue.Text);
                UBT.config.batteryCheckSec   = byte.Parse(tbBatteryCheckSec.Text);
                UBT.config.batteryAlarmSec   = byte.Parse(tbBatteryAlarmSec.Text);

                UBT.config.maxServo        = byte.Parse(tbMaxServo.Text);
                UBT.config.maxDetectRetry  = byte.Parse(tbMaxDetectRetry.Text);
                UBT.config.commandTimeout  = byte.Parse(tbCommandTimeout.Text);
                UBT.config.maxCommandRetry = byte.Parse(tbMaxCommandRetry.Text);

                UBT.config.mp3Enabled = (cbxMp3Enabled.IsChecked == true);
                UBT.config.mp3Volume  = byte.Parse(tbMp3Volume.Text);
                UBT.config.mp3Startup = byte.Parse(tbMp3Startup.Text);

                UBT.config.enableOLED = (cbxEnableOLED.IsChecked == true);

                UBT.config.touchEnabled       = (cbxTouchEnabled.IsChecked == true);
                UBT.config.touchDetectPeriod  = (UInt16)int.Parse(tbTouchDetectPeriod.Text);
                UBT.config.touchReleasePeriod = (UInt16)int.Parse(tbTouchReleasePeriod.Text);

                UBT.config.mpuEnabled           = (cbxMpuEnabled.IsChecked == true);
                UBT.config.mpuCheckFreq         = byte.Parse(tbMpuCheckFreq.Text);
                UBT.config.mpuPositionCheckFreq = byte.Parse(tbMpuPositionCheckFreq.Text);

                UBT.config.psxEnabled        = (cbxPsxEnabled.IsChecked == true);
                UBT.config.psxCheckMs        = byte.Parse(tbPsxCheckMs.Text);
                UBT.config.psxNoEventMs      = byte.Parse(tbPsxNoEventMs.Text);
                UBT.config.psxIgnoreRepeatMs = (UInt16)int.Parse(tbPsxIgnoreRepeatMs.Text);
                UBT.config.psxShock          = (cbxPsxShock.IsChecked == true);

                UBT.networkConfig.enableRouter  = (cbxEnableRouter.IsChecked == true);
                UBT.networkConfig.ssid          = tbSSID.Text;
                UBT.networkConfig.password      = tbPassword.Text;
                UBT.networkConfig.routerTimeout = byte.Parse(tbRouterTimeout.Text);

                UBT.networkConfig.enableAP = (cbxEnableAP.IsChecked == true);
                UBT.networkConfig.apName   = tbAPName.Text;
                UBT.networkConfig.apKey    = tbAPKey.Text;

                UBT.networkConfig.enableServer = (cbxEnableServer.IsChecked == true);
                UBT.networkConfig.serverPort   = (UInt16)int.Parse(tbServerPort.Text);

                UBT.networkConfig.enableUDP = (cbxEnableUDP.IsChecked == true);
                UBT.networkConfig.udpRxPort = (UInt16)int.Parse(tbUdpRxPort.Text);
                UBT.networkConfig.udpTxPort = (UInt16)int.Parse(tbUdpTxPort.Text);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "输入资料错误", MessageBoxButton.OK, MessageBoxImage.Error);
                return;
            }
            if (UBT.SetConfig() && UBT.SetNetworkConfig())
            {
                MessageBox.Show("主控板设定已更新, 但部份设定必须在重启时才生效.\n为确保系统的稳定性, 请即重启机器人.",
                                "主控板设定更新成功", MessageBoxButton.OK, MessageBoxImage.Asterisk);
            }
            else
            {
                MessageBox.Show("主控板更新失败", "系统错误", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }