#include <stdio.h>
#include "ModbusTCP.h"

char	_szHexSend[ADAM_MAX_MSGLEN]; // for modbus functions
char	_szHexRecv[ADAM_MAX_MSGLEN]; // for modbus functions

bool CommonSendRead(int i_iAddr, 
					int i_iFun,
					int i_iStartIndex,
					int i_iTotalPoint)
{
	int iHexLen, iRTULen;
	unsigned char szRTUCmd[ADAM_MAX_MSGLEN]={0};
	char szModCmd[ADAM_MAX_MSGLEN] = {0};

	memset(_szHexSend, 0, ADAM_MAX_MSGLEN);
	sprintf(szModCmd, "%02X%02X%04X%04X", i_iAddr, i_iFun, i_iStartIndex-1, i_iTotalPoint);
	sprintf(_szHexSend, "0000000000%02X%s", strlen(szModCmd)/2, szModCmd);
	iHexLen = strlen(_szHexSend);
	// form TCP-RTU command
	HexToRTU(_szHexSend, szRTUCmd);
	iRTULen = iHexLen/2;
	return SendTCP(szRTUCmd, iRTULen);
}

bool CommonRecvRead(unsigned char o_szData[], int *o_iTotalByte)
{
	unsigned char szRecv[ADAM_MAX_MSGLEN]={0};
	int iRTULen, iDatLen;

	// iRTULen must be greater or equal 9; 
	// 'header(12)', 'addr(2)', 'fun(2)', 'count(2)', 18 TCP-HEX bytes
	// 'header(6)', 'addr(1)', 'fun(1)', 'count(1)', 9 TCP-RTU bytes
	if (RecvTCP(szRecv, &iRTULen) && iRTULen>9)
	{
        RTUToHex(szRecv, iRTULen, _szHexRecv);
		if (_szHexSend[14] == _szHexRecv[14] && 
			_szHexSend[15] == _szHexRecv[15]) 
			// function code must be the same, otherwise, exception
		{
			iDatLen = szRecv[8];
			*o_iTotalByte = iDatLen;
			memcpy(o_szData, szRecv+9, iDatLen);
			return true;
		}
	}
	return false;
}

void HexToRTU(char *i_szHexCmd, unsigned char *o_szRTUCmd)
{
	int idx, iRTULen;
	char szTmp[8];

	iRTULen = strlen(i_szHexCmd)/2;
	for (idx=0; idx<iRTULen; idx++)
	{
		memset(szTmp, 0, 8);
		memcpy(szTmp, i_szHexCmd + idx*2, 2);
		sscanf(szTmp, "%X", o_szRTUCmd+idx); 
	}
}

void RTUToHex(unsigned char *i_szRTUCmd, int i_RTULen, char *o_szHexCmd)
{
	int idx;
	char szTmp[8];

	o_szHexCmd[0] = '\0';
	for (idx=0; idx<i_RTULen; idx++)
	{
		memset(szTmp, 0, 8);
		sprintf(szTmp, "%02X", i_szRTUCmd[idx]);
		strcat(o_szHexCmd, szTmp);
	}
}

// function (01 HEX)
bool SendReadCoilStatus(int i_iAddr, 
									int i_iStartIndex,
									int i_iTotalPoint)
{
	return CommonSendRead(i_iAddr, 1, i_iStartIndex, i_iTotalPoint);
}

// function (01 HEX)
bool RecvReadCoilStatus(unsigned char o_szData[], int *o_iTotalByte)
{
	return CommonRecvRead(o_szData, o_iTotalByte);
}

// function (02 HEX)
bool SendReadInputStatus(int i_iAddr, 
									 int i_iStartIndex,
									 int i_iTotalPoint)
{
	return CommonSendRead(i_iAddr, 2, i_iStartIndex, i_iTotalPoint);
}

