/*

	Connect, GetResult, ReadParameters, WriteParameters, Disconnect
	..with no use of RFDevice

*/

#include <Windows.h>
#include <WinSock.h>
#include <iostream>
#include <time.h>

#define ProfileValuesCount (2 * 1280*4)
#define ProfileSize (ProfileValuesCount + 12 + 4 + 512)

#define UserCfgAreaSize 512

#pragma pack(push, 1)
typedef struct _RF_COMMAND_PACKET { 
	DWORD				ulCommand; 
	DWORD				ulAttachSize;
	DWORD				ulOffset;
	DWORD				ulSize;
}  RF_COMMAND_PACKET; 
#pragma pack(pop)

int main(int argc, char *argv[])
{
	SOCKET s = SOCKET_ERROR;
	WORD wVersionRequested;
	WSADATA wsaData;
	DWORD sockOpt;
	char *szIP = NULL;
	char *szPort = NULL;
	sockaddr_in sin;
	RF_COMMAND_PACKET rfcp;
	int iCount;
	BYTE *lpBuffer = NULL;

	// Get IP address and port from command line arguments if specified
	if (argc > 1) {
		szIP = argv[1];
	}
	if (argc > 2) {
		szPort = argv[2];
	}

	lpBuffer = new BYTE[ProfileSize];
	if (!lpBuffer) {
		std::cout << "Memory allocation failure" << std::endl;
		return 0;
	}

	// initialize Windows sockets
	wVersionRequested = MAKEWORD( 2, 2 );
	if (WSAStartup( wVersionRequested, &wsaData ) != 0)
	{
		std::cout << "WSAStartup() failed" << std::endl;
		return 0;
	}

	// Create and configure the socket
	s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (s == INVALID_SOCKET) {
		std::cout << "Unable to initialize socket" << std::endl;
		goto l_Exit;
	}

	sockOpt = 4000;
	if (setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (const char *)&sockOpt, sizeof(sockOpt)) == -1) {
		std::cout << "setsockopt(SO_RCVTIMEO) failed" << std::endl;
		goto l_Exit;
	}

	sockOpt = 1024*1024;
	if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, (const char *)&sockOpt, sizeof(sockOpt)) == -1) {
		std::cout << "setsockopt(SO_RCVBUF) failed" << std::endl;
		goto l_Exit;
	}

	//////////////////////////////////////////////////////////////////////////
	// Connect to sensor over TCP
	//////////////////////////////////////////////////////////////////////////
	sin.sin_family = AF_INET;
	sin.sin_addr.s_addr	= inet_addr(szIP ? szIP : "192.168.1.100");
	sin.sin_port = htons(szPort ? atoi(szPort) : 620);

	if (connect(s, (SOCKADDR*) &sin, sizeof(sin)) == SOCKET_ERROR) {
		std::cout << "connect() failed" << std::endl;
		goto l_Exit;
	}

	//////////////////////////////////////////////////////////////////////////
	// EXAMPLE 1: 
	// Send command packet (GetResult = 0x0001)
	//////////////////////////////////////////////////////////////////////////
	rfcp.ulCommand = 1;
	rfcp.ulAttachSize = 0;
	rfcp.ulOffset = 0;
	rfcp.ulSize = 0;

	iCount = send(s, (const char *)&rfcp, sizeof(rfcp), 0);

	if (iCount < sizeof(rfcp)) {
		std::cout << "send(rfcp) failed" << std::endl;
		goto l_Exit;
	}

	// Receive answer with profile data
	iCount = recv(s, (char *)lpBuffer, ProfileSize, 0);

	// Size of answer is variable length but max is ProfileSize bytes
	if (iCount <= 0) {
		std::cout << "recv(lpBuffer) failed" << std::endl;
		goto l_Exit;
	}

	// Data successfully received, length iCount bytes
	std::cout << "Received " << iCount << " bytes packet" << std::endl;

	//////////////////////////////////////////////////////////////////////////
	// EXAMPLE 2: 
	// Read user parameters
	//////////////////////////////////////////////////////////////////////////
	rfcp.ulCommand = 4;
	rfcp.ulAttachSize = 0;
	rfcp.ulOffset = 0;
	rfcp.ulSize = 0;

	iCount = send(s, (const char *)&rfcp, sizeof(rfcp), 0);

	if (iCount < sizeof(rfcp)) {
		std::cout << "send(rfcp) failed" << std::endl;
		goto l_Exit;
	}

	// Receive answer with configuration block
	iCount = recv(s, (char *)lpBuffer, UserCfgAreaSize, 0);

	// Size of answer is variable length but max is ProfileSize bytes
	if (iCount != UserCfgAreaSize) {
		std::cout << "recv(lpBuffer) failed" << std::endl;
		goto l_Exit;
	}

	// Data successfully received, length iCount bytes
	std::cout << "Received " << iCount << " bytes packet" << std::endl;

	//////////////////////////////////////////////////////////////////////////
	// EXAMPLE 3: 
	// Write user parameters
	//////////////////////////////////////////////////////////////////////////
	rfcp.ulCommand = 5;
	rfcp.ulAttachSize = UserCfgAreaSize;
	rfcp.ulOffset = 0;
	rfcp.ulSize = 0;

	iCount = send(s, (const char *)&rfcp, sizeof(rfcp), 0);

	if (iCount < sizeof(rfcp)) {
		std::cout << "send(rfcp) failed" << std::endl;
		goto l_Exit;
	}

	// Receive answer with configuration block
	iCount = send(s, (char *)lpBuffer, rfcp.ulAttachSize, 0);

	// Size of answer is variable length but max is ProfileSize bytes
	if (iCount != rfcp.ulAttachSize) {
		std::cout << "send(lpBuffer) failed" << std::endl;
		goto l_Exit;
	}

	// Data successfully sent, length iCount bytes
	std::cout << "Sent " << iCount << " bytes packet" << std::endl;

l_Exit:

	// Cleanup
	if (lpBuffer) delete[] lpBuffer;
	//////////////////////////////////////////////////////////////////////////
	// Close TCP connection to sensor
	//////////////////////////////////////////////////////////////////////////
	rfcp.ulCommand = 0x19;
	rfcp.ulAttachSize = 0;
	rfcp.ulOffset = 0;
	rfcp.ulSize = 0;

	iCount = send(s, (const char *)&rfcp, sizeof(rfcp), 0);

	if (s != SOCKET_ERROR) {
		shutdown(s, 1);
		closesocket(s);
	}
	WSACleanup();

	return 0;
}

