// Module Name: udpreceiver.cpp
//
// Date: 05JUN09
//
// Description:
//
//    This sample program illustrates how to develop a simple UDP application
//		that reads 83P, 83B or 83Z data messages through port 4040 from another
//		PC running the Imagenex DeltaT.exe Multibeam beamforming sonar program.
//		This sample is implemented as a console-style application and simply
//		prints status messages when data is received.

// Command Line Options:
//
//    udpreceiver.exe
//
//    NOTE: There are no command parameters.
//

#include <winsock2.h>
#include <stdio.h>
#include <conio.h>

void main(void)
{
   WSADATA              wsaData;
   SOCKET               ReceivingSocket;
   SOCKADDR_IN          ReceiverAddr;
   int                  Port = 4040;
   unsigned char        ReceiveBuf[65536];
   int                  BufLength = 65536;
   SOCKADDR_IN          SenderAddr;
   int                  SenderAddrSize = sizeof(SenderAddr);
   int                  Ret;
	int						temp;
	float						ftemp;
   unsigned int			ping;

   // Initialize Winsock version 2.2

   if ((Ret = WSAStartup(MAKEWORD(2,2), &wsaData)) != 0)
   {
      // NOTE: Since Winsock failed to load we cannot use WSAGetLastError
      // to determine the error code as is normally done when a Winsock
      // API fails. We have to report the return status of the function.

      printf("ERROR: WSAStartup failed with error %d\n", Ret);
      getch();
      return;
   }


   // Create a new socket to receive datagrams on.

   if ((ReceivingSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))
       == INVALID_SOCKET)
   {
      printf("ERROR: socket failed with error %d\n", WSAGetLastError());
      WSACleanup();
      getch();
      return;
   }

   // Setup a SOCKADDR_IN structure that will tell bind that we
   // want to receive datagrams from all interfaces using port
   // 4040.

   ReceiverAddr.sin_family = AF_INET;
   ReceiverAddr.sin_port = htons(Port);
   ReceiverAddr.sin_addr.s_addr = htonl(INADDR_ANY);

   // Associate the address information with the socket using bind.

   if (bind(ReceivingSocket, (SOCKADDR *)&ReceiverAddr, sizeof(ReceiverAddr))
       == SOCKET_ERROR)
   {
      printf("ERROR: bind failed with error %d\n", WSAGetLastError());
      closesocket(ReceivingSocket);
      WSACleanup();
      getch();
      return;
   }

   printf("We are ready to receive 1 datagram from any interface on port %d...\n",
          Port);

   // At this point you can receive datagrams on your bound socket.

	while(!kbhit()) {
	   if ((Ret = recvfrom(ReceivingSocket, ReceiveBuf, BufLength, 0,
   	    (SOCKADDR *)&SenderAddr, &SenderAddrSize)) == SOCKET_ERROR)
	   {
   	   printf("ERROR: recvfrom failed with error %d\n", WSAGetLastError());
      	closesocket(ReceivingSocket);
	      WSACleanup();
   	   getch();
      	return;
	   }
      printf("%c%c%c - ",ReceiveBuf[0],ReceiveBuf[1],ReceiveBuf[2]);
      if(ReceiveBuf[2]=='Z') {
			printf("No Data, ");
      }
      else {
      	printf("%s %s%s, ",&ReceiveBuf[8],&ReceiveBuf[20],&ReceiveBuf[112]);
	      printf("%d Beams, ",(ReceiveBuf[70]<<8)|ReceiveBuf[71]);

         /*
   	   ping = ( (ReceiveBuf[93]<<24) | (ReceiveBuf[94]<<16) |
      			   (ReceiveBuf[95]<<8) | ReceiveBuf[96] );
	      printf("Ping %d, ",ping);
         */

	      //Ping Latency
      	temp = (ReceiveBuf[118]<<8) | ReceiveBuf[119];
	      ftemp = temp/10.0;
   	   printf("PL=%3.1fms, ",ftemp);

      	//Data Latency
   	   temp = (ReceiveBuf[120]<<8) | ReceiveBuf[121];
      	ftemp = temp/10.0;
	      printf("DL=%3.1fms, ",ftemp);

      	//Center Ping Time Offset
   	   temp = (ReceiveBuf[126]<<8) | ReceiveBuf[127];
      	ftemp = temp/10.0;
	      printf("CP=%3.1fms",ftemp);

      }
      //printf("num_bytes=%d",Ret);
		printf("\n");
	}

   // When your application is finished receiving datagrams close
   // the socket.

   closesocket(ReceivingSocket);

   // When your application is finished call WSACleanup.

   WSACleanup();
   getch();
}
