using Aitex.Core.Common.DeviceData; using Aitex.Core.RT.DataCenter; using Aitex.Core.RT.Device; using Aitex.Core.RT.Log; using Aitex.Core.RT.OperationCenter; using Aitex.Core.RT.SCCore; using Aitex.Core.RT.Tolerance; using Aitex.Core.UI.Control; using Aitex.Core.Util; using CommunityToolkit.HighPerformance.Buffers; using MECF.Framework.Common.Communications; using MECF.Framework.Common.DataCenter; using MECF.Framework.Common.Device.Bases; using MECF.Framework.Common.Equipment; using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.ServiceModel.Channels; using Venus_Core; namespace Venus_RT.Devices { public class TruPlasmaRF : RfPowerBase { private readonly AsyncSerialPort _serial; private List buffer = new List(4096); private double _total; private double _fromLast; private bool _bRFPowerOn = false; private readonly DeviceTimer _timerQueryStatus = new DeviceTimer(); private readonly DeviceTimer _timerTotal = new DeviceTimer(); private readonly DeviceTimer _timerFromLast = new DeviceTimer(); private readonly DeviceTimer _timerRFTurnOn = new DeviceTimer(); private readonly RD_TRIG _rfOnTrigger = new RD_TRIG(); private readonly R_TRIG _ErrTrigger = new R_TRIG(); private readonly R_TRIG _trigPMNeeded = new R_TRIG(); private readonly RD_TRIG _trigOnOff = new RD_TRIG(); private ToleranceChecker _alarmChecker; private ToleranceChecker _warningChecker; private ToleranceChecker _checkerReflectPower; private readonly double _scPowerAlarmTime; private readonly double _scPowerAlarmRange; private readonly double _scPowerWarningTime; private readonly double _scPowerWarningRange; private readonly double _scReflectPowerAlarmTime; private readonly double _scReflectPowerAlarmRange; private StatsDataItemRFAndPump _statRFOnTime = new StatsDataItemRFAndPump(); public string LastPMTime { get { return _statRFOnTime != null ? _statRFOnTime.LastPMTime.ToString() : ""; } } public double DaysFromLastPM { get { return _statRFOnTime == null ? 0 : _statRFOnTime.fromLastPM; } set { if (_statRFOnTime != null) _statRFOnTime.fromLastPM = value; } } public double TotalDays { get { return _statRFOnTime != null ? _statRFOnTime.Total : 0; } set { if (_statRFOnTime != null) _statRFOnTime.Total = value; } } public double PMIntervalDays { get { return _statRFOnTime != null ? _statRFOnTime.PMInterval : 0; } } public bool IsPMNeeded { get { return DaysFromLastPM > PMIntervalDays; } } public bool EnableAlarm { get { return _statRFOnTime == null || _statRFOnTime.AlarmEnable; } } private readonly double _scPowerRange; public override float ScalePower => (float)_scPowerRange; public TruPlasmaRF(ModuleName mod, VenusDevice device) : base(mod.ToString(), device.ToString()) { this.Status = GeneratorStatus.Unknown; var portNum = SC.GetStringValue(device == VenusDevice.Rf ? $"{mod}.Rf.Port" : $"{mod}.BiasRf.Port"); _serial = new AsyncSerialPort(portNum, 9600, 8, System.IO.Ports.Parity.None, System.IO.Ports.StopBits.One, "/r", false); ResetRFStats(); _scPowerAlarmTime = SC.GetValue($"{Module}.{Name}.PowerAlarmTime"); _scPowerAlarmRange = SC.GetValue($"{Module}.{Name}.PowerAlarmRange"); _scPowerWarningTime = SC.GetValue($"{Module}.{Name}.PowerWarningTime"); _scPowerWarningRange = SC.GetValue($"{Module}.{Name}.PowerWarningRange"); _scReflectPowerAlarmTime = SC.GetValue($"{Module}.{Name}.ReflectPowerAlarmTime"); _scReflectPowerAlarmRange = SC.GetValue($"{Module}.{Name}.ReflectPowerAlarmRange"); _scPowerRange = SC.GetValue($"{Module}.{Name}.PowerRange"); _scEnableCalibration = SC.GetConfigItem($"{Module}.{Name}.EnableCalibration"); _scCalibrationTable = SC.GetConfigItem($"{Module}.{Name}.CalibrationTable"); _scRFPhysicalMaxPower = SC.GetConfigItem($"{Module}.{Name}.RFPhysicalMaxPower"); _scCurrentRFMaxPower = SC.GetConfigItem($"{Module}.{Name}.CurrentRFMaxPower"); } public override bool Initialize() { base.Initialize(); DATA.Subscribe($"{Module}.{Name}.DeviceData", () => DeviceData); if (_serial.Open()) { _serial.OnBinaryDataChanged += SerialPortDataReceived; _serial.OnErrorHappened += SerialPortErrorOccurred; ResetCommand(); getcontrol(); SetPulseMode(false); } else { LOG.Write(eEvent.ERR_RF, Module, "Tru 射频发生器串口无法打开"); return false; } return true; } public new AITRfData DeviceData => new AITRfData { Module = Module, DeviceName = Name, ScalePower = ScalePower, ForwardPower = ForwardPower, ReflectPower = ReflectPower, IsRfOn = IsPowerOn, PowerSetPoint = PowerSetPoint, }; private void SerialPortDataReceived(byte[] rawMessage) { try { buffer.AddRange(rawMessage); while (buffer.Count >= 18) //至少包含ACK帧头(1字节)、长度、校验位(17或12字节) { //2.1 查找数据头 if (buffer[0] == 0x06) //传输数据有帧头,用于判断 { //得到完整的数据,复制到ReceiveBytes中进行校验 byte[] ReceiveBytes = new byte[13]; byte[] ReadReceiveBytes = new byte[18]; buffer.CopyTo(0, ReceiveBytes, 0, 13); buffer.CopyTo(0, ReadReceiveBytes, 0, 18); if ((ReceiveBytes[12] == 0x55) && (ReceiveBytes[1] == 0xAA)) //校验,最后一个字节是校验位 { parsecmd(ReceiveBytes); buffer.RemoveRange(0, 13); } else if ((ReadReceiveBytes[17] == 0x55) && (ReceiveBytes[1] == 0xAA)) { parsecmd(ReadReceiveBytes); buffer.RemoveRange(0, 18); } else { buffer.Clear(); LOG.Write(eEvent.ERR_RF, Module, $"rf通讯错误"); } } else //帧头不正确时,记得清除 { //buffer.RemoveAt(0); } } } catch (Exception ex) { buffer.Clear(); LOG.WriteExeption(ex); } } public GeneratorStatus Status { get; set; } private float _forwardPower; public override float ForwardPower { get { return _forwardPower; } set { _forwardPower = CalibrationData(value, false); } } private bool GetBitValue(byte value, int bit) { return (value & (byte)Math.Pow(2, bit)) > 0 ? true : false; } public override bool ReConnect() { return _serial.ReConnect(); } public override bool IsPowerOn { get => Status == GeneratorStatus.ON; set { } } public void parsecmd(byte[] message) { try { IsPowerOn = GetBitValue(message[4], 4); if (GetBitValue(message[4], 4)) { //LOG.Write(eEvent.INFO_RF,Module,"RF Status:ON"); Status = GeneratorStatus.ON; } else { //LOG.Write(eEvent.INFO_RF, Module, "RF Status:OFF"); Status = GeneratorStatus.OFF; } switch (message[5]) { case 0x01://ParamRead if (message.Length == 18 && message[6] == 0x14) { int DataValue = BitConverter.ToInt32(new byte[] { message[11], message[12], message[13], message[14] }, 0); ReflectPower = DataValue; } else if (message.Length == 18 && message[6] == 0x12) { int DataValue1 = BitConverter.ToInt32(new byte[] { message[11], message[12], message[13], message[14] }, 0); ForwardPower = DataValue1; } break; case 0x02://ParamWrite break; case 0xFE://TelegramError LOG.Write(eEvent.ERR_RF, Module, "Telegram structure is not correct"); break; default: // 默认代码块 break; } switch (message[9]) { case 0x26: //LOG.Write(eEvent.INFO_RF, Module, "RF Status:OFF"); Status = GeneratorStatus.OFF; IsPowerOn = false; break; case 0x24: LOG.Write(eEvent.ERR_RF, Module, "Telegram structure is not correct"); break; default: // 默认代码块 break; } } catch (Exception ex) { LOG.WriteExeption(ex); } } private void SerialPortErrorOccurred(string obj) { LOG.Write(eEvent.ERR_RF, Module, $"Tru 射频串口出错, [{obj}]"); } public override void SetPower(float val) { List baseBytes = new List() { 0xAA, 0x02, 0x0B, 0x00, 0x02, 0x06, 0x00, 0x01, 0x00, 0x04 }; val = !_scEnableCalibration.BoolValue ? (ushort)val : (ushort)CalibrationData(val, true); byte[] valueBytes = BitConverter.GetBytes((int)val); baseBytes.AddRange(valueBytes); baseBytes = CRC16(baseBytes.ToArray()); baseBytes.Add(0x55); _serial.Write(baseBytes.ToArray()); } public override void Monitor() { readpi(); readpr(); _rfOnTrigger.CLK = IsPowerOn; if (_rfOnTrigger.R) { _total = TotalDays; _fromLast = DaysFromLastPM; _timerTotal.Start(0); _timerFromLast.Start(0); _timerTotal.Restart(0); _timerFromLast.Restart(0); _alarmChecker.Reset(_scPowerAlarmTime); _warningChecker.Reset(_scPowerWarningTime); _checkerReflectPower.Reset(_scReflectPowerAlarmTime); } if (_rfOnTrigger.M) { TotalDays = _timerTotal.GetElapseTime() / 1000 / 60 / 60; DaysFromLastPM = _timerFromLast.GetElapseTime() / 1000 / 60 / 60; } if (PMIntervalDays > 0) { _trigPMNeeded.CLK = IsPMNeeded; if (_trigPMNeeded.Q) { if (EnableAlarm) { LOG.Write(eEvent.ERR_RF, $"{Module}", "rf on time value larger than setting interval days"); } } } if (_rfOnTrigger.T) { _timerTotal.Stop(); _timerFromLast.Stop(); StatsDataManager.Instance.Increase($"{Module}.{Name}OnTime", $"{Module}{Name}RfOnTime", DaysFromLastPM, TotalDays); } if (!_rfOnTrigger.CLK) { ForwardPower = 0; ReflectPower = 0; } // RF Turn On & Off Timeout Check _trigOnOff.CLK = _bRFPowerOn; if (_trigOnOff.R) //RF Turn On { _timerRFTurnOn.Start(SC.GetValue($"{Module}.{Name}.RFTurnOnTimeout") * 1000); } if (_trigOnOff.M) //RF Stay On { if (_timerRFTurnOn.IsTimeout()) { if (!IsPowerOn) { LOG.Write(eEvent.ERR_RF, $"{Module}", $"{Name} Turn On Failed"); _timerRFTurnOn.Stop(); } } } if (_trigOnOff.T) { _timerRFTurnOn.Stop(); } base.Monitor(); } public override void ResetRFStats() { _statRFOnTime = StatsDataManager.Instance.GetItemRFAndPump($"{Module}.{Name}OnTime"); } public void getcontrol() { byte[] getincontrol = new byte[] { 0xAA, 0x02, 0x06, 0x00, 0x05, 0x01, 0x00, 0x00, 0xFF, 0x34, 0x8A, 0x55 }; _serial.Write(getincontrol.ToArray()); } public void releasecontrol() { byte[] getincontrol = new byte[] { 0xAA, 0x02, 0x06, 0x00, 0x05, 0x02, 0x00, 0x00, 0xFF, 0xE8, 0x11, 0x55 }; _serial.Write(getincontrol.ToArray()); } public void readpr()//reflect { byte[] getincontrol = new byte[] { 0xAA, 0x02, 0x06, 0x00, 0x01, 0x14, 0x00, 0x01, 0xFF, 0xE1, 0x97, 0x55 }; _serial.Write(getincontrol.ToArray()); } public void readpi()//forward { byte[] getincontrola = new byte[] { 0xAA, 0x02, 0x06, 0x00, 0x01, 0x12, 0x00, 0x01, 0xFF, 0x78, 0xB0, 0x55 }; _serial.Write(getincontrola.ToArray()); } public void ResetCommand() { LOG.Write(eEvent.ERR_RF, Module, $"Send rest"); byte[] getincontrol = new byte[] { 0xAA, 0x02, 0x0B, 0x00, 0x02, 0x4D, 0x00, 0x01, 0x00, 0x04, 0x01, 0x00, 0x00, 0x00, 0x30, 0x72, 0x55 }; _serial.Write(getincontrol.ToArray()); } public override void Reset() { byte[] getincontrol = new byte[] { 0xAA, 0x02, 0x0B, 0x00, 0x02, 0x4D, 0x00, 0x01, 0x00, 0x04, 0x01, 0x00, 0x00, 0x00, 0x30, 0x72, 0x55 }; _serial.Write(getincontrol.ToArray()); } public override bool SetPowerOnOff(bool on, out string str) { str = ""; var _chamber = DEVICE.GetDevice(Module); if (on && !_chamber.CheckGeneratorAndHVInterlock(VenusDevice.Rf)) { return false; } getcontrol(); List baseBytes = new List() { 0xAA, 0x02, 0x0B, 0x00, 0x02, 0x6F, 0x00, 0x01, 0x00, 0x07 }; if (on == true) { _bRFPowerOn = true; baseBytes.AddRange(new List { 0x01, 0x00, 0x00, 0x00 }); } else { _bRFPowerOn = false; baseBytes.AddRange(new List { 0x00, 0x00, 0x00, 0x00 }); } baseBytes = CRC16(baseBytes.ToArray()); baseBytes.Add(0x55); _serial.Write(baseBytes.ToArray()); if (on == false) { releasecontrol(); } return true; } public override void SetPulseMode(bool on) { List baseBytes = new List() { 0xAA, 0x02, 0x0B, 0x00, 0x02, 0x6A, 0x01, 0x01, 0x00, 0x04 }; if (on == true) { baseBytes.AddRange(new List { 0x01, 0x00, 0x00, 0x00 }); } else { baseBytes.AddRange(new List { 0x00, 0x00, 0x00, 0x00 }); } baseBytes = CRC16(baseBytes.ToArray()); baseBytes.Add(0x55); _serial.Write(baseBytes.ToArray()); } public override void SetPulseRateFreq(int nFreq) { if (nFreq > 0) { List baseBytes = new List() { 0xAA, 0x02, 0x0B, 0x00, 0x02, 0x6C, 0x01, 0x01, 0x00, 0x04 }; byte[] valueBytes = BitConverter.GetBytes(nFreq); baseBytes.AddRange(valueBytes); baseBytes = CRC16(baseBytes.ToArray()); baseBytes.Add(0x55); _serial.Write(baseBytes.ToArray()); } else { LOG.Write(eEvent.ERR_RF, Module, $"{Name},SetPulseRateFreq() parameter error: {nFreq}"); } } public override void SetPulseDutyCycle(int percentage) { if (percentage >= 10 && percentage <= 90) { List baseBytes = new List() { 0xAA, 0x02, 0x0B, 0x00, 0x02, 0x6D, 0x01, 0x01, 0x00, 0x04 }; byte[] valueBytes = BitConverter.GetBytes(percentage); baseBytes.AddRange(valueBytes); baseBytes = CRC16(baseBytes.ToArray()); baseBytes.Add(0x55); _serial.Write(baseBytes.ToArray()); } else { LOG.Write(eEvent.ERR_RF, Module, $"{Name},SetPulseDutyCycle() parameter error: {percentage}"); } } #region 霍廷格RF协议crc-16/CCITT-FALSE校验 private bool CRC16(byte[] buffer, ref byte[] ResCRC16) // crc-16/CCITT-FALSE,判断校验 { bool status = false; ushort crc = 0xFFFF; int size = buffer.Length; //计算待计算的数据长度 int i = 0; if (size > 0) { while (size-- > 0) { crc = (ushort)((crc >> 8) | (crc << 8)); crc ^= buffer[i++]; crc ^= (ushort)(((byte)crc) >> 4); crc ^= (ushort)(crc << 12); crc ^= (ushort)((crc & 0xff) << 5); } } //判断输入的ResCRC16与计算出来的是否一致 if (ResCRC16[0] == (byte)((crc >> 8) & 0xff) && ResCRC16[1] == (byte)(crc & 0xff)) { status = true; } return status; } private List CRC16(byte[] buffer) // crc-16/CCITT-FALSE,补全两个字节 { ushort crc = 0xFFFF; int size = buffer.Length; //计算待计算的数据长度 int i = 0; if (size > 0) { while (size-- > 0) { crc = (ushort)((crc >> 8) | (crc << 8)); crc ^= buffer[i++]; crc ^= (ushort)(((byte)crc) >> 4); crc ^= (ushort)(crc << 12); crc ^= (ushort)((crc & 0xff) << 5); } } var byteList = buffer.ToList(); byteList.Add((byte)(crc & 0xff)); byteList.Add((byte)((crc >> 8) & 0xff)); return byteList; } #endregion } class TruPlasmaMatch : RfMatchBase { private readonly AsyncSerialPort _serial; private const ushort S3_HEAD_LENGTH = 2; private readonly DeviceTimer _timerQueryStatus = new DeviceTimer(); private int QUERY_INTERVAL = 1000; private List buffer = new List(4096); [Subscription("MatchWorkMode")] public EnumRfMatchTuneMode WorkMode { get; set; } public float C1 { get; set; } public float C2 { get; set; } public float _C1setpoint { get; set; } public float _C2setpoint { get; set; } //[Subscription("VPP")] public ushort VPP { get; set; } public float VDC { get; set; } public new AITMatchData DeviceData { get { return new AITMatchData { Module = Module, DeviceName = Name, WorkMode = WorkMode.ToString(), C1 = TunePosition1, C2 = TunePosition2, VPP = "", DCBias = DCBias.ToString(), C1SetPoint= _C1setpoint, C2SetPoint = _C2setpoint, }; } } public TruPlasmaMatch(ModuleName mod, VenusDevice device) : base(mod.ToString(), device.ToString()) { var portNum = SC.GetStringValue($"{mod}.{device}.Port"); _serial = new AsyncSerialPort(portNum, 9600, 8, System.IO.Ports.Parity.None, System.IO.Ports.StopBits.One, "/r", false); intervalTime = 100; } ~TruPlasmaMatch() { _serial?.Close(); } public override bool Initialize() { base.Initialize(); preset(50,50); DATA.Subscribe($"{Module}.{Name}.DeviceData", () => DeviceData); if (_serial.Open()) { _serial.OnBinaryDataChanged += SerialBinaryPortDataReceived; _serial.OnErrorHappened += SerialPortErrorOccurred; } else { LOG.Write(eEvent.ERR_RF, Module, "Match 串口无法打开"); return false; } DATA.Subscribe($"{Module}.{Name}.C1", () => TunePosition1); DATA.Subscribe($"{Module}.{Name}.C2", () => TunePosition2); DATA.Subscribe($"{Module}.{Name}.VDC", () => VDC); DATA.Subscribe($"{Module}.{Name}.WorkMode", () => WorkMode.ToString()); OP.Subscribe($"{Module}.{Name}.SetC1", (func, args) => { return true; }); OP.Subscribe($"{Module}.{Name}.SetC2", (func, args) => { return true; }); OP.Subscribe($"{Module}.{Name}.{AITRfOperation.SetMatchPositionC1}", (out string reason, int time, object[] param) => { SetMatchPositionC1((float)Convert.ToDouble(param[0]), out reason); return true; }); OP.Subscribe($"{Module}.{Name}.{AITRfOperation.SetMatchPositionC2}", (out string reason, int time, object[] param) => { SetMatchPositionC2((float)Convert.ToDouble(param[0]), out reason); return true; }); OP.Subscribe($"{Module}.{Name}.{AITRfOperation.SetMatchPosition}", (out string reason, int time, object[] param) => { SetMatchPosition((float)Convert.ToDouble(param[0]), (float)Convert.ToDouble(param[1]), out reason); return true; }); OP.Subscribe($"{Module}.{Name}.{AITRfOperation.SetMatchProcessMode}", (out string reason, int time, object[] param) => { SetMatchMode((string)param[0] == "Auto" ? EnumRfMatchTuneMode.Auto : EnumRfMatchTuneMode.Manual, out reason); return true; }); return true; } public void readc1() { byte[] readc1 = new byte[] { 0x0C, 0xF3, 0x00, 0x02, 0x00, 0x01, 0x61, 0x42, 0x79, 0x18, 0x01, 0x37 }; _serial.Write(readc1.ToArray()); } public void readc2() { byte[] readc1 = new byte[] { 0x0C, 0xF3, 0x00, 0x02, 0x00, 0x01, 0x61, 0x42, 0x79, 0x19, 0x01, 0x38 }; _serial.Write(readc1.ToArray()); } public void readVDC() { byte[] readvdc = new byte[] { 0x0C, 0xF3, 0x00, 0x02, 0x00, 0x00, 0x61, 0x42, 0x79, 0x1E, 0x01, 0x3C }; _serial.Write(readvdc.ToArray()); } public override void Monitor() { //ReadPosition(50,50);//0x10 (present mode)CMD 可实现任意模式下只读不设值,0x08(auto then manual)在auto模式下可实现相同功能 readc1(); readc2(); //readVDC(); } public override void Terminate() { } public override void Reset() { preset(50, 50); } /// /// /// /// 百分比数字 /// /// private void executeMatchPostion(float c1, float c2) { SetPositionManualAuto(c1, c2); } public override void SetMatchPosition(float c1, float c2, out string reason) { //preset(c1, c2); executeMatchPostion(c1, c2); reason = ""; } public void SetPresetMode(RfMatchPresetMode mode) { } // -----------------------Private Method------------------------- // private void SerialBinaryPortDataReceived(byte[] message) { if (message.Count() < 18) { string hexString = BitConverter.ToString(message.ToArray()).Replace("-", " "); //LOG.Write(eEvent.ERR_MATCH, Module, hexString); //LOG.Write(eEvent.ERR_RF, Module, "收到 Match 数据格式不正确"); } else { try { buffer.AddRange(message); while (buffer.Count >= 18) //至少包含帧头(1字节)、长度(1字节)、其余27字节 { //2.1 查找数据头 if (buffer[0] == 0x1D && buffer[1] == 0xE2) //传输数据有帧头,用于判断 { //得到完整的数据,复制到ReceiveBytes中进行校验 byte[] ReceiveBytes = new byte[29]; buffer.CopyTo(0, ReceiveBytes, 0, 29); TunePosition1 = BitConverter.ToSingle(new byte[] { ReceiveBytes[10], ReceiveBytes[11], ReceiveBytes[12], ReceiveBytes[13] }, 0) * 100; TunePosition2 = BitConverter.ToSingle(new byte[] { ReceiveBytes[14], ReceiveBytes[15], ReceiveBytes[16], ReceiveBytes[17] }, 0) * 100; buffer.RemoveRange(0, 29); switch (ReceiveBytes[19]) { case 0x01: this.WorkMode = EnumRfMatchTuneMode.Manual; break; case 0x02: this.WorkMode = EnumRfMatchTuneMode.Auto; break; case 0x20: this.WorkMode = EnumRfMatchTuneMode.Undefined; break; default: break; } } else if (buffer[0] == 0x12 && buffer[1] == 0xED) { byte[] ReceiveBytes18 = new byte[18]; buffer.CopyTo(0, ReceiveBytes18, 0, 18); if (ReceiveBytes18[10] == 0x79 && ReceiveBytes18[11] == 0x18) { TunePosition1 = BitConverter.ToSingle(new byte[] { ReceiveBytes18[12], ReceiveBytes18[13], ReceiveBytes18[14], ReceiveBytes18[15] }, 0) * 100; } else if (ReceiveBytes18[10] == 0x79 && ReceiveBytes18[11] == 0x19) { TunePosition2 = BitConverter.ToSingle(new byte[] { ReceiveBytes18[12], ReceiveBytes18[13], ReceiveBytes18[14], ReceiveBytes18[15] }, 0) * 100; } else if (ReceiveBytes18[10] == 0x79 && ReceiveBytes18[11] == 0x1E) { VDC = BitConverter.ToSingle(new byte[] { ReceiveBytes18[12], ReceiveBytes18[13], ReceiveBytes18[14], ReceiveBytes18[15] }, 0); } buffer.RemoveRange(0, 18); } else //帧头不正确时,记得清除 { buffer.Clear(); //LOG.Write(eEvent.ERR_MATCH, Module, $"Match通讯错误"); } } } catch (Exception ex) { buffer.Clear(); LOG.WriteExeption(ex); } } } private void SerialPortErrorOccurred(string str) { LOG.Write(eEvent.ERR_RF, Module, $"TruPlasma Match error [{str}]"); } private void SetPositionManualAuto(float c1val, float c2val) { _C1setpoint = c1val; _C2setpoint = c2val; List Len = new List() { 0x16, 0xE9 }; List DstSrc = new List() { 0x00, 0x02, 0x00, 0x01 }; List Cmd = new List { 0x60, 0x40 }; byte[] val1Bytes = BitConverter.GetBytes(c1val / 100); byte[] val2Bytes = BitConverter.GetBytes(c2val / 100); List Act = new List() { 0x00 }; List Ctr123 = new List { 0x08, 0x00, 0x00 }; List baseBytes = new List() { }; baseBytes.AddRange(Len); baseBytes.AddRange(DstSrc); baseBytes.AddRange(Cmd); baseBytes.AddRange(val1Bytes); baseBytes.AddRange(val2Bytes); baseBytes.AddRange(Act); baseBytes.AddRange(Ctr123); int a = 0; for (int i = 2; i < baseBytes.Count; i++) { a += (Int16)baseBytes[i]; } byte[] ackture = new byte[2]; byte[] ackbyte = BitConverter.GetBytes(a); ackture[0] = ackbyte[1]; ackture[1] = ackbyte[0]; baseBytes.AddRange(ackture); _serial.Write(baseBytes.ToArray()); } private void preset(float c1val, float c2val) { _C1setpoint = c1val; _C2setpoint = c2val; List Len = new List() { 0x16, 0xE9 }; List DstSrc = new List() { 0x00, 0x02, 0x00, 0x01 }; List Cmd = new List { 0x60, 0x40 }; byte[] val1Bytes = BitConverter.GetBytes(c1val / 100); byte[] val2Bytes = BitConverter.GetBytes(c2val / 100); List Act = new List() { 0x00 }; List Ctr123 = new List { 0x04, 0x10, 0x80 }; List baseBytes = new List() { }; baseBytes.AddRange(Len); baseBytes.AddRange(DstSrc); baseBytes.AddRange(Cmd); baseBytes.AddRange(val1Bytes); baseBytes.AddRange(val2Bytes); baseBytes.AddRange(Act); baseBytes.AddRange(Ctr123); int a = 0; for (int i = 2; i < baseBytes.Count; i++) { a += (Int16)baseBytes[i]; } byte[] ackture = new byte[2]; byte[] ackbyte = BitConverter.GetBytes(a); ackture[0] = ackbyte[1]; ackture[1] = ackbyte[0]; baseBytes.AddRange(ackture); _serial.Write(baseBytes.ToArray()); } public override bool SetMatchMode(EnumRfMatchTuneMode enumRfMatchTuneMode, out string reason) { reason = string.Empty; return true; } public override bool ReConnect() { return _serial.ReConnect(); } private void SetWorkMode(EnumRfMatchTuneMode mode) { } private void SetPresetMemory(byte gear) { } } }