/// <summary> /// 메모리 어드레스 변수이름을 생성한다. /// </summary> /// <param name="dataType">데이터타입</param> /// <param name="memType">메모리타입</param> /// <param name="pAddress">주소번지</param> /// <returns></returns> private string CreateValueName(XGT_DataType dataType, XGT_MemoryType memType, string pAddress) { string vReturn = string.Empty; string vMemTypeChar = this.GetMemTypeChar(memType); //메모리타입 string vDataTypeChar = this.GetTypeChar(dataType); //데이터타입 if (dataType == XGT_DataType.Continue) { //연속읽기의 경우는 바이트 단위로만 표현 할 수 있으므로, Word 단위의 메모리를 읽으려면 주소값 * 2 를 해야함. //2Byte = 1Word pAddress = (Convert.ToInt32(pAddress) * 2).ToString(); } if (dataType == XGT_DataType.Bit) { /* * 변수이름 표현 방법에 있어서 비트 영역을 접근하고자 할 때에는 메모리 디바이스의 데이터 * 타입 단위의 순서로 표현하여야 합니다. M172의 C번째 비트를 쓰기 위하여서는 M이 * WORD디바이스 이므로 아래와 같이 비트 타입으로 산출해내는 과정이 필요합니다. * 잘못된 표현: %MX172C * 올바른 표현: 172 x 16(WORD) + 12(BIT) = 2764 * %MX2764 */ int vSEQ = 0; string vAddress = pAddress.Substring(0, pAddress.Length - 1); //입력받은 주소값의 마지막 자리 앞까지가 주소번지 string Last = pAddress.Substring(pAddress.Length - 1); // 입력받은 주소값의 마지막 자리는 비트 위치 vSEQ = Convert.ToInt32(Last, 16); pAddress = (Convert.ToInt32(vAddress) * 16 + vSEQ).ToString(); } return($"%{vMemTypeChar}{vDataTypeChar}{pAddress}"); }
/// <summary> /// 데이터 읽기 /// </summary> /// <param name="pDataType">연속읽기인 경우 (pDataCount)데이터 갯수를 꼭 입력해야함.</param> /// <param name="pAddress">메모리주소 번지</param> /// <param name="pMemtype">메모리 타입</param> /// <param name="pInvokeID"></param> /// <param name="pMsg">리턴 메세지</param> /// <param name="pDataCount">연속읽기일 경우 읽을 데이터 갯수, 개별 읽기면 기본값 0</param> /// <param name="pInputData">쓰기일 경우 입력데이터 받아옴.</param> /// <returns></returns> public XGTData Read(XGT_DataType pDataType, List <XgtAddressData> pAddress, XGT_MemoryType pMemtype, int pInvokeID, int pDataCount = 0) { XGTData vData = new XGTData(); if (pAddress.Count > 16) { vData.Message = "16개 이상 읽어올 수 없습니다."; } else { var buffer = new List <byte>(); try { byte[] data = CreateReadDataFormat(XGT_Request_Func.Read, pDataType, pAddress, pMemtype, pDataCount); byte[] header = CreateHeader(pInvokeID, data.Length); //전송할 프레임 byte[] tcpFrame = new byte[header.Length + data.Length]; //어플레케이션 헤더와 데이터 정보를 합쳐서 전송 Frame을 만든다. int idx = 0; AddByte(header, ref idx, ref tcpFrame); AddByte(data, ref idx, ref tcpFrame); vData.TX = tcpFrame; if (tcpSocket == null || !tcpSocket.Connected) { tcpSocket.Connect(_ip, _port); } tcpSocket.Send(tcpFrame, 0, tcpFrame.Length, SocketFlags.None); do { byte[] currByte = new byte[1]; int byteCounter = tcpSocket.Receive(currByte, 0, currByte.Length, SocketFlags.None); if (byteCounter.Equals(1)) { buffer.Add(currByte[0]); } } while (tcpSocket.Available > 0); vData.RX = buffer.ToArray(); vData.Message = "OK"; } catch (Exception ex) { vData.Message = "ERROR:" + ex.Message.ToString(); } finally { vData.MakeData(); } } return(vData); }
/// <summary> /// 메모리 타입에에 따른 Char 반환 /// </summary> /// <param name="type">메모리타입</param> /// <returns></returns> private string GetMemTypeChar(XGT_MemoryType type) { string vReturn = string.Empty; switch (type) { case XGT_MemoryType.IO: vReturn = XGT_Memory_TypeClass.IO; break; case XGT_MemoryType.SubRelay: vReturn = XGT_Memory_TypeClass.SubRelay; break; case XGT_MemoryType.LinkRelay: vReturn = XGT_Memory_TypeClass.LinkRelay; break; case XGT_MemoryType.KeepRelay: vReturn = XGT_Memory_TypeClass.KeepRelay; break; case XGT_MemoryType.EtcRelay: vReturn = XGT_Memory_TypeClass.EtcRelay; break; case XGT_MemoryType.Timer: vReturn = XGT_Memory_TypeClass.Timer; break; case XGT_MemoryType.DataRegister: vReturn = XGT_Memory_TypeClass.DataRegister; break; case XGT_MemoryType.Counter: vReturn = XGT_Memory_TypeClass.Counter; break; case XGT_MemoryType.ComDataRegister: vReturn = XGT_Memory_TypeClass.ComDataRegister; break; case XGT_MemoryType.FileDataRegister: vReturn = XGT_Memory_TypeClass.FileDataRegister; break; } return(vReturn); }
//어플리케이션 데이터 WRITE 포맷 만들기 private byte[] CreateWriteDataFormat (XGT_Request_Func emFunc, XGT_DataType emDatatype, List <XgtAddressData> pAddressList, XGT_MemoryType emMemtype, int pDataCount) { int vLenth = 0; //데이타 포맷 프레임의 크기 byte[] command = BitConverter.GetBytes((short)emFunc); //StringToByteArray((int)emFunc, true); //명령어 읽기,쓰기 byte[] dataType = BitConverter.GetBytes((short)emDatatype); //StringToByteArray((int)emDatatype, true); //데이터 타입 byte[] reserved = BitConverter.GetBytes((short)0); //예약영역 고정(0x0000) byte[] blockcount = BitConverter.GetBytes((short)pAddressList.Count); //블록수 //프레임 크기 설정 : 명령어(2) + 데이터타입(2) + 예약영역(2) + 블록수 (?) + 변수길이(?) + 변수(?) vLenth = command.Length + dataType.Length + reserved.Length + blockcount.Length; List <XgtAddressData> lstAddress = new List <XgtAddressData>(); foreach (XgtAddressData addr in pAddressList) { string vAddress = CreateValueName(emDatatype, emMemtype, addr.Address); addr.AddressString = vAddress; object oData = new object(); //입력받은 값이 숫자형인지 문자형이지 확실치 않아 Object 로 선언 int oDataLength = 0; //입력받은 값의 바이트 배열의 크기. //데이터 쓰기일 경우 입력 데이터의 크기를 구한다. int nInput = 0; //입력받은 데이터가 숫자형일경우 받을 변수 string strInput = string.Empty; //입력받은 데이터가 문자형일 경우 받을 변수. if (!int.TryParse(addr.Data, out nInput)) { //문자형일 경우 strInput = addr.Data; oData = Encoding.ASCII.GetBytes(strInput); } else { //숫자형일 경우 oData = BitConverter.GetBytes((short)nInput); } if (emDatatype == XGT_DataType.Bit) { addr.DataByteArray = new byte[1]; addr.DataByteArray[0] = ((byte[])oData)[0]; } else { addr.DataByteArray = (byte[])oData; } //입력값의 바이트 배열의 크기 oDataLength = ((byte[])oData).Length; vLenth += addr.AddressByteArray.Length + addr.LengthByteArray.Length + 2 + oDataLength; //데이터 갯수 + 데이터 길이 lstAddress.Add(addr); } if (XGT_DataType.Continue == emDatatype) { vLenth += 2; //연속읽기 인 경우 2바이트 추가.(데이터 갯수) } byte[] data = new byte[vLenth]; int idx = 0; AddByte(command, ref idx, ref data); AddByte(dataType, ref idx, ref data); AddByte(reserved, ref idx, ref data); AddByte(blockcount, ref idx, ref data); foreach (XgtAddressData addr in lstAddress) { AddByte(addr.LengthByteArray, ref idx, ref data); AddByte(addr.AddressByteArray, ref idx, ref data); } foreach (XgtAddressData addr in lstAddress) { //데이터 쓰기일 경우 byte[] count = BitConverter.GetBytes((short)addr.DataByteArray.Length); AddByte(count, ref idx, ref data); AddByte(addr.DataByteArray, ref idx, ref data); } return(data); }
//어플리케이션 데이터 READ 포맷 만들기 private byte[] CreateReadDataFormat (XGT_Request_Func emFunc, XGT_DataType emDatatype, List <XgtAddressData> pAddressList, XGT_MemoryType emMemtype, int pDataCount) { List <XgtAddressData> lstAddress = new List <XgtAddressData>(); int vLenth = 0; //데이타 포맷 프레임의 크기 byte[] command = BitConverter.GetBytes((short)emFunc); //StringToByteArray((int)emFunc, true); //명령어 읽기,쓰기 byte[] dataType = BitConverter.GetBytes((short)emDatatype); //StringToByteArray((int)emDatatype, true); //데이터 타입 byte[] reserved = BitConverter.GetBytes((short)0); //예약영역 고정(0x0000) byte[] blockcount = BitConverter.GetBytes((short)pAddressList.Count); //블록수 //프레임 크기 설정 : 명령어(2) + 데이터타입(2) + 예약영역(2) + 블록수 (?) + 변수길이(?) + 변수(?) vLenth = command.Length + dataType.Length + reserved.Length + blockcount.Length; foreach (XgtAddressData addr in pAddressList) { string vAddress = CreateValueName(emDatatype, emMemtype, addr.Address); //byte[] value = Encoding.ASCII.GetBytes(vAddress); //byte[] valueLength = BitConverter.GetBytes((short)value.Length); XgtAddressData XgtAddr = new XgtAddressData(); XgtAddr.AddressString = vAddress; lstAddress.Add(XgtAddr); vLenth += XgtAddr.AddressByteArray.Length + XgtAddr.LengthByteArray.Length; } if (XGT_DataType.Continue == emDatatype && XGT_Request_Func.Read == emFunc) { vLenth += 2; //연속읽기 인 경우 2바이트 추가.(데이터 갯수) } byte[] data = new byte[vLenth]; int idx = 0; AddByte(command, ref idx, ref data); AddByte(dataType, ref idx, ref data); AddByte(reserved, ref idx, ref data); AddByte(blockcount, ref idx, ref data); foreach (XgtAddressData addr in lstAddress) { AddByte(addr.LengthByteArray, ref idx, ref data); AddByte(addr.AddressByteArray, ref idx, ref data); } /* 연속 읽기의 경우 읽을 갯수 지정. */ if (XGT_DataType.Continue == emDatatype) { //데이터 타입이 연속 읽기 인 경우. byte[] vDataCount = BitConverter.GetBytes((short)pDataCount); AddByte(vDataCount, ref idx, ref data); } return(data); }