# 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;


int home_menu();
void connect();
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_request();
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);
void receive_connection_acknowledgement();
void monitor_orbo();
void send_data_request();
int receive_data_acknowledgement();
void output_data();
void monitor_comm_link();
void send_comm_link_request();
int receive_comm_link_acknowledgement();
void output_comm_link_data();
void monitor_battery_power();
void send_command();
void orbo_live();
void help();
void exit_program();
int gethex(string hexstr);


void connect()
{
cout << "**************************************************************************************************************************************"<<endl;
cout<<"CONNECT"<<setw(100)<<"Connect to ORBO"<<endl;
cout << "**************************************************************************************************************************************"<<endl;
cout<<"Connecting to ORBO..."<<endl;
}

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;
}

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_request()
{
cout<<"Sending connection request to ORBO..."<<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]="connectionrequest";
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 request sent to ORBO"<<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;
}

void receive_connection_acknowledgement()
{
cout<<"Waiting for connection acknowledgement from ORBO..."<<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);
string message_connection_acknowledgement=mydata.data_payload;
if (checksum_ok_value==1 && myheader.packet_type=='1' && message_connection_acknowledgement=="connectionok")
{
cout<<"Acknowledgement received from ORBO"<<endl;
cout<<"Wireless link established"<<endl;
}
else
{
cout<<"ERROR! Did not receive acknowledgement from ORBO"<<endl;
cout<<"ERROR! Wireless link could not be established"<<endl;

for(;;)
{
cout<<"Please press 0 to go back to menu selection: ";
int response_receive_connection_acknowledgement=1;
cin>>response_receive_connection_acknowledgement;
if(response_receive_connection_acknowledgement==0) break;
else
{
cin.clear();
cin.ignore(10000,'\n');
}
}
}
}

void monitor_orbo()
{
cout<<"****************************************************************************************************************************************"<<endl;
cout<<"MONITOR ORBO"<<setw(100)<<"Monitor the UAV system";
cout<<endl;
cout<<"****************************************************************************************************************************************"<<endl;
cout<<"Initiating monitoring of ORBO..."<<endl;
}


void send_data_request()
{
cout<<"Sending data request to ORBO..."<<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]="datarequest";
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 request sent to ORBO"<<endl;
}

int receive_data_acknowledgement()
{
int receive_data_acknowledgement_response=0;
cout<<"Waiting for data acknowledgement from ORBO..."<<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);
string message_data_acknowledgement=mydata.data_payload;
if (checksum_ok_value==1 && myheader.packet_type=='1' && message_data_acknowledgement=="dataok")
{
cout<<"Acknowledgement received from ORBO"<<endl;
receive_data_acknowledgement_response=1;
}
else
{
cout<<"ERROR! Did not receive acknowledgement from ORBO"<<endl;

for(;;)
{
cout<<"Please press 0 to go back to menu selection: ";
int response_receive_connection_acknowledgement=1;
cin>>response_receive_connection_acknowledgement;
if(response_receive_connection_acknowledgement==0) break;
else
{
cin.clear();
cin.ignore(10000,'\n');
}
}
receive_data_acknowledgement_response=0;
}
return receive_data_acknowledgement_response;
}

void output_data()
{
cout<<"****************************************************************************************************************************************"<<endl;
string outputfilename = "orbo_data.txt";
string inputfilename = "/dev/ttyDNT1";
char buffer[256];
ifstream instream;
ofstream outstream;
string message[250];
int packet_drop=0;
instream.open(inputfilename.data());
instream.clear();
outstream.open(outputfilename.data(),ios::app);
outstream.clear();
int count=0;
outstream<<"****************************************************************************************************************************************\
***********"<<endl;
outstream<<setw(80)<<"ORBO Data"<<endl;
outstream<<"*****************************************************************************************************************************************\
***********"<<endl;

for(;;)
{
instream.getline(buffer,256);
ntohheaderdata(myheader,mydata,buffer);
count++;
if(myheader.last_packet=='9' && myheader.packet_type=='9')
{
count--;
goto stop;
}
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)
{
cout<<mydata.data_payload<<endl;
outstream<<mydata.data_payload<<endl;
}
else
{
cout<<"Data packet discarded"<<endl;
packet_drop++;
outstream<<"Data packet discarded"<<endl;
}
}
stop:instream.close();
outstream.close();
cout<<endl<<endl<<"------------------------------------------------TRANSMISSION COMPLETE-------------------------------------------------------"<<endl;
outstream<<endl<<endl<<"------------------------------------------------TRANSMISSION\ 
COMPLETE-------------------------------------------------------"<<endl;
cout<<"TOTAL PACKETS RECEIVED: "<<count<<endl<<endl;
outstream<<"TOTAL PACKETS RECEIVED: "<<count<<endl<<endl;
cout<<"TOTAL BYTES RECEIVED: "<<count*256<<endl<<endl;
outstream<<"TOTAL BYTES RECEIVED: "<<count*256<<endl<<endl;
cout<<"TOTAL PACKETS DISCARDED: "<<packet_drop<<endl<<endl;
outstream<<"TOTAL PACKETS DISCARDED: "<<packet_drop<<endl<<endl;
cout<<"Data written to file: orbo_data.txt"<<endl;
}

