# include <unistd.h>
# include <iomanip>
# include <iostream>
# include <stdio.h>
# include <fstream>
# include <string.h>
# include <stdint.h>
# include <arpa/inet.h>
# include <cstdlib>
# include <unistd.h>

using namespace std;

struct header
{
uint16_t packet_index;
uint8_t packet_type;
uint8_t last_packet;
uint16_t checksum;
}myheader;

struct data
{
char data_payload[250];
}mydata;




void run_ldattach();
void htonheader(struct header h,char buffer[6]);
void htondata(struct data d,char buffer[250]);
void htonheaderdata(struct header h,struct data d,char buffer[256]);
uint16_t checksum(char *ptr,size_t sz);
void send_connection_acknowledgement();
void ntohheader(struct header h,char buffer[6]);
void ntohdata(struct data d,char buffer[250]);
void ntohheaderdata(struct header h,struct data d,char buffer[256]);
bool test_checksum(uint16_t data_checksum,uint16_t calculated_checksum);
int receive_cts();
void send_data_acknowledgement();
int listen();
void send_data();
void send_comm_link_acknowledgement();









void run_ldattach()
{
cout<<"Attaching radio DNT900 to USB port ttyUSB0..."<<endl;
system("ldattach -8n1 -s 9600 29 /dev/ttyUSB0");
sleep(60);
cout<<"Radio DNT900 successfully attached to USB port ttyUSB0"<<endl;
}


int listen()
{
string inputfilename = "/dev/ttyDNT1";
ifstream instream;
instream.open(inputfilename.data());
instream.clear();
cout<<"Listening for requests from ground control station..."<<endl;
char buffer[256];
string message[250];
for (int i=0;i<256;i++)
{
instream>>buffer[i];
}
ntohheaderdata(myheader,mydata,buffer);
size_t length =strlen(mydata.data_payload);
uint16_t checksumvalue=checksum(mydata.data_payload,length);
bool checksum_ok_value=test_checksum(myheader.checksum,checksumvalue);
if (checksum_ok_value==1 && myheader.packet_type=='1')
{
string message_listen=mydata.data_payload;
if (message_listen=="connectionrequest")
return 1;
else if (message_listen=="datarequest")
return 2;
else if (message_listen=="commlinkrequest")
return 3;
}
else
return 0;
}



void htonheader(struct header h,char buffer[6])
{
uint16_t p_index;
uint8_t p_type;
uint8_t p_last;
uint16_t p_checksum;
p_index=h.packet_index;
memcpy(buffer+0,&p_index,2);
p_type=h.packet_type;
memcpy(buffer+2,&p_type,1);
p_last=h.last_packet;
memcpy(buffer+3,&p_last,1);
p_checksum=h.checksum;
memcpy(buffer+4,&p_checksum,2);
}

void htondata(struct data d,char buffer[250])
{
char d_payload[250];
for (int i=0;i<250;i++)
{
d_payload[i]=d.data_payload[i];
}
memcpy(buffer+0,&d_payload,250);
}

void htonheaderdata(struct header h,struct data d,char buffer[256])
{
htonheader(h,buffer+0);
htondata(d,buffer+6);
}

uint16_t checksum(char *ptr,size_t sz)
{
uint16_t chk=0;
while(sz-- !=0)
chk-=*ptr++;
return chk;
}

void send_connection_acknowledgement()
{
cout<<"Received connection request from ground control station"<<endl;
cout<<"Sending connection acknowledgement to ground control station..."<<endl;
string outputfilename="/dev/ttyDNT1";
char buffer[256];
ofstream outstream;
outstream.open(outputfilename.data());
outstream.clear();
myheader.packet_index=500;
myheader.packet_type='1';
myheader.last_packet='1';
char connection_request_message[250]="connectionok";
for(int i=0;i<250;i++)
{
mydata.data_payload[i]=connection_request_message[i];
}
size_t length=strlen(mydata.data_payload);
myheader.checksum=checksum(mydata.data_payload,length);
htonheaderdata(myheader,mydata,buffer);
for(int i=0;i<256;i++)
{
outstream<<buffer[i];
}
outstream<<endl;
outstream.close();
cout<<"Connection acknowledgement sent to ground control station"<<endl;
}

void ntohheader(struct header h,char buffer[6])
{
uint16_t p_index;
uint8_t p_type;
uint8_t p_last;
uint16_t p_checksum;
memcpy(&p_index,buffer+0,2);
h.packet_index=p_index;
myheader.packet_index=h.packet_index;
memcpy(&p_type,buffer+2,1);
h.packet_type=p_type;
myheader.packet_type=h.packet_type;
memcpy(&p_last,buffer+3,1);
h.last_packet=p_last;
myheader.last_packet=h.last_packet;
memcpy(&p_checksum,buffer+4,2);
h.checksum=p_checksum;
myheader.checksum=h.checksum;
}

void ntohdata(struct data d,char buffer[250])
{
char d_payload[250];
memcpy(&d_payload,buffer+0,250);
for (int i=0;i<250;i++)
{
d.data_payload[i]=d_payload[i];
mydata.data_payload[i]=d.data_payload[i];
}
}

