C#控制TH300(韩荣/志和)温湿度控制器
// C#控制TH300(韩荣/志和)温湿度控制器
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.IO.Ports;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
namespace JohnKit
{
/// <summary>
/// 温箱控制 TH300
/// H.Z.XIN 2021-11-30
/// Modified:
/// 2021-11-30 create
///
/// </summary>
public class Temper
{
private SerialPort mComPort = new SerialPort();
private string mMachineNum; //"001";
private byte[] mRecvBuffer = new byte[2048];
private static readonly byte STX = 0x02;
//private static readonly byte ETX = 0x03;
private static readonly byte[] ECL = { 0x03, 0x0D, 0x0A };
class TRetData
{
public TRetData()
{
bok = false;
data = new List<byte[]>();
}
public bool bok;
public List<byte[]> data;
}
public Temper(string machineNum, int nReadTimeOut = 4000)
{
mMachineNum = machineNum;
mComPort.ReadTimeout = nReadTimeOut < 0 ? SerialPort.InfiniteTimeout : nReadTimeOut;
mComPort.BaudRate = 38400;
mComPort.DataBits = 8;
mComPort.Parity = Parity.None;
mComPort.StopBits = StopBits.One;
mComPort.RtsEnable = false;
}
/// <summary>
/// 尝试打开串口
/// </summary>
/// <returns>
/// -1 -- COM口不存在
/// 0 -- COM口打开失败
/// 1 -- COM口打开成功
/// </returns>
public int TryOpenCOM(string scom)
{
mComPort.PortName = scom;
try
{
mComPort.Open();
}
catch (IOException)
{
Debug.WriteLine(string.Format("{0} not exist", scom));
return -1;
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
return 0;
}
return mComPort.IsOpen ? 1 : 0;
}
private List<byte> ComRead(int nMaxRead = 100)
{
var lsby = new List<byte>();
int nGet = -1;
ResetBuf();
try
{
//sret = mComPort.ReadLine();
//Debug.WriteLine($"ret: {sret}");
nGet = mComPort.Read(mRecvBuffer, 0, nMaxRead);
}
catch (System.Exception ex)
{
Debug.WriteLine(ex.Message);
}
int iStart = -1;
int iEnd = -1;
for (int i = 0; i < nGet; i++)
{
if (mRecvBuffer[i] == STX)
{
iStart = i;
}
else if (i <= nGet - ECL.Length)
{
bool bFound = true;
for (int j = 0; j < ECL.Length; j++)
{
if (mRecvBuffer[i + j] != ECL[j])
{
bFound = false;
break;
}
}
if (bFound)
{
iEnd = i;
}
}
}
if (iStart < iEnd && iStart >= 0)
{
for (int i = iStart; i < iEnd + ECL.Length; i++)
{
lsby.Add(mRecvBuffer[i]);
}
}
return lsby;
}
private bool ComWrite(byte[] cSendData, int iStart, int n)
{
try
{
mComPort.Write(cSendData, iStart, n);
}
catch (System.Exception ex)
{
Debug.WriteLine(ex.Message);
return false;
}
return true;
}
public void ComClose()
{
mComPort.Close();
}
public bool IsConnected()
{
bool bok = mComPort.IsOpen;
return bok;
}
#region 内部函数
private static byte[] Short2Byte(short n)
{
var bys = new byte[2];
bys[0] = (byte)((n & 0xFF00) >> 8);
bys[1] = (byte)((n & 0x00FF) >> 0);
return bys;
}
private static short toLSB(short n)
{
short sval = 0;
sval |= (short)((n & 0xFF00) >> 8);
sval |= (short)((n & 0x00FF) << 8);
return sval;
}
private static byte[] Str2Byte(string s)
{
return System.Text.Encoding.ASCII.GetBytes(s);
}
private static string Byte2Str(byte[] bys)
{
return System.Text.Encoding.ASCII.GetString(bys);
}
private static byte[] MakePackage(byte[] bydat)
{
int nLen = 1 + 3 + bydat.Length; // STX + bydat + ECL
var bys = new byte[nLen];
int i = 0;
bys[i++] = STX;
for (var j = 0; j < bydat.Length; j++)
{
bys[i++] = bydat[j];
}
for (var j = 0; j < ECL.Length; j++)
{
bys[i++] = ECL[j];
}
return bys;
}
private void ResetBuf()
{
for (int i = 0; i < mRecvBuffer.Length; i++)
{
mRecvBuffer[i] = 0;
}
}
// 解包
private static bool ExtractPackage(List<byte> lsby, ref TRetData res)
{
var poss = new List<int>();
for(int i=0; i<lsby.Count; i++)
{
if(0x2C == lsby[i])
{
poss.Add(i);
}
}
if (poss.Count < 1)
{
return false;
}
int iDiv = poss[0];
int iNextDiv = poss.Count > 1 ? poss[1] : lsby.Count;
int nLen = iNextDiv-iDiv-1;
var byTemp = new byte[nLen];
lsby.CopyTo(iDiv + 1, byTemp, 0, nLen);
bool bok = "OK".Equals(Byte2Str(byTemp), StringComparison.InvariantCultureIgnoreCase);
res.data.Clear();
int nDiv = poss.Count;
for(int i=1; i<nDiv; i++)
{
if(i==nDiv-1)
{
iDiv = poss[i];
iNextDiv = iDiv;
bool bEndsign = false;
while(iNextDiv<=lsby.Count-ECL.Length)
{
bool bsign = true;
for(int k=0; k<ECL.Length; k++)
{
if(lsby[iNextDiv+k] != ECL[k])
{
bsign = false;
break;
}
}
if(bsign)
{
bEndsign = true;
break; //!
}
iNextDiv++;
}
if(!bEndsign)
{
Debug.WriteLine("*返回数据没有找到ECL");
}
iNextDiv = bEndsign ? iNextDiv : lsby.Count;
}
else
{
iDiv = poss[i];
iNextDiv = poss[i + 1];
}
nLen = iNextDiv-iDiv-1;
byTemp = new byte[nLen];
lsby.CopyTo(iDiv + 1, byTemp, 0, nLen);
res.data.Add(byTemp);
}
return res.data.Count > 0;
}
private static object BytesToStruct(byte[] bytes, Type strcutType)
{
int size = Marshal.SizeOf(strcutType);
IntPtr buffer = Marshal.AllocHGlobal(size);
try
{
Marshal.Copy(bytes, 0, buffer, size);
return Marshal.PtrToStructure(buffer, strcutType);
}
catch(Exception ex)
{
Debug.WriteLine(ex.Message);
}
finally
{
Marshal.FreeHGlobal(buffer);
}
return null;
}
private static float packTemp(float fraw)
{
return (fraw + 100.00F) * 100.00F;
}
private static float unpackTemp(float fraw)
{
return fraw/100.00F - 100.00F;
}
#endregion
public bool GetMachineVersion(ref string sVer)
{
sVer = string.Empty;
if (!mComPort.IsOpen)
{
return false;
}
var scmd = string.Format("{0}WHO", mMachineNum);
var bys = MakePackage(Str2Byte(scmd));
List<byte> byRead;
{
//Debug.Assert(10 == bys.Length);
if (!ComWrite(bys, 0, bys.Length))
{
return false;
}
byRead = ComRead(64);
}
var pRet = new TRetData();
if (!ExtractPackage(byRead, ref pRet))
{
return false;
}
if (pRet.data.Count > 0)
{
sVer = Byte2Str(pRet.data[0]);
return true;
}
return false;
}
private bool sendWRP(string sReg, byte[] byCmd)
{
if (!mComPort.IsOpen)
{
return false;
}
//机号 WRP , REG号 , Data
var byList = new List<byte>();
var stemp = string.Format("{0}WRP,{1},", mMachineNum, sReg);
byList.AddRange(Str2Byte(stemp));
byList.AddRange(byCmd);
var bys = MakePackage(byList.ToArray());
//Debug.Assert(18 == bys.Length);
if (!ComWrite(bys, 0, bys.Length))
{
return false;
}
var byRead = ComRead(40);
var pRet = new TRetData();
if (!ExtractPackage(byRead, ref pRet))
{
return false;
}
bool bok = false;
if (pRet.data.Count > 0)
{
var sRet = Byte2Str(pRet.data[0]);
bok = sReg.Equals(sRet);
}
return bok;
}
public bool startRun()
{
var sReg = "0001";
var byCmd = new byte[] { 0x00, 0x01 };
return sendWRP(sReg, byCmd);
}
public bool stopRun()
{
var sReg = "0001";
var byCmd = new byte[] { 0x00, 0x00 };
return sendWRP(sReg, byCmd);
}
public bool setTemperature(float ftemp)
{
var sReg = "0012";
var fval = packTemp(ftemp);
var byCmd = Short2Byte((short)fval);
return sendWRP(sReg, byCmd);
}
[StructLayoutAttribute(LayoutKind.Sequential,Pack=1)]
struct TCurValue
{
public short TSV;
public short TPV;
public short TMV;
public short HSV;
public short HPV;
public short HMV;
public short TIpS;
public short TpS;
public short ApS;
public short RY;
public short OpC;
public short DpI;
public byte RM;
public short RTH;
public byte RTM;
public byte RTS;
public short SRTH;
public byte SRTM;
public short SFTH;
public byte SFTM;
public short RPTN;
public byte RSEG;
public short RPRC;
public short RPRN;
public byte RLC;
public byte RLN;
public byte UDSW;
}
private bool sendRCV(string sReg, ref TCurValue pval)
{
if (!mComPort.IsOpen)
{
return false;
}
//机号 RCV
var byList = new List<byte>();
var stemp = string.Format("{0}RCV", mMachineNum);
byList.AddRange(Str2Byte(stemp));
var bys = MakePackage(byList.ToArray());
//Debug.Assert(10 == bys.Length);
if (!ComWrite(bys, 0, bys.Length))
{
return false;
}
var byRead = ComRead(59);
var pRet = new TRetData();
if (!ExtractPackage(byRead, ref pRet))
{
return false;
}
bool bok = pRet.data.Count > 0;
if (bok)
{
var oval = (TCurValue?)BytesToStruct(pRet.data[0], typeof(TCurValue));
bok = oval.HasValue;
if (bok)
{
pval = oval.Value;
}
}
return bok;
}
public bool getTemperature(out float ftemp)
{
ftemp = 0.0f;
var sReg = "0012";
TCurValue tval=new TCurValue();
if (!sendRCV(sReg, ref tval))
{
return false;
}
ftemp = unpackTemp(toLSB(tval.TPV));
//float ftsv = unpackTemp(toLSB(tval.TSV));
return true;
}
}
}