// function (02 HEX)
bool RecvReadInputStatus(unsigned char o_szData[], int *o_iTotalByte)
{
	return CommonRecvRead(o_szData, o_iTotalByte);
}

// function (03 HEX)
bool SendReadHoldingRegs(int i_iAddr, 
									 int i_iStartIndex,
									 int i_iTotalPoint)
{
	return CommonSendRead(i_iAddr, 3, i_iStartIndex, i_iTotalPoint);
}

// function (03 HEX)
bool RecvReadHoldingRegs(unsigned char o_szData[], int *o_iTotalByte)
{
	return CommonRecvRead(o_szData, o_iTotalByte);
}

// function (04 HEX)
bool SendReadInputRegs( int i_iAddr, 
									int i_iStartIndex,
									int i_iTotalPoint)
{
	return CommonSendRead(i_iAddr, 4, i_iStartIndex, i_iTotalPoint);
}

// function (04 HEX)
bool RecvReadInputRegs(unsigned char o_szData[], int *o_iTotalByte)
{
	return CommonRecvRead(o_szData, o_iTotalByte);
}

// function (05 HEX)
bool SendForceSingleCoil(int i_iAddr,
									 int i_iCoilIndex,
									 int i_iData)
{
	int iHexLen, iRTULen;
	unsigned char szRTUCmd[ADAM_MAX_MSGLEN]={0};
	char szModCmd[ADAM_MAX_MSGLEN] = {0};
	int coilData;

	if (i_iData == 0)
		coilData = 0x0000;
	else
		coilData = 0xFF00;
    memset(_szHexSend, 0, ADAM_MAX_MSGLEN);
	sprintf(szModCmd, "%02X%02X%04X%04X", i_iAddr, 5, i_iCoilIndex-1, coilData);
	sprintf(_szHexSend, "0000000000%02X%s", strlen(szModCmd)/2, szModCmd);
	iHexLen = strlen(_szHexSend);
	// form TCP-RTU command
	HexToRTU(_szHexSend, szRTUCmd);
	iRTULen = iHexLen/2;
	return SendTCP(szRTUCmd, iRTULen);
}

// function (05 HEX)
bool RecvForceSingleCoil()
{
	unsigned char szRecv[ADAM_MAX_MSGLEN];
	int iRTULen;

	// 'header(12)', 'addr(2)', 'fun(2)', 'Coil addr Hi-Lo(4)', 
	// 'Force data Hi-Lo(4)', 24 TCP-HEX bytes, 12 TCP_RTU bytes
	if (RecvTCP(szRecv, &iRTULen) && iRTULen>=12)
    {
        RTUToHex(szRecv, iRTULen, _szHexRecv);
		if (_szHexSend[14] == _szHexRecv[14] && 
			_szHexSend[15] == _szHexRecv[15]) 
			// function code must be the same, otherwise, exception
			return true;
    }
	return false;
}

// function (06 HEX)
bool SendPresetSingleReg(int i_iAddr,
									 int i_iRegIndex,
									 int i_iData)
{
	int iHexLen, iRTULen;
	unsigned char szRTUCmd[ADAM_MAX_MSGLEN]={0};
	char szModCmd[ADAM_MAX_MSGLEN] = {0};

    memset(_szHexSend, 0, ADAM_MAX_MSGLEN);
	sprintf(szModCmd, "%02X%02X%04X%04X", i_iAddr, 6, i_iRegIndex-1, i_iData);
	sprintf(_szHexSend, "0000000000%02X%s", strlen(szModCmd)/2, szModCmd);
	iHexLen = strlen(_szHexSend);
	// form TCP-RTU command
	HexToRTU(_szHexSend, szRTUCmd);
	iRTULen = iHexLen/2;
	return SendTCP(szRTUCmd, iRTULen);
}

