using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace AGVEmulator { class DevBMS : AR.Dev.RS232 { public class RequestBatteryDataArgs : EventArgs { public float Volt { get; set; } public float Remain { get; set; } public int CurA { get; set; } public int MaxA { get; set; } public UInt16 Temp1 { get; set; } public UInt16 Temp2 { get; set; } public RequestBatteryDataArgs() { this.Volt = 25; this.Remain = 79f; this.CurA = 40; this.MaxA = 80; Temp1 = 0; Temp2 = 0; } } public class RequestVoltageDataArgs : EventArgs { public UInt16[] cellVolt { get; set; } public RequestVoltageDataArgs() { cellVolt = new UInt16[] { 0, 0, 0, 0, 0, 0, 0, 0 }; } } public event EventHandler RequestBatteryData; public event EventHandler RequestVoltageData; public override bool ProcessRecvData(byte[] data) { //dd로 시작하고 34개의 데이터(명령이 0D로 끝나면 34이고, 77로 끝나면 34보다크다) var sample000D = "DD 03 00 1B 0A 65 00 00 21 63 29 04 00 00 2C 92 00 00 00 00 00 00 28 51 03 08 02 0B 69 0B 66 FC 9C 77"; var sampleFC77 = "DD 03 00 1B 0A 6E 0D DD 04 00 10 0D 0A 0D 09 0D 0C 0D 09 0D 0A 0D 09 0D 09 0D 0C FF 38 77 DD 04 00 10 0D 0A 0D 09 0D 0C 0D 09 0D 0A 0D 09 0D 09 0D 0C FF 38 77"; var sampleFD77 = "DD 03 00 1B 0A 6E 00 00 1F 4A 29 04 00 4E 2C D7 00 00 00 00 00 00 28 4C 03 08 02 0B 9F 0B A9 FB A7 77 DD 03 00 1B 0A 6E 00 00 1F 4A 29 04 00 4E 2C D7 00 00 00 00 00 00 28 4C 03 08 02 0B 9F 0B AA FB A6 77"; //basic var basicinfosmaple = "0A 65 00 00 21 63 29 04 00 00 2C 92 00 00 00 00 00 00 28 51 03 08 02 0B 69 0B 66"; var basic_payload = basicinfosmaple.Split(' ').ToList().Select(t => Convert.ToByte(t, 16)).ToArray(); //old var barr0D = sample000D.Split(' ').ToList().Select(t => Convert.ToByte(t, 16)).ToArray(); //old var barrFC77 = sampleFC77.Split(' ').ToList().Select(t => Convert.ToByte(t, 16)).ToArray(); //setting var barrFD77 = sampleFD77.Split(' ').ToList().Select(t => Convert.ToByte(t, 16)).ToArray(); //normal if (data.First() != 0xDD || data.Last() != 0x77) { RaiseMessage(MessageType.Error, $"stx,etx error data={data.HexString()}"); return false; } var sts = data[1]; var cmd = data[2]; RaiseMessage(MessageType.Normal, "Rx:" + data.HexString()); byte sendOld = 0; if (cmd == 0x03) //get basic info { if (RequestBatteryData != null) { var p = new RequestBatteryDataArgs(); RequestBatteryData.Invoke(this, p); //전압 var Volt = (UInt16)(p.Volt * 100); var arr_volt = BitConverter.GetBytes(Volt).Reverse().ToArray(); Array.Copy(arr_volt, 0, basic_payload, 0, arr_volt.Length); //잔량A var CurA = (UInt16)p.CurA; var arr_cura = BitConverter.GetBytes(CurA).Reverse().ToArray(); Array.Copy(arr_cura, 0, basic_payload, 4, arr_cura.Length); //최대A var MaxA = (UInt16)p.MaxA; var arr_maxa = BitConverter.GetBytes(MaxA).Reverse().ToArray(); Array.Copy(arr_maxa, 0, basic_payload, 6, arr_maxa.Length); //% var perc = (byte)(int)p.Remain; Array.Copy(new byte[] { perc }, 0, basic_payload, 19, 1); //temp1 var temp1 = BitConverter.GetBytes((UInt16)(p.Temp1 + 2731)).Reverse().ToArray(); Array.Copy(temp1, 0, basic_payload, 23,2); //temp2 var temp2 = BitConverter.GetBytes((UInt16)(p.Temp2 + 2731)).Reverse().ToArray(); Array.Copy(temp2, 0, basic_payload, 25, 2); var datalen = (byte)basic_payload.Length; var payload_cs = new List(); payload_cs.Add(datalen); payload_cs.AddRange(basic_payload); var chks = MakeCheckSum(payload_cs); var buffer = new List(); buffer.Add(0xdd); buffer.Add(cmd); buffer.Add(0x00); buffer.Add(datalen); buffer.AddRange(basic_payload); buffer.AddRange(chks); buffer.Add(0x77); ////makechecksum //UInt16 chksum = 0; //for (int i = 3; i <= 19; i++) //{ // chksum += barrFD77[i]; //} //chksum = (UInt16)(0xFFFF - chksum + 1); //Array.Copy(BitConverter.GetBytes(chksum).Reverse().ToArray(), 0, barrFD77, 20, 2); RaiseMessage(MessageType.Normal, $"Volt:{p.Volt}v,Remain:{p.Remain}%,temp1:{p.Temp1/10f},Temp2:{p.Temp2/10f}"); var sendstr = System.Text.Encoding.Default.GetString(barr0D); RaiseMessage(MessageType.Normal, "Tx:" + barr0D.HexString()); WriteData(buffer.ToArray()); } } else if (cmd == 0x04) //get cellvoltage { if (RequestVoltageData != null) { var p = new RequestVoltageDataArgs(); RequestVoltageData.Invoke(this, p); //var sig = data.Skip(data.Length - 2).Take(1).First(); //cellvolt 240201 var payload = new byte[8 * 2]; for (int i = 0; i < 8; i++) { var volt = p.cellVolt[i]; var arr_cellvolt = BitConverter.GetBytes(volt).Reverse().ToArray(); Array.Copy(arr_cellvolt, 0, payload, (i * 2), arr_cellvolt.Length); } //makechecksum var datalen = (byte)payload.Length; var payload_cs = new List(); payload_cs.Add(datalen); payload_cs.AddRange(payload); var chksum = MakeCheckSum(payload_cs); var buffer = new List(); buffer.Add(0xDD); buffer.Add(cmd); buffer.Add(0x00); buffer.Add(datalen); buffer.AddRange(payload); buffer.AddRange(chksum); buffer.Add(0x77); WriteData(buffer.ToArray()); RaiseMessage(MessageType.Normal, "Tx:" + buffer.ToArray().HexString()); } } return true; } public byte[] MakeCheckSum(IEnumerable payload) { UInt16 retval = 0; var payloadsum = payload.Sum(t => t); retval = (UInt16)(payloadsum); retval = (UInt16)(0xFFFF - retval); retval += 1; return BitConverter.GetBytes(retval).Reverse().ToArray(); } protected override bool CustomParser(byte[] buf, out byte[] remainBuffer) { //DD A5 03 00 FF FD 77 0D //remainBuffer = new byte[] { }; List remain = new List(); bool retval = false; foreach (var b in buf) { if (retval) { remain.Add(b); continue; } if (b == 0xDD) //stx { tempBuffer.Clear(); tempBuffer.Add(b); } else if (b == 0x0D || b == 0x77) //etx { //과거데이터 34개이다 (DD A5 03 00 FF FD 77 0D) //대쉬보드상태일때(DD A5 03 00 FF FD 77) //설정상태일때-셀전압표시(DD A5 04 00 FF FC 77) tempBuffer.Add(b); retval = true; } else { if (tempBuffer.Count > 0 && tempBuffer[0] == 0xDD) { tempBuffer.Add(b); if (tempBuffer.Count > 10) { RaiseMessage(MessageType.Error, "buffer over"); tempBuffer.Clear(); retval = false; } } else { //trash } } } remainBuffer = remain.ToArray(); return retval; } } }