void ntohheaderdata(struct header h,struct data d,char buffer[256])
{
ntohheader(h,buffer+0);
ntohdata(d,buffer+6);
}

bool test_checksum(uint16_t data_checksum,uint16_t calculated_checksum)
{
bool checksum_ok=0;
if(data_checksum==calculated_checksum)
checksum_ok=1;
else
checksum_ok=0;
return checksum_ok;
}

int receive_cts()
{
cout<<"Waiting for CTS from ground control station..."<<endl;
string inputfilename="/dev/ttyDNT1";
char buffer[256];
ifstream instream;
string message[250];
instream.open(inputfilename.data());
instream.clear();

for (int i=0;i<256;i++)
{
instream>>buffer[i];
}

ntohheaderdata(myheader,mydata,buffer);
size_t length=strlen(mydata.data_payload);
uint16_t checksumvalue=checksum(mydata.data_payload,length);
bool checksum_ok_value=test_checksum(myheader.checksum,checksumvalue);
int return_cts=0;
string message_receive_cts=mydata.data_payload;
if (checksum_ok_value==1 && myheader.packet_type=='1' && message_receive_cts=="cts")
{
cout<<"CTS received from ground control station"<<endl;
return_cts=1;
}
else
{
cout<<"ERROR! Did not receive CTS from ground control station"<<endl;
return_cts=2;
}
return return_cts;
}



void send_data_acknowledgement()
{
cout<<"Received data request from ground control station"<<endl;
cout<<"Sending data acknowledgement to ground control station..."<<endl;
string outputfilename="/dev/ttyDNT1";
char buffer[256];
ofstream outstream;
outstream.open(outputfilename.data());
outstream.clear();
myheader.packet_index=500;
myheader.packet_type='1';
myheader.last_packet='1';
char data_request_message[250]="dataok";
for(int i=0;i<250;i++)
{
mydata.data_payload[i]=data_request_message[i];
}
size_t length=strlen(mydata.data_payload);
myheader.checksum=checksum(mydata.data_payload,length);
htonheaderdata(myheader,mydata,buffer);
for(int i=0;i<256;i++)
{
outstream<<buffer[i];
}
outstream<<endl;
outstream.close();
cout<<"Data acknowledgement sent to ground control station"<<endl;
}

void send_comm_link_acknowledgement()
{
cout<<"Received communication link status request from ground control station"<<endl;
cout<<"Sending communication link status acknowledgement to ground control station..."<<endl;
string outputfilename="/dev/ttyDNT1";
char buffer[256];
ofstream outstream;
outstream.open(outputfilename.data());
outstream.clear();
myheader.packet_index=500;
myheader.packet_type='1';
myheader.last_packet='1';
char data_request_message[250]="commlinkok";
for(int i=0;i<250;i++)
{
mydata.data_payload[i]=data_request_message[i];
}
size_t length=strlen(mydata.data_payload);
myheader.checksum=checksum(mydata.data_payload,length);
htonheaderdata(myheader,mydata,buffer);
for(int i=0;i<256;i++)
{
outstream<<buffer[i];
}
outstream<<endl;
outstream.close();
cout<<"Communication link status acknowledgement sent to ground control station"<<endl;
}



void send_data()
{
cout<<"Sending ORBO data to ground control station..."<<endl;
string outputfilename = "/dev/ttyDNT1";
string inputfilename = "test2.txt";
char buffer[256];
ifstream instream;
ofstream outstream;
char message[250];
instream.open(inputfilename.data());
outstream.open(outputfilename.data());
instream.clear();
outstream.clear();
uint16_t count = 0;
for(;;)
{
instream.getline(message,250);
if(instream.eof()) break;
count++;
myheader.packet_index=500;
myheader.packet_type='2';
myheader.last_packet='1';
for (int i=0;i<250;i++)
{
mydata.data_payload[i]= message[i];
}
size_t length=strlen(mydata.data_payload);
myheader.checksum=checksum(mydata.data_payload,length);
htonheaderdata(myheader,mydata,buffer);
outstream<<buffer<<endl;
}
myheader.packet_type='9';
myheader.last_packet='9';
htonheaderdata(myheader,mydata,buffer);
outstream<<buffer<<endl;
outstream.close();
instream.close();
cout<<endl<<endl<<"---------------------------------------------TRANSMISSION\ 
COMPLETE-------------------------------------------------------------"<<endl;
cout<<"TOTAL PACKETS TRANSMITTED: "<<count<<endl<<endl;
cout<<"TOTAL BYTES TRANSMITTED: "<<count*256<<endl<<endl;
}











int main()
{
run_ldattach();
for(;;)
{
int listen_response=0;
listen_response=listen();
switch (listen_response)
{
case 1:
{
send_connection_acknowledgement();
}
break;
case 2:
{
send_data_acknowledgement();
receive_cts();
send_data();
}
break;
case 3:
{
send_comm_link_acknowledgement();
}
break;
default:
{
cout<<"Did not receive a valid request from ground control station!"<<endl;
}
}
}
return 0;
}