// function (06 HEX)
bool RecvPresetSingleReg()
{
	unsigned char szRecv[ADAM_MAX_MSGLEN];
	int iRTULen;

	// iRTULen must be equal 12;
	// 'header(12)', 'addr(2)', 'fun(2)', 'Coil addr Hi-Lo(4)',
	// 'Force data Hi-Lo(4)', 24 TCP-HEX bytes, 12 TCP-RTU bytes
	if (RecvTCP(szRecv, &iRTULen) && iRTULen>=12)
    {
        RTUToHex(szRecv, iRTULen, _szHexRecv);
		if (_szHexSend[14] == _szHexRecv[14] && 
			_szHexSend[15] == _szHexRecv[15]) 
			// function code must be the same, otherwise, exception
			return true;
    }
	return false;
}

// function (0F HEX)
bool SendForceMultiCoils(int i_iAddr, 
									 int i_iCoilIndex,
									 int i_iTotalPoint,
									 int i_iTotalByte,
									 unsigned char i_szData[])
{
	int idx, iHexLen, iRTULen;
	unsigned char szRTUCmd[ADAM_MAX_MSGLEN]={0};
	char szTmp[8];
	char szModCmd[ADAM_MAX_MSGLEN] = {0};

	// form modbus command
    memset(_szHexSend, 0, ADAM_MAX_MSGLEN);
	sprintf(szModCmd, "%02X%02X%04X%04X%02X", i_iAddr, 0x0F, i_iCoilIndex-1,
			i_iTotalPoint, i_iTotalByte);
	for (idx=0; idx<i_iTotalByte; idx++)
	{
		memset(szTmp, 0, 8);
		sprintf(szTmp, "%02X", i_szData[idx]);
		strcat(szModCmd, szTmp);
	}

	// form TCP-HEX command
	sprintf(_szHexSend, "0000000000%02X%s", strlen(szModCmd)/2, szModCmd);
	iHexLen = strlen(_szHexSend);
	// form TCP-RTU command
	HexToRTU(_szHexSend, szRTUCmd);
	iRTULen = iHexLen/2;
	return SendTCP(szRTUCmd, iRTULen);
}

// function (0F HEX)
bool RecvForceMultiCoils()
{
	unsigned char szRecv[ADAM_MAX_MSGLEN];
	int iRTULen;

	// iRTULen must be equal 12;
	// 'header(12)', 'addr(2)', 'fun(2)', 'addr Hi-Lo(4)',
	// 'quantity Hi-Lo(4)', 24 TCP-HEX bytes, 12 TCP-RTU bytes
	if (RecvTCP(szRecv, &iRTULen) && iRTULen>=12)
    {
        RTUToHex(szRecv, iRTULen, _szHexRecv);
		if (_szHexSend[14] == _szHexRecv[14] && 
			_szHexSend[15] == _szHexRecv[15]) 
			// function code must be the same, otherwise, exception
			return true;
    }
	return false;
}

// function (10 HEX)
bool SendPresetMultiRegs(int i_iAddr, 
									 int i_iStartReg,
									 int i_iTotalReg,
									 int i_iTotalByte,
									 unsigned char i_szData[])
{
	int idx, iHexLen, iRTULen;
	unsigned char szRTUCmd[ADAM_MAX_MSGLEN]={0};
	char szTmp[8];
	char szModCmd[ADAM_MAX_MSGLEN] = {0};

	// form modbus command
    memset(_szHexSend, 0, ADAM_MAX_MSGLEN);
	sprintf(szModCmd, "%02X%02X%04X%04X%02X", i_iAddr, 0x10, i_iStartReg-1,
			i_iTotalReg, i_iTotalByte);
	for (idx=0; idx<i_iTotalByte; idx++)
	{
		memset(szTmp, 0, 8);
		sprintf(szTmp, "%02X", i_szData[idx]);
		strcat(szModCmd, szTmp);
	}

	// form TCP-HEX command
	sprintf(_szHexSend, "0000000000%02X%s", strlen(szModCmd)/2, szModCmd);
	iHexLen = strlen(_szHexSend);
	// form TCP-RTU command
	HexToRTU(_szHexSend, szRTUCmd);
	iRTULen = iHexLen/2;
	return SendTCP(szRTUCmd, iRTULen);
}