void send_cts()
{
cout<<"Sending CTS (Clear To Send) to ORBO..."<<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 cts_message[250]="cts";
for(int i=0;i<250;i++)
{
mydata.data_payload[i]=cts_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<<"CTS sent to ORBO"<<endl;
}

void monitor_comm_link()
{
cout<<"****************************************************************************************************************************************"<<endl;
cout<<setw(100)<<"Monitoring wireless communication link";
cout<<endl;
cout<<"****************************************************************************************************************************************"<<endl;
}

void send_comm_link_request()
{
cout<<"Sending communication link status request to ORBO..."<<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 comm_link_request_message[250]="commlinkrequest";
for (int i=0;i<250;i++)
{
mydata.data_payload[i]=comm_link_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 request sent to ORBO"<<endl;
}

int receive_comm_link_acknowledgement()
{
cout<<"Waiting for communication link status acknowledgement from ORBO..."<<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);
string message_comm_link_acknowledgement=mydata.data_payload;
if (checksum_ok_value==1 && myheader.packet_type=='1' && message_comm_link_acknowledgement=="commlinkok")
{
cout<<"Acknowledgement received from ORBO"<<endl;
}
else
{
cout<<"ERROR! Did not receive acknowledgement from ORBO"<<endl;

for(;;)
{
cout<<"Please press 0 to go back to menu selection: ";
int response_receive_connection_acknowledgement=1;
cin>>response_receive_connection_acknowledgement;
if(response_receive_connection_acknowledgement==0) break;
else
{
cin.clear();
cin.ignore(10000,'\n');
}
}
int receive_comm_link_acknowledgement_response=0;
return receive_comm_link_acknowledgement_response;
}
}

void output_comm_link_data()
{


string inputfilename_local_currfreqband = "/sys/devices/virtual/dnt900/ttyUSB0/0x001F5D/CurrFreqBand";
string inputfilename_local_currrfdatarate = "/sys/devices/virtual/dnt900/ttyUSB0/0x001F5D/CurrRF_DataRate";
string inputfilename_local_currrangedelay = "/sys/devices/virtual/dnt900/ttyUSB0/0x001F5D/CurrRangeDelay";
string inputfilename_local_currtxpower = "/sys/devices/virtual/dnt900/ttyUSB0/0x001F5D/CurrTxPower";
string inputfilename_local_rssilast = "/sys/devices/virtual/dnt900/ttyUSB0/0x001F5D/RSSI_Last";

string outputfilename_write_data = "orbo_communication_link_status.txt";

ifstream instream_local_cfb;
ifstream instream_local_cfd;
ifstream instream_local_crd;
ifstream instream_local_ctp;
ifstream instream_local_rl;

ofstream outstream_write_data;

for(;;)
{

instream_local_cfb.open(inputfilename_local_currfreqband.data());
instream_local_cfd.open(inputfilename_local_currrfdatarate.data());
instream_local_crd.open(inputfilename_local_currrangedelay.data());
instream_local_ctp.open(inputfilename_local_currtxpower.data());
instream_local_rl.open(inputfilename_local_rssilast.data());


char cfb_data [4];
for(int i=0;i<4;i++)
{
instream_local_cfb>>cfb_data[i];
if (instream_local_cfb.eof()) break;
}

char cfd_data [4];
for(int i=0;i<4;i++)
{
instream_local_cfd>>cfd_data[i];
if (instream_local_cfd.eof()) break;
}

char crd_data [4];
for(int i=0;i<4;i++)
{
instream_local_crd>>crd_data[i];
if (instream_local_crd.eof()) break;
}

char ctp_data [4];
for(int i=0;i<4;i++)
{
instream_local_ctp>>ctp_data[i];
if (instream_local_ctp.eof()) break;
}

char rl_data [4];
for(int i=0;i<4;i++)
{
instream_local_rl>>rl_data[i];
if (instream_local_rl.eof()) break;
}



outstream_write_data.open(outputfilename_write_data.data(),ios::app);
outstream_write_data<<endl;

outstream_write_data<<"Local Radio: Current Frequency Band: ";
for (int i=0;i<4;i++)
{
outstream_write_data<<cfb_data[i];
}
outstream_write_data<<endl;

outstream_write_data<<"Local Radio: Current RF Data Rate: ";
for (int i=0;i<4;i++)
{
outstream_write_data<<cfd_data[i];
}
outstream_write_data<<endl;

outstream_write_data<<"Local Radio: Current Range Delay: ";
for (int i=0;i<4;i++)
{
outstream_write_data<<crd_data[i];
}
outstream_write_data<<endl;

outstream_write_data<<"Local Radio: Current Transmission Power: ";
for (int i=0;i<4;i++)
{
outstream_write_data<<ctp_data[i];
}
outstream_write_data<<endl;

outstream_write_data<<"Local Radio: Last Received Signal Strength Indicator: ";

char rl_data_3[5];
for(int i=0;i<4;i++)
{
rl_data_3[i]=rl_data[i];
}
int rssi_converted_2=gethex(rl_data_3);
outstream_write_data<<rssi_converted_2;
outstream_write_data<<endl;




cout<<"Frequency Band: ";
for(int i=0;i<4;i++)
{
cout<<cfb_data[i];
}
cout<<"   ";

cout<<"Data Rate: ";
for(int i=0;i<4;i++)
{
cout<<cfd_data[i];
}
cout<<"   ";

cout<<"Tx Power: ";
for(int i=0;i<4;i++)
{
cout<<ctp_data[i];
}
cout<<"   ";

cout<<"Local RSSI: ";
char rl_data_2[5];
for(int i=0;i<4;i++)
{
rl_data_2[i]=rl_data[i];
}
int rssi_converted=gethex(rl_data_2);
cout<<rssi_converted;
cout<<"   ";


cout<<"Range Delay: ";
for(int i=0;i<4;i++)
{
cout<<crd_data[i];
}
cout<<endl;




instream_local_cfb.clear();
instream_local_cfd.clear();
instream_local_crd.clear();
instream_local_ctp.clear();
instream_local_rl.clear();

instream_local_cfb.close();
instream_local_cfd.close();
instream_local_crd.close();
instream_local_ctp.close();
instream_local_rl.close();

outstream_write_data.close();

}

}


int gethex(string hexstr)
{
return(int)strtol(hexstr.c_str(),0,16);
}



void monitor_battery_power()
{
}

void send_command()
{
}

void orbo_live()
{
}

void help()
{
cout<<"****************************************************************************************************************************************"<<endl;
cout<<"HELP"<<setw(100)<<"Get help using the orbo_gcs_1.1 software"<<endl;
cout<<"****************************************************************************************************************************************"<<endl;
cout<<endl;

cout<<setw(100)<<"orbo_gcs_1.1"<<endl;
cout<<setw(100)<<"ORBO-Unmanned Aerial Systems"<<endl;
cout<<setw(100)<<"Buoyant Aircraft Systems International"<<endl;
cout<<setw(100)<<"Author: Rafi Belal"<<endl;
cout<<setw(100)<<"Email - rafi2213@yahoo.com"<<endl;
cout<<endl<<endl;

cout<<"-----------------------------------------------------------------------------------------------------------------------------------------"<<endl;
cout<<"Press the menu keys (1-10) to operate different functions of the ground control station software.Press 0 to go back to the menu selection screen\ 
. For more information, email - rafi2213@yahoo.com and put orbo_gcs_1.1 on the subject line. "<<endl;
cout<<endl<<"Thank you for using orbo_gcs_1.1"<<endl;
cout<<"-----------------------------------------------------------------------------------------------------------------------------------------"<<endl;

for (;;)
{
cout<<"Press 0 to go back to menu selection: ";
int response_help=1;
cin>>response_help;
if(response_help==0) break;
else
{
cin.clear();
cin.ignore(10000,'\n');
}
}
}

void exit_program()
{
for(;;)
{
cout<<"Are you sure you want to quit the program? (Y/N): ";
char response_exit;
cin>>response_exit;
if (response_exit=='y')
{
exit(0);
}
else if (response_exit=='n') break;
else
{
cin.clear();
cin.ignore(10000,'\n');
}
}
}





int home_menu()
{
for(;;)
{
char my_choice;
cout << endl<<endl;
cout <<"****************************************************************************************************************************************"<<endl;
cout <<"ORBO_GCS_1.1";
cout << setw(40)<<"MAIN MENU";
cout <<setw(60)<<"BASI"<<endl;
cout <<"****************************************************************************************************************************************"<<endl;
cout <<"C";
cout <<setw(40)<<"CONNECT";
cout <<setw(60)<<"Connect to ORBO UAV"<<endl;
cout <<"M";
cout <<setw(40)<<"MONITOR ORBO";
cout <<setw(60)<<"Monitor the UAV system"<<endl;
cout <<"L";
cout <<setw(40)<<"MONITOR COMM LINK";
cout <<setw(60)<<"Monitor the wireless link"<<endl;
cout <<"B";
cout <<setw(40)<<"MONITOR BATTERY HEALTH";
cout <<setw(60)<<"Monitor the health of battery in ORBO"<<endl;
cout <<"S";
cout <<setw(40)<<"SEND COMMAND";
cout <<setw(60)<<"Send commands to ORBO UAV"<<endl;
cout <<"O";
cout <<setw(40)<<"ORBO LIVE";
cout <<setw(60)<<"Start live video transmission from UAV"<<endl;
cout <<"H";
cout <<setw(40)<<"HELP";
cout <<setw(60)<<"Get help using orbo_gcs_1.1 software"<<endl;
cout <<"Q";
cout <<setw(40)<<"QUIT";
cout <<setw(60)<<"Leave the orbo_gcs_1.1 software"<<endl;
cout<<endl<<endl;
cout<<setw(80)<<"ORBO-Unmanned Aerial Systems"<<endl;
cout<<setw(84)<<"Buoyant Aircraft System International"<<endl<<endl;
cout <<"****************************************************************************************************************************************"<<endl;
cout<<endl;
cout<<"Please enter your choice: ";
cin>>my_choice;

switch (my_choice)
{
case 'c':
return 1;
break;
case 'C':
return 1;
break;
case 'm':
return 2;
break;
case 'M':
return 2;
break;

case 'l':
return 3;
break;
case 'L':
return 3;
break;

case 'b':
return 4;
break;
case 'B':
return 4;
break;

case 's':
return 5;
break;
case 'S':
return 5;
break;

case 'o':
return 6;
break;
case 'O':
return 6;
break;

case 'h':
return 7;
break;
case 'H':
return 7;
break;

case 'q':
return 8;
break;
case 'Q':
return 8;
break;

default:
cout<<"ERROR! Please enter a valid menu choice"<<endl;
cin.clear();
cin.ignore(10000,'\n');
}
}
}




int main()
{
for(;;)
{
int my_menu_choice=0;
my_menu_choice=home_menu();
switch (my_menu_choice)
{
case 1:
{
connect();
run_ldattach();
send_connection_request();
receive_connection_acknowledgement();
}
break;
case 2:
{
monitor_orbo();
send_data_request();
int return_data;
return_data=receive_data_acknowledgement();
if(return_data==0) break;
send_cts();
output_data();
}
break;
case 3:
{
monitor_comm_link();
send_comm_link_request();
int return_data;
return_data=receive_comm_link_acknowledgement();
if(return_data==0) break;
output_comm_link_data();
}
break;
case 4:
{
monitor_battery_power();
}
break;
case 5:
{
send_command();
}
break;
case 6:
{
orbo_live();
}
break;
case 7:
{
help();
}
break;
case 8:
{
exit_program();
}
break;
default:
cout<<"Please enter a valid menu selection"<<endl;
}
}
return 0;
}



