using System; using System.Collections.Generic; using System.IO.Ports; using System.Linq; using System.Text; using System.Threading.Tasks; using Aurora.Api; using Aurora.Api.Devices; using Hermes; namespace AuroraChiller { public class DongShinChiller : DongShinChillerBase { public const string OP_GET = "01"; public const int OP_GET_COOLING_STATUS = 1; public const int OP_GET_TARGET_TEMP = 2; public const int OP_GET_LOW_TEMP1 = 3; public const int OP_GET_LOW_TEMP2 = 4; public const int OP_GET_HIGH_TEMP1 = 5; public const int OP_GET_HIGH_TEMP2 = 6; public const int OP_GET_CURRENT_TEMP = 7; public const int OP_GET_ERROR = 8; public const string OP_SET_COOLING_STATUS = "11"; public const string OP_SET_TARGET_TEMP = "12"; public const string OP_SET_LOW_TEMP1 = "13"; public const string OP_SET_LOW_TEMP2 = "14"; public const string OP_SET_HIGH_TEMP1 = "15"; public const string OP_SET_HIGH_TEMP2 = "16"; public const byte BYTE_STX = 0x02; // 02 public const byte BYTE_CR = 0x0D; // 13 public const byte BYTE_0 = 0x30; // 48 public const byte BYTE_1 = 0x31; // 49 public const byte BYTE_5 = 0x35; // 53 private Config _Config; public DongShinChiller(string deviceId) : base(deviceId) { } protected override int DoActivate(IDeviceConfig config) { _Config = config as Config; if (IsPortOpen()) { return E1.OK; } var result = Open(_Config.ConnConfig as SerialConnConfig); if (result == E1.OK) { return Init(); } return result; } private int Init() { // Set init vaues from config return E1.OK; } protected override int DoDeactivate() { return Close(); } #region Set public override bool SetCooling(bool bOn) { return SetValue(OP_SET_COOLING_STATUS, bOn); } public override bool SetTargetTemp(double temp) { return SetValue(OP_SET_TARGET_TEMP, temp); } public override bool SetLowTemp1(double temp) { return SetValue(OP_SET_LOW_TEMP1, temp); } public override bool SetLowTemp2(double temp) { return SetValue(OP_SET_LOW_TEMP2, temp); } public override bool SetHighTemp1(double temp) { return SetValue(OP_SET_HIGH_TEMP1, temp); } public override bool SetHighTemp2(double temp) { return SetValue(OP_SET_HIGH_TEMP2, temp); } private bool SetValue(string cmd, double value) { if (!IsPortOpen()) { return false; } lock (LockThis) { } byte[] opCode = Encoding.Default.GetBytes(cmd); if (opCode[0] != '1' || opCode[1] < '2' || '6' < opCode[1]) { return false; } // Data Format : ab.c var dataByte = Encoding.Default.GetBytes( string.Format("{0:00.0}", Math.Abs(value))); byte[] sendData = new byte[10]; sendData[0] = BYTE_STX; sendData[1] = opCode[0]; // ‘12’ ~ '16' sendData[2] = opCode[1]; sendData[3] = BYTE_5; //Data Length (1byte) sendData[4] = (value < 0) ? Convert.ToByte('-') : Convert.ToByte('+'); sendData[5] = dataByte[0]; // Data a sendData[6] = dataByte[1]; // Data b sendData[7] = dataByte[2]; // Data . sendData[8] = dataByte[3]; // Data c sendData[9] = BYTE_CR; return Write(sendData); } private bool SetValue(string cmd, bool value) { if (!IsPortOpen()) { return false; } lock (LockThis) { if (cmd != OP_SET_COOLING_STATUS) { return false; } byte[] sendData = new byte[6]; byte[] opCode = Encoding.Default.GetBytes(cmd); sendData[0] = BYTE_STX; sendData[1] = opCode[0]; //‘11’ sendData[2] = opCode[1]; sendData[3] = BYTE_1; //Data Length (1byte) sendData[4] = (value) ? BYTE_1 : BYTE_0; sendData[5] = BYTE_CR; return Write(sendData); } } #endregion #region Get public override int GetCoolingOnStatus() { return GetValueInt(OP_GET, OP_GET_COOLING_STATUS); } public override double GetTargetTemp() { return GetValueDouble(OP_GET, OP_GET_TARGET_TEMP); } public override double GetLowTemp1() { return GetValueDouble(OP_GET, OP_GET_LOW_TEMP1); } public override double GetLowTemp2() { return GetValueDouble(OP_GET, OP_GET_LOW_TEMP2); } public override double GetHighTemp1() { return GetValueDouble(OP_GET, OP_GET_HIGH_TEMP1); } public override double GetHighTemp2() { return GetValueDouble(OP_GET, OP_GET_HIGH_TEMP2); } public override double GetCurrentTemp() { return GetValueDouble(OP_GET, OP_GET_CURRENT_TEMP); } public override int GetError() { return GetValueInt(OP_GET, OP_GET_ERROR); } private int GetValueInt(string cmd, int code) { var strReceive = GetValueString(cmd, code); if (CheckNumberString(strReceive)) { return Convert.ToInt32(strReceive); } return E1.GENERIC; } private double GetValueDouble(string cmd, int code) { var strReceive = GetValueString(cmd, code); if (CheckNumberString(strReceive)) { return Convert.ToDouble(strReceive); } return E1.GENERIC; } private string GetValueString(string cmd, int value) { if (!IsPortOpen()) { return string.Empty; } lock (LockThis) { if (cmd != OP_GET) { return string.Empty; } byte[] sendData = new byte[6]; byte[] opCode = Encoding.Default.GetBytes(cmd); sendData[0] = BYTE_STX; sendData[1] = opCode[0]; //‘01’ sendData[2] = opCode[1]; sendData[3] = BYTE_1; //Data Length (1byte) sendData[4] = (byte)(BYTE_0 + value); sendData[5] = BYTE_CR; #warning 읽는 방식 바꿀것. 사용한 적 없는 디바이스. string readData = string.Empty; //if (!ReadExisting(sendData, out readData)) { // return string.Empty; //} return readData; } } private bool CheckNumberString(string str) { if (str == string.Empty) { return false; } var numBytes = Encoding.Default.GetBytes(str); int index = 0; // 양수 및 음수(+/-) 부호 체크 if (numBytes[index] == '-' || numBytes[index] == '+') { index++; } // 문자열 앞에 0이 있을 경우 0.123 형태의 소수점 숫자인지 잘못된 숫자인지 체크 if (numBytes[index] == BYTE_0) { if (numBytes.Length == 1) { return true; } index++; if (numBytes[index] != '.' && !IsDigit(numBytes[index])) { return false; } index++; } // 입력받은 문자열 중간에 숫자가 아닌 문자 존재여부 판별 및 올바른 형태의 숫자여부 판별 int pointCount = 0; int lengthCount = 0; while (index < numBytes.Length) { // 소수점 체크. 소수점은 1.234처럼 숫자 중간에 단 한개만 올 수 있으며, // .123과 같이 숫자 맨 앞에 혹은 123. 과 같이 숫자 맨 뒤에 소수점이 올 수 없다. if (!IsDigit(numBytes[index])) { if ((numBytes[index] != '.') || (numBytes[index] == '.' && lengthCount == 0) || (numBytes[index] == '.' && pointCount > 0)) { return false; } else { index++; if (index >= numBytes.Length) { return false; } pointCount++; } } else { index++; } lengthCount++; } return true; } private bool IsDigit(byte b) { return ('0' <= b && b <= '9'); } #endregion } }