// function (10 HEX)
bool RecvPresetMultiRegs()
{
	unsigned char szRecv[ADAM_MAX_MSGLEN];
	int iRTULen;

	// iRTULen must be equal 12;
	// 'header(12)', 'addr(2)', 'fun(2)', 'addr Hi-Lo(4)',
	// 'No. of reg Hi-Lo(4)', 24 TCP-HEX bytes, 12 TCP-RTU bytes
	if (RecvTCP(szRecv, &iRTULen) && iRTULen>=12)
    {
        RTUToHex(szRecv, iRTULen, _szHexRecv);
		if (_szHexSend[14] == _szHexRecv[14] && 
			_szHexSend[15] == _szHexRecv[15]) 
			// function code must be the same, otherwise, exception
			return true;
    }
	return false;
}

//=========================================================================
//=========================================================================
bool ReadTransaction(char *i_szTwoHexAddr,
								 int  i_regLen,
							     char *i_szCmd,
							     char *o_szRecv,
                                 char *o_szSendHex, // if NULL, no value assign
                                 char *o_szRecvHex) // if NULL, no value assign
{
	int iAddr, iLen, iReg, iTotal, idx, count, iHexLen;
	unsigned char szCmd[ADAM_MAX_MSGLEN] = {0}, szRecv[ADAM_MAX_MSGLEN] = {0};
	char szBuf[3]={0};

	// address
	sscanf(i_szTwoHexAddr, "%X", &iAddr);
	// copy command
	iLen = strlen(i_szCmd);
	memcpy(szCmd, i_szCmd, iLen);
	szCmd[iLen] = 0x0D;
	iLen++;
	// 2 bytew per reg
	if (iLen % 2) // odd number of bytes
		iLen++;
	iReg = iLen/2;
	// send read command
	if (SendPresetMultiRegs(iAddr, 10000, iReg, iLen, szCmd) &&
        RecvPresetMultiRegs())
	{
		if (o_szSendHex) // not NULL, copy send HEX to it
			strcpy(o_szSendHex, _szHexSend);
		count = 0;
		while(1)
		{
			if (SendReadHoldingRegs(iAddr, 10000, i_regLen) &&
				RecvReadHoldingRegs(szRecv, &iTotal)) // szRecv is data alreay
			{
				for (idx=0; idx<iTotal; idx++)
				{
					if (szRecv[idx] == 0x0D)
					{
						o_szRecv[idx] = 0;
						break;
					}
					o_szRecv[idx] = szRecv[idx];
				}
				// Modbus/TCP (byte)
				// header(6), add(1), fun(1), byte Count(1), data(idx+1)
				if (o_szRecvHex) // not NULL, copy recv HEX to it
				{
					iHexLen = 18+(idx+1)*2;
					memcpy(o_szRecvHex, _szHexRecv, iHexLen);
					o_szRecvHex[iHexLen] = '\0';
					// modify header count
					sprintf(szBuf, "%02X", idx+1+3); // data length(idx+1)+add(1)+fun(1)+byte count(1)
					memcpy(o_szRecvHex+10, szBuf, 2);
					// modify byte count
					sprintf(szBuf, "%02X", idx+1); // data length(idx+1)
					memcpy(o_szRecvHex+16, szBuf, 2);
				}
				return true;
			}
			if (++count >= 5)
				return false;
			else
				Sleep(100);
		}
	}
	return false;
}



<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head><title>

</title></head>
<body>
    <form name="form1" method="post" action="DownloadSr.aspx?file_id=1-RAQCQ" id="form1">
<div>
<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwULLTE2MTY2ODcyMjlkZLNNJP85KggLvxsiTV7YApHD8b4/" />
</div>

    <div>
    
    </div>
    </form>
</body>
</html>
