From 8c8cbcfdac3bbe248bd4389815f2d12b49f37126 Mon Sep 17 00:00:00 2001
From: Kris Burney <burneykb@iastate.edu>
Date: Fri, 28 Oct 2016 22:36:11 -0500
Subject: [PATCH] Fixed select and formatCommand bugs

---
 groundStation/src/commands.c      | 625 +++++++++++++++++++++++++++---
 groundStation/src/commands.h      |  94 ++---
 groundStation/src/communication.c | 143 ++++---
 groundStation/src/communication.h |   8 +-
 groundStation/src/microcart_cli.c | 121 +++---
 5 files changed, 750 insertions(+), 241 deletions(-)

diff --git a/groundStation/src/commands.c b/groundStation/src/commands.c
index dc4749ee..cdbbbe8a 100644
--- a/groundStation/src/commands.c
+++ b/groundStation/src/commands.c
@@ -1,109 +1,624 @@
 #include "commands.h"
 
-static command_t registeredCommands[NUM_COMMANDS] = {
-	{ 0x00, 0x00, stringType, "debug", 			&debug },				//DEBUG
-	{ 0x01, 0x00, stringType, "setyaw", 		&setyaw },				//CALIBRATION
-	{ 0x01, 0x01, stringType, "setyawp", 		&setyawp },
-	{ 0x01, 0x02, stringType, "setyawd", 		&setyawd },
-	{ 0x01, 0x03, stringType, "setroll", 		&setroll },
-	{ 0x01, 0x04, stringType, "setrollp", 		&setrollp },
-	{ 0x01, 0x05, stringType, "setrolld", 		&setrolld },
-	{ 0x01, 0x06, stringType, "setpitch", 		&setpitch },
-	{ 0x01, 0x07, stringType, "setpitchp",		&setpitchp },
-	{ 0x01, 0x08, stringType, "setpitchd", 		&setpitchd },
-	{ 0x01, 0x09, stringType, "setthrottle", 	&setthrottle },
-	{ 0x01, 0x0A, stringType, "setthrottlep", 	&setthrottlep },
-	{ 0x01, 0x0B, stringType, "setthrottlei", 	&setthrottlei },
-	{ 0x01, 0x0C, stringType, "setthrottled", 	&setthrottled },
-	{ 0x02, 0x00, stringType, "getaccel", 		&getaccel },			//REQUEST
-	{ 0x02, 0x01, stringType, "getgyro", 		&getgyro },
-	{ 0x02, 0x02, stringType, "getpitchangle", 	&getpitchangle },
-	{ 0x02, 0x03, stringType, "getrollangle", 	&getrollangle },
-	{ 0x03, 0x00, stringType, "accelresp",		accelresp },			//RESPONSE
-	{ 0x03, 0x01, stringType, "gyroresp",   	&gyroresp },
-	{ 0x03, 0x02, stringType, "pitchangleresp", &pitchangleresp },
-	{ 0x03, 0x03, stringType, "rollangleresp", 	&rollangleresp },
-	{ 0x04, 0x00, stringType, "update", 		&update },				//UPDATE
-	{ 0x04, 0x01, stringType, "beginupdate", 	&beginupdate },
-	{ 0x05, 0x00, stringType, "log", 			&logdata },				//LOG
-	{ 0x05, 0x01, stringType, "response", 		&response },
-};
+// TAKE THESE OUT WHEN IMPLEMENTING ON THE QUAD SIDE
+float getFloat(unsigned char* str, int pos) {
+	union {
+		float f;
+		int i;
+	} x;
+	x.i = ((str[pos+3] << 24) | (str[pos+2] << 16) | (str[pos+1] << 8) | (str[pos]));
+	return x.f;
+}
 
-int debug(unsigned char *c, int dataLen){
-	return 0;
+int getInt(unsigned char* str, int pos) {
+	int i = ((str[pos+3] << 24) | (str[pos+2] << 16) | (str[pos+1] << 8) | (str[pos]));
+	return i;
 }
-int setyaw(unsigned char *c, int dataLen){
+//------------------------------------------------
+
+struct MessageType MessageTypes[MAX_TYPE] = 
+{
+	// DEBUG
+	{
+		// Message Type ID
+		0x00,
+		
+		// Debug Subtypes
+		{
+			// NONE subtype
+			{
+				// ID
+				0x00,
+				// Command text
+				"debug",
+				// Type of the command data
+				stringType,
+				// Function pointer
+				&debug
+			}
+		}
+	},
+	
+	// CALIBRATION
+	{
+		// Message Type ID
+		0x01,
+		
+		// Calibration Subtypes
+		{
+			// yaw setpoint subtype
+			{
+				// ID
+				0x00,
+				// Command text
+				"setyaw",
+				// Type of the command data
+				floatType,
+				// Function pointer
+				&yawset
+			},
+			// yaw p constant subtype
+			{
+				// ID
+				0x01,
+				// Command text
+				"setyawp",
+				// Type of the command data
+				floatType,
+				// Function pointer
+				&yawp
+			},
+			// yaw d constant subtype
+			{
+				// ID
+				0x02,
+				// Command text
+				"setyawd",
+				// Type of the command data
+				floatType,
+				// Function pointer
+				&yawd
+			},
+			// roll setpoint subtype
+			{
+				// ID
+				0x03,
+				// Command text
+				"setroll",
+				// Type of the command data
+				floatType,
+				// Function pointer
+				&rollset
+			},
+			// roll p constant subtype
+			{
+				// ID
+				0x04,
+				// Command text
+				"setrollp",
+				// Type of the command data
+				floatType,
+				// Function pointer
+				&rollp
+			},
+			// roll d constant subtype
+			{
+				// ID
+				0x05,
+				// Command text
+				"setrolld",
+				// Type of the command data
+				floatType,
+				// Function pointer
+				&rolld
+			},
+			// pitch setpoint subtype
+			{
+				// ID
+				0x06,
+				// Command text
+				"setpitch",
+				// Type of the command data
+				floatType,
+				// Function pointer
+				&pitchset
+			},
+			// pitch p constant subtype
+			{
+				// ID
+				0x07,
+				// Command text
+				"setpitchp",
+				// Type of the command data
+				floatType,
+				// Function pointer
+				&pitchp
+			},
+			// pitch d constant subtype
+			{
+				// ID
+				0x08,
+				// Command text
+				"setpitchd",
+				// Type of the command data
+				floatType,
+				// Function pointer
+				&pitchd
+			},
+			// throttle setpoint subtype
+			{
+				// ID
+				0x09,
+				// Command text
+				"setthrottle",
+				// Type of the command data
+				floatType,
+				// Function pointer
+				&throttleset
+			},
+			// throttle p constant subtype
+			{
+				// ID
+				0x0A,
+				// Command text
+				"setthrottlep",
+				// Type of the command data
+				floatType,
+				// Function pointer
+				&throttlep
+			},
+			// throttle i constant subtype
+			{
+				// ID
+				0x0B,
+				// Command text
+				"setthrottlei",
+				// Type of the command data
+				floatType,
+				// Function pointer
+				&throttlei
+			},
+			// throttle d constant subtype
+			{
+				// ID
+				0x0C,
+				// Command text
+				"setthrottled",
+				// Type of the command data
+				floatType,
+				// Function pointer
+				&throttled
+			}
+		}
+	},
+	
+	// REQUEST
+	{
+		// Message Type ID
+		0x02,
+		
+		// Request Subtypes
+		{
+			// accelerometer subtype
+			{
+				// ID 
+				0x00,
+				// Command text
+				"accelreq",
+				// Type of the command data
+				floatType,
+				// Function pointer
+				&accelreq
+			},
+			// gyroscope subtype
+			{
+				// ID 
+				0x01,
+				// Command text
+				"gyroreq",
+				// Type of the command data
+				floatType,
+				// Function pointer
+				&gyroreq
+			},
+			// pitch angle subtype
+			{
+				// ID 
+				0x02,
+				// Command text
+				"reqpitchangle",
+				// Type of the command data
+				floatType,
+				// Function pointer
+				&pitchanglereq
+			},
+			// roll angle subtype
+			{
+				// ID 
+				0x03,
+				// Command text
+				"reqrollangle",
+				// Type of the command data
+				floatType,
+				// Function pointer
+				&rollanglereq
+			}
+		}
+	},
+	
+	// RESPONSE
+	{
+		// Message Type ID
+		0x03,
+		
+		// Response Subtypes
+		{
+			// accelerometer subtype
+			{
+				// ID
+				0x00,
+				// Command text
+				"respaccel",
+				// Type of the command data
+				floatType,
+				// Function pointer
+				&accelresp
+			},
+			// gyroscope subtype
+			{
+				// ID
+				0x01,
+				// Command text
+				"respgyro",
+				// Type of the command data
+				floatType,
+				// Function pointer
+				&gyroresp
+			},
+			// pitch angle subtype
+			{
+				// ID 
+				0x02,
+				// Command text
+				"resppitchangle",
+				// Type of the command data
+				floatType,
+				// Function pointer
+				&pitchangleresp
+			},
+			// roll angle subtype
+			{
+				// ID 
+				0x03,
+				// Command text
+				"resprollangle",
+				// Type of the command data
+				floatType,
+				// Function pointer
+				&rollangleresp
+			}
+		}
+	},
+	
+	// UPDATE
+	{
+		// Message Type ID
+		0x04,
+		
+		// Update Subtypes
+		{
+			// NONE subtype
+			{
+				// ID 
+				0x00,
+				// Command text
+				"update",
+				// Type of the command data
+				stringType,
+				// Function pointer
+				&update
+			}
+		}
+	},
+	
+	// LOG
+	{
+		// Message Type ID
+		0x05,
+		
+		// Log Subtypes
+		{
+			// NONE subtype
+			{
+				// ID
+				0x00,
+				// Command text
+				"log",
+				// Type of the command data
+				stringType,
+				// Function pointer
+				&logdata
+			},
+			// Response subtype
+			{
+				// ID
+				0x01,
+				// Command text
+				"response",
+				// Type of the command data
+				stringType,
+				// Function pointer
+				&response
+			}
+		}
+	},
+	
+};
+
+int debug(unsigned char *packet, int dataLen, modular_structs_t *structs)
+{
+	printf("function for debug\n");
 	return 0;
 }
-int setyawp(unsigned char *c, int dataLen){
+
+int update(unsigned char *packet, int dataLen,	modular_structs_t *structs)
+{
+	unsigned char update[28];
+	memcpy(update, ((float *)packet), 28);
+	
+	int packetId = getInt(update, 0);
+	float y_pos = getFloat(update, 4);
+	float x_pos = getFloat(update, 8);
+	float alt_pos = getFloat(update, 12);
+	float roll = getFloat(update, 16);
+	float pitch = getFloat(update, 20);
+	float yaw = getFloat(update, 24);
+
+	structs->log_struct.currentQuadPosition.packetId = packetId;
+	structs->log_struct.currentQuadPosition.y_pos = y_pos;
+	structs->log_struct.currentQuadPosition.x_pos = x_pos;
+	structs->log_struct.currentQuadPosition.alt_pos = alt_pos;
+	structs->log_struct.currentQuadPosition.roll = roll;
+	structs->log_struct.currentQuadPosition.pitch = pitch;
+	structs->log_struct.currentQuadPosition.yaw = yaw;
+	
+	printf("QUAD: VRPN Packet:");
+	printf("Packet ID: %d\n", packetId);
+	printf("Y Position: %f\n", y_pos);
+	printf("X Position: %f\n", x_pos);
+	printf("Altitude Position: %f\n", alt_pos);
+	printf("Roll: %f\n", roll);
+	printf("Pitch: %f\n", pitch);
+	printf("Yaw: %f\n", yaw);
+	
+	printf("function for update\n");
 	return 0;
 }
-int setyawd(unsigned char *c, int dataLen){
+
+// Why is this here?
+// This should be on the ground station side
+int logdata(unsigned char *packet, int dataLen, modular_structs_t *structs)
+{
+	printf("Logging: %s\n", packet);
 	return 0;
 }
-int setroll(unsigned char *c, int dataLen){
+
+int response(unsigned char *packet, int dataLen, modular_structs_t *structs)
+{
+	printf("This is the response: %s\n", packet);
+	
 	return 0;
 }
-int setrollp(unsigned char *c, int dataLen){
+
+// ------------------------------------------------------------------
+
+int yawset(unsigned char *packet, int dataLen, modular_structs_t *structs)
+{
+	float value;
+	
+	memcpy(&value, ((float *)packet), dataLen);
+	
+	printf("%f\n", value);
+	
+	structs->setpoint_struct.desiredQuadPosition.yaw = value;
+
+	printf("function for yawset: %f\n", structs->setpoint_struct.desiredQuadPosition.yaw);
+	
 	return 0;
 }
-int setrolld(unsigned char *c, int dataLen){
+
+int yawp(unsigned char *packet, int dataLen,  modular_structs_t *structs)
+{
+	float value;
+	
+	memcpy(&value, ((float *)packet), dataLen);
+	structs->parameter_struct.yaw_angle_pid.Kp = value;
+	
+	printf("function for yawp: %f\n", structs->parameter_struct.yaw_angle_pid.Kp);
+	
 	return 0;
 }
-int setpitch(unsigned char *c, int dataLen){
+
+int yawd(unsigned char *packet, int dataLen,  modular_structs_t *structs)
+{
+	float value;
+	
+	memcpy(&value, ((float *)packet), dataLen);
+	structs->parameter_struct.yaw_angle_pid.Kd = value;
+	
+	printf("function for yawd: %f\n", structs->parameter_struct.yaw_angle_pid.Kd);
+	
 	return 0;
 }
-int setpitchp(unsigned char *c, int dataLen){
+
+int rollset(unsigned char *packet, int dataLen,	 modular_structs_t *structs)
+{
+	float value;
+	
+	memcpy(&value, ((float *)packet), dataLen);
+	structs->setpoint_struct.desiredQuadPosition.roll = value;
+	
+	printf("function for rollset: %f\n", structs->setpoint_struct.desiredQuadPosition.roll);
+	
 	return 0;
 }
-int setpitchd(unsigned char *c, int dataLen){
+
+int rollp(unsigned char *packet, int dataLen,  modular_structs_t *structs)
+{
+	float value;
+	
+	memcpy(&value, ((float *)packet), dataLen);
+	structs->parameter_struct.local_y_pid.Kp = value;
+	
+	printf("function for rollp: %f\n", structs->parameter_struct.local_y_pid.Kp);
+	
 	return 0;
 }
-int setthrottle(unsigned char *c, int dataLen){
+
+int rolld(unsigned char *packet, int dataLen,  modular_structs_t *structs)
+{
+	float value;
+	
+	memcpy(&value, ((float *)packet), dataLen);
+	structs->parameter_struct.local_y_pid.Kd = value;
+	
+	printf("function for rolld: %f\n", structs->parameter_struct.local_y_pid.Kd);
+	
 	return 0;
 }
-int setthrottlep(unsigned char *c, int dataLen){
+
+int pitchset(unsigned char *packet, int dataLen,  modular_structs_t *structs)
+{
+	float value;
+	
+	memcpy(&value, ((float *)packet), dataLen);
+	structs->setpoint_struct.desiredQuadPosition.pitch = value;
+	
+	printf("function for pitchset: %f\n", structs->setpoint_struct.desiredQuadPosition.pitch);
+	
 	return 0;
 }
-int setthrottlei(unsigned char *c, int dataLen){
+
+int pitchp(unsigned char *packet, int dataLen,	modular_structs_t *structs)
+{
+	float value;
+	
+	memcpy(&value, ((float *)packet), dataLen);
+	structs->parameter_struct.local_x_pid.Kp = value;
+	
+	printf("function for pitchp: %f\n", structs->parameter_struct.local_x_pid.Kp);
+	
 	return 0;
 }
-int setthrottled(unsigned char *c, int dataLen){
+
+int pitchd(unsigned char *packet, int dataLen,	modular_structs_t *structs)
+{
+	float value;
+	
+	memcpy(&value, ((float *)packet), dataLen);
+	structs->parameter_struct.local_x_pid.Kd = value;
+	
+	printf("function for pitchd: %f\n", structs->parameter_struct.local_x_pid.Kd);
+	
 	return 0;
 }
-int getaccel(unsigned char *c, int dataLen){
+
+// ------------------------------------------------------------
+// These should be renamed to altitude!
+int throttleset(unsigned char *packet, int dataLen,	 modular_structs_t *structs)
+{
+	float value;
+	
+	memcpy(&value, ((float *)packet), dataLen);
+	structs->setpoint_struct.desiredQuadPosition.alt_pos = value;
+	
+	printf("function for throttleset: %f\n", structs->setpoint_struct.desiredQuadPosition.alt_pos);
+	
 	return 0;
 }
-int getgyro(unsigned char *c, int dataLen){
+
+int throttlep(unsigned char *packet, int dataLen,  modular_structs_t *structs)
+{
+	float value;
+	
+	memcpy(&value, ((float *)packet), dataLen);
+	structs->parameter_struct.alt_pid.Kp = value;
+	
+	printf("function for throttlep: %f\n", structs->parameter_struct.alt_pid.Kp);
+	
 	return 0;
 }
-int getpitchangle(unsigned char *c, int dataLen){
+
+int throttlei(unsigned char *packet, int dataLen,  modular_structs_t *structs)
+{
+	float value;
+	
+	memcpy(&value, ((float *)packet), dataLen);
+	structs->parameter_struct.alt_pid.Ki = value;
+	
+	printf("function for throttlei: %f\n", structs->parameter_struct.alt_pid.Ki);
+	
 	return 0;
 }
-int getrollangle(unsigned char *c, int dataLen){
+
+int throttled(unsigned char *packet, int dataLen,  modular_structs_t *structs)
+{
+	float value;
+	
+	memcpy(&value, ((float *)packet), dataLen);
+	structs->parameter_struct.alt_pid.Kd = value;
+	
+	printf("function for throttled: %f\n", structs->parameter_struct.alt_pid.Kd);
+	
 	return 0;
 }
-int accelresp(unsigned char *c, int dataLen){
+// These should be renamed to altitude!
+// ------------------------------------------------------------
+
+int accelreq(unsigned char *packet, int dataLen,  modular_structs_t *structs)
+{
+	printf("function for accelreq\n");
 	return 0;
 }
-int gyroresp(unsigned char *c, int dataLen){
+
+int gyroresp(unsigned char *packet, int dataLen,  modular_structs_t *structs)
+{
+	printf("function for accelreq\n");
 	return 0;
 }
-int pitchangleresp(unsigned char *c, int dataLen){
+
+int pitchangleresp(unsigned char *packet, int dataLen,	modular_structs_t *structs)
+{
+	printf("function for accelreq\n");
 	return 0;
 }
-int rollangleresp(unsigned char *c, int dataLen){
+
+int rollangleresp(unsigned char *packet, int dataLen,  modular_structs_t *structs)
+{
+	printf("function for accelreq\n");
 	return 0;
 }
-int update(unsigned char *c, int dataLen){
+
+int gyroreq(unsigned char *packet, int dataLen,	 modular_structs_t *structs)
+{
+	printf("function for accelreq\n");
 	return 0;
 }
-int beginupdate(unsigned char *c, int dataLen){
+
+int pitchanglereq(unsigned char *packet, int dataLen,  modular_structs_t *structs)
+{
+	printf("function for accelreq\n");
 	return 0;
 }
-int logdata(unsigned char *c, int dataLen){
+
+int rollanglereq(unsigned char *packet, int dataLen,  modular_structs_t *structs)
+{
+	printf("function for accelreq\n");
 	return 0;
 }
-int response(unsigned char *packet, int dataLen){
+
+int accelresp(unsigned char *packet, int dataLen,  modular_structs_t *structs)
+{
+	printf("function for accelreq\n");
 	return 0;
 }
\ No newline at end of file
diff --git a/groundStation/src/commands.h b/groundStation/src/commands.h
index 050990de..51c82bd7 100644
--- a/groundStation/src/commands.h
+++ b/groundStation/src/commands.h
@@ -1,44 +1,24 @@
 #ifndef _COMMANDS_H
 #define _COMMANDS_H
 
-#define NUM_COMMANDS 26
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "type_def.h"
+
+
+// ----------------------
+// Helper stuff
 
-//TODO handle with enums
 #define MAX_TYPE 6
 #define MAX_SUBTYPE 100
 
-int debug(unsigned char *c, int dataLen);
-int setyaw(unsigned char *c, int dataLen);
-int setyawp(unsigned char *c, int dataLen);
-int setyawd(unsigned char *c, int dataLen);
-int setroll(unsigned char *c, int dataLen);
-int setrollp(unsigned char *c, int dataLen);
-int setrolld(unsigned char *c, int dataLen);
-int setpitch(unsigned char *c, int dataLen);
-int setpitchp(unsigned char *c, int dataLen);
-int setpitchd(unsigned char *c, int dataLen);
-int setthrottle(unsigned char *c, int dataLen);
-int setthrottlep(unsigned char *c, int dataLen);
-int setthrottlei(unsigned char *c, int dataLen);
-int setthrottled(unsigned char *c, int dataLen);
-int getaccel(unsigned char *c, int dataLen);
-int getgyro(unsigned char *c, int dataLen);
-int getpitchangle(unsigned char *c, int dataLen);
-int getrollangle(unsigned char *c, int dataLen);
-int accelresp(unsigned char *c, int dataLen);
-int gyroresp(unsigned char *c, int dataLen);
-int pitchangleresp(unsigned char *c, int dataLen);
-int rollangleresp(unsigned char *c, int dataLen);
-int update(unsigned char *c, int dataLen);
-int beginupdate(unsigned char *c, int dataLen);
-int logdata(unsigned char *c, int dataLen);
-int response(unsigned char *packet, int dataLen);
-
 enum Message{
 	BEGIN_CHAR = 0xBE,
 	END_CHAR   = 0xED
 };
 
+// This should also have double to avoid confusion with float values.
 enum DataType
 {
 	floatType,
@@ -46,24 +26,50 @@ enum DataType
 	stringType
 };
 
-typedef struct command {
+// MESSAGE SUBTYPES
+struct MessageSubtype{
 	char ID;
-	char subID;
-	char dataType;
-	char commandText[100];
-	int (*functionPtr)(unsigned char *command, int dataLen);
-}command_t;
+	char cmdText[100];
+	char cmdDataType;
+	int (*functionPtr)(unsigned char *command, int dataLen, modular_structs_t *structs);
+};
 
-enum CommandIDs{
-	DEBUG,
-	CALIBRATION,
-	REQUEST,
-	RESPONSE,
-	UPDATE,
-	LOG,
-	MAX_COMMAND_IDS
+// MESSAGE TYPES
+struct MessageType{
+	char ID;
+	struct MessageSubtype subtypes[MAX_SUBTYPE];
 };
 
-static command_t registeredCommands[NUM_COMMANDS];
+int debug(unsigned char *c, int dataLen, modular_structs_t *structs);
+int update(unsigned char *c, int dataLen, modular_structs_t *structs);
+int logdata(unsigned char *c, int dataLen, modular_structs_t *structs);
+int response(unsigned char *packet, int dataLen, modular_structs_t *structs);
+int yawset(unsigned char *c, int dataLen, modular_structs_t *structs);
+int yawp(unsigned char *c, int dataLen, modular_structs_t *structs);
+int yawd(unsigned char *c, int dataLen, modular_structs_t *structs);
+int rollset(unsigned char *c, int dataLen, modular_structs_t *structs);
+int rollp(unsigned char *c, int dataLen, modular_structs_t *structs);
+int rolld(unsigned char *c, int dataLen, modular_structs_t *structs);
+int pitchset(unsigned char *c, int dataLen, modular_structs_t *structs);
+int pitchp(unsigned char *c, int dataLen, modular_structs_t *structs);
+int pitchd(unsigned char *c, int dataLen, modular_structs_t *structs);
+int throttleset(unsigned char *c, int dataLen, modular_structs_t *structs);
+int throttlep(unsigned char *c, int dataLen, modular_structs_t *structs);
+int throttlei(unsigned char *c, int dataLen, modular_structs_t *structs);
+int throttled(unsigned char *c, int dataLen, modular_structs_t *structs);
+int accelreq(unsigned char *c, int dataLen, modular_structs_t *structs);
+int gyroresp(unsigned char *c, int dataLen, modular_structs_t *structs);
+int pitchangleresp(unsigned char *c, int dataLen, modular_structs_t *structs);
+int rollangleresp(unsigned char *c, int dataLen, modular_structs_t *structs);
+int gyroreq(unsigned char *c, int dataLen, modular_structs_t *structs);
+int pitchanglereq(unsigned char *c, int dataLen, modular_structs_t *structs);
+int rollanglereq(unsigned char *c, int dataLen, modular_structs_t *structs);
+int accelresp(unsigned char *c, int dataLen, modular_structs_t *structs);
+
+float getFloat(unsigned char* str, int pos);
+int getInt(unsigned char* str, int pos);
+
+// TODO add in string to be read from the command line when sending a subtype of message
+extern struct MessageType MessageTypes[MAX_TYPE];
 
 #endif
\ No newline at end of file
diff --git a/groundStation/src/communication.c b/groundStation/src/communication.c
index f9d35792..77202ed4 100644
--- a/groundStation/src/communication.c
+++ b/groundStation/src/communication.c
@@ -52,10 +52,13 @@ int checkInt(char *intString, int *value) {
 //--------------------------------
 
 // Formatting commands from ground station CLI
-int formatCommand(unsigned char *command, unsigned char **formattedCommand) {
-	//command[strlen((char *)command) - 1] = 0;
-	
-	tokenList_t tokens = tokenize((char *)command);
+int formatCommand(char *command, unsigned char **formattedCommand) {
+	fprintf(stderr, "length = %li , received '%s'\n", strlen(command), command);
+	char cmd[strlen(command)];
+	strncpy(cmd, command, strlen(command));
+	cmd[strlen(command)] = '\0';
+
+	tokenList_t tokens = tokenize(cmd);
 	float floatValue = 0.0;
 	int intValue = 0;
 	int valid;
@@ -63,72 +66,76 @@ int formatCommand(unsigned char *command, unsigned char **formattedCommand) {
 	
 	// ----------------------------------------------
 	if(tokens.numTokens > 1) {
-		for(int cmdIndex = 0; cmdIndex < NUM_COMMANDS; ++cmdIndex)
+		for(int type = 0; type < MAX_TYPE; type++)
 		{
-			if(strcmp(tokens.tokens[0], registeredCommands[cmdIndex].commandText) == 0)
+			for(int subtype = 0; subtype < MAX_SUBTYPE; subtype++)
 			{
-				switch (registeredCommands[cmdIndex].dataType)
+				if(strcmp(tokens.tokens[0], MessageTypes[type].subtypes[subtype].cmdText) == 0)
 				{
-					// Validate the float input
-					case floatType:
-						valid = checkFloat(tokens.tokens[1], &floatValue);
-						if(!valid) {
-							return -1;
-						}
-						
-						printf("%f, %s\n", floatValue, tokens.tokens[1]);
-						
-						metadata.begin_char  = (char) BEGIN_CHAR;
-						metadata.msg_type    = registeredCommands[cmdIndex].ID;
-						metadata.msg_subtype = registeredCommands[cmdIndex].subID;
-						metadata.msg_id      = msgNum++;
-						metadata.data_len    = sizeof(floatValue);
-						
-						formatPacket(&metadata, &floatValue, formattedCommand);
-						
-						break;
-					
-					// Validate the integer input
-					case intType:
-						valid = checkInt(tokens.tokens[1], &intValue);
-						if(!valid) {
-							return -1;
-						}
-						
-						metadata.begin_char  = (char) BEGIN_CHAR;
-						metadata.msg_type    = registeredCommands[cmdIndex].ID;
-						metadata.msg_subtype = registeredCommands[cmdIndex].subID;
-						metadata.msg_id      = msgNum++;
-						metadata.data_len    = sizeof(intValue);
-						
-						formatPacket(&metadata, &intValue, formattedCommand);
-						
-						break;
+					printf("Sending\n\ttype: %d, \n\tsubtype: %d\n\tcommand: %s\n", type, subtype, MessageTypes[type].subtypes[subtype].cmdText);
 					
-					// Validate the string input (doesn't need to happen)
-					case stringType:
-						metadata.begin_char  = (char) BEGIN_CHAR;
-						metadata.msg_type    = registeredCommands[cmdIndex].ID;
-						metadata.msg_subtype = registeredCommands[cmdIndex].subID;
-						metadata.msg_id      = msgNum++;
-						metadata.data_len    = strlen(tokens.tokens[1]);
+					// Make sure the second token is the right type
+					switch (MessageTypes[type].subtypes[subtype].cmdDataType)
+					{
+						// Validate the float input
+						case floatType:
+							valid = checkFloat(tokens.tokens[1], &floatValue);
+							if(!valid) {
+								return -1;
+							}
+							
+							printf("%f, %s\n", floatValue, tokens.tokens[1]);
+							
+							metadata.begin_char = (char) BEGIN_CHAR;
+							metadata.msg_type = MessageTypes[type].ID;
+							metadata.msg_subtype = MessageTypes[type].subtypes[subtype].ID;
+							metadata.msg_id = msgNum++;
+							metadata.data_len = sizeof(floatValue);
+							
+							formatPacket(&metadata, &floatValue, formattedCommand);
+							
+							break;
 						
-						formatPacket(&metadata, &tokens.tokens[1], formattedCommand);
+						// Validate the integer input
+						case intType:
+							valid = checkInt(tokens.tokens[1], &intValue);
+							if(!valid) {
+								return -1;
+							}
+							
+							metadata.begin_char = (char) BEGIN_CHAR;
+							metadata.msg_type = MessageTypes[type].ID;
+							metadata.msg_subtype = MessageTypes[type].subtypes[subtype].ID;
+							metadata.msg_id = msgNum++;
+							metadata.data_len = sizeof(intValue);
+							
+							formatPacket(&metadata, &intValue, formattedCommand);
+							
+							break;
 						
-						break;
-					default:
-						return -1;
+						// Validate the string input (doesn't need to happen)
+						case stringType:
+							metadata.begin_char = (char) BEGIN_CHAR;
+							metadata.msg_type = MessageTypes[type].ID;
+							metadata.msg_subtype = MessageTypes[type].subtypes[subtype].ID;
+							metadata.msg_id = msgNum++;
+							metadata.data_len = strlen(tokens.tokens[1]);
+							
+							formatPacket(&metadata, &tokens.tokens[1], formattedCommand);
+							
+							break;
+						default:
+							return -1;
+					}
+					return 0;
 				}
-
-				return 0;
 			}
 		}
 	}
-	
+
 	// Only gets here if the command does not exist
-	return -1;
+	return -1;	
 }
-
 // QUAD & Ground Station
 // Format the log data from log_message
 //int formatData(unsigned char *log_msg, unsigned char *formattedCommand)
@@ -231,7 +238,7 @@ int parse_packet(unsigned char * packet, unsigned char ** data, metadata_t * met
 
 // QUAD & Ground Station
 // Process the command received
-int processCommand(unsigned char *packet, unsigned int cmdIndex) {
+int processCommand(unsigned char *packet, modular_structs_t *structs) {
 	int validPacket;
 	unsigned char *data;
 	metadata_t metadata;
@@ -244,25 +251,11 @@ int processCommand(unsigned char *packet, unsigned int cmdIndex) {
 	
 	if(metadata.data_len >= 0) {
 		// Call the appropriate subtype function
-		(* (registeredCommands[cmdIndex].functionPtr))(data, metadata.data_len);
+		(* (MessageTypes[(unsigned char)metadata.msg_type].subtypes[(unsigned char)metadata.msg_subtype].functionPtr))(data, metadata.data_len, structs);
 		
 		return 0;
 	}
 	
 	// Only gets here if there is an error
 	return -1;
-}
-
-float getFloat(unsigned char* str, int pos) {
-	union {
-		float f;
-		int i;
-	} x;
-	x.i = ((str[pos+3] << 24) | (str[pos+2] << 16) | (str[pos+1] << 8) | (str[pos]));
-	return x.f;
-}
-
-int getInt(unsigned char* str, int pos) {
-	int i = ((str[pos+3] << 24) | (str[pos+2] << 16) | (str[pos+1] << 8) | (str[pos]));
-	return i;
-}
+}
\ No newline at end of file
diff --git a/groundStation/src/communication.h b/groundStation/src/communication.h
index 94a3c33c..746b9f5d 100644
--- a/groundStation/src/communication.h
+++ b/groundStation/src/communication.h
@@ -10,12 +10,10 @@
 tokenList_t tokenize(char* cmd);
 int checkFloat(char *floatString, float *value);
 int checkInt(char *intString, int *value);
-int formatCommand(unsigned char *command, unsigned char **formattedCommand);
+int formatCommand(char *command, unsigned char **formattedCommand);
 int formatPacket(metadata_t *metadata, void *data, unsigned char **formattedCommand);
 int parse_packet(unsigned char * packet, unsigned char ** data, metadata_t * meta_data);
-int processCommand(unsigned char *command, unsigned int cmdIndex);
+int processCommand(unsigned char *command, modular_structs_t *structs);
 int logData(unsigned char *log_msg, unsigned char *formattedCommand);
-float getFloat(unsigned char* str, int pos);
-int getInt(unsigned char* str, int pos);
 
-#endif
+#endif
\ No newline at end of file
diff --git a/groundStation/src/microcart_cli.c b/groundStation/src/microcart_cli.c
index 7589cdb2..a439a897 100644
--- a/groundStation/src/microcart_cli.c
+++ b/groundStation/src/microcart_cli.c
@@ -1,4 +1,4 @@
-/* Author: Kris Burney
+/* Author: Kris Burney & Jake Drahos
  *
  * BlueTooth socket program for passing vrpn data to quad.
  */
@@ -39,10 +39,6 @@ void sendStartPacket(void);
 void getVRPNPacket(struct ucart_vrpn_TrackerData *);
 void printVrpnData(struct ucart_vrpn_TrackerData *);
 int connectToZybo();
-// void *handleQuadResponse();
-// void *handleCliInput();
-// int atomic_check(int*, pthread_mutex_t*);
-void performCommand(char *, char *);
 int startsWith(const char *, const char *);
 int safe_fd_set(int , fd_set* , int* );
 int safe_fd_clr(int , fd_set* , int* );
@@ -58,6 +54,8 @@ static char * get_client_buffer(int fd);
 static int remove_client(int fd);
 /* Receive data from client */
 static void client_recv(int fd);
+/* Checks to see if socket has disconnected. Returns 1 on disconnect, else returns 0 */
+static int wasDisconnected(int fd);
 
 /* Thread-safe wrappers */
 pthread_mutex_t quadSocketMutex;
@@ -75,6 +73,8 @@ const char *logHeader = "";//"#\n#\tDefault log header\n#\tEverything after '#'`
 #define CLIENT_BUFFER_SIZE 1024
 static char client_buffers[MAX_CLIENTS][CLIENT_BUFFER_SIZE];
 static int client_fds[MAX_CLIENTS];
+fd_set rfds_master;
+int max_fd = 0;
 
 pthread_mutex_t quadResponseMutex, cliInputMutex ;
 unsigned char *respBuf, *commandBuf;
@@ -109,10 +109,7 @@ static void cb(struct ucart_vrpn_TrackerData * td)
 
 int main(int argc, char **argv)
 {
-	// pthread_t quadResponse, cliInput;
-	fd_set rfds_master;
 	int activity;
-	int max_fd = 0;
 	FD_ZERO(&rfds_master);
 
 	/* 
@@ -156,7 +153,7 @@ int main(int argc, char **argv)
 		client_buffers[i][0] = '\n';
 	}
 
-	signal(SIGINT, killHandler);
+	//signal(SIGINT, killHandler);
 
 	if (pthread_mutex_lock(&quadSocketMutex)) {
 		err(-2, "pthrtead_mutex_lock (%s:%d):", __FILE__, __LINE__);
@@ -201,7 +198,7 @@ int main(int argc, char **argv)
 	// ucart_vrpn_tracker_addCallback(tracker, cb);
 
 	// start the prompt
-	fprintf(stdout, "$microcart> ");
+	// fprintf(stdout, "$microcart> ");
 
 	struct timeval timeout = {
 		.tv_sec = 1,
@@ -218,35 +215,35 @@ int main(int argc, char **argv)
 			fprintf(stderr, "Select activity = %d\n", activity);
 			for(int fd = 0; fd <= max_fd; ++fd) {
 				if (FD_ISSET(fd, &rfds)) {
-					fprintf(stderr, "Select woke for fd %d\n", fd);
-					if (fd == fileno(stdin)) {
-						unsigned char userCommand[CMD_MAX_LENGTH];
-						read(fileno(stdin), (char *)userCommand, sizeof(userCommand));
-						unsigned int cmdLen = strlen((char*) userCommand);
-						// if the user simply hit enter then let them try again
-						if((userCommand[0] != '\n') && (userCommand[0] != '\r'))
-						{
-							// remove newline and return line chars
-							if((userCommand[cmdLen - 1] == '\n') || (userCommand[cmdLen - 1] == '\r'))
-							userCommand[cmdLen - 1] = '\0';
-
-							unsigned char *packet;
-							formatCommand(userCommand, &packet);
-
-							printf("received input from cli: '%s'\n", userCommand);
-
-							fprintf(stdout, "CLI sees as: %f\n", getFloat(packet, 7));
-
-							// Write the command to the control_loop socket
-							// int n = writeQuad(packet, ((packet[6] << 8) | packet[5]) + 8);
-							// if(n < 0) {
-							// 	fprintf(stdout, "CLI: ERROR writing to socket\n");
-							// }
-						}
-						
+					if(wasDisconnected(fd))
+						break;
 
-						fprintf(stdout, "$microcart> ");
-						memset(userCommand, 0, cmdLen);
+					if (fd == fileno(stdin)) {
+						// break;
+						// unsigned char userCommand[CMD_MAX_LENGTH];
+						// read(fileno(stdin), (char *)userCommand, sizeof(userCommand));
+						// unsigned int cmdLen = strlen((char*) userCommand);
+						// // if the user simply hit enter then let them try again
+						// if((userCommand[0] != '\n') && (userCommand[0] != '\r'))
+						// {
+						// 	// remove newline and return line chars
+						// 	if((userCommand[cmdLen - 1] == '\n') || (userCommand[cmdLen - 1] == '\r'))
+						// 	userCommand[cmdLen - 1] = '\0';
+
+						// 	unsigned char *packet;
+						// 	formatCommand(userCommand, &packet);
+
+						// 	printf("received input from cli: '%s'\n", userCommand);
+
+						// 	// Write the command to the control_loop socket
+						// 	// int n = writeQuad(packet, ((packet[6] << 8) | packet[5]) + 8);
+						// 	// if(n < 0) {
+						// 	// 	fprintf(stdout, "CLI: ERROR writing to socket\n");
+						// 	// }
+						// }
+
+						// fprintf(stdout, "$microcart> ");
+						// memset(userCommand, 0, cmdLen);
 					} else if (fd == zyboSocket) {
 						
 					} else if (fd == backendSocket) {
@@ -267,13 +264,6 @@ int main(int argc, char **argv)
 				}
 			}
 		} else {
-			for(int i = 0; i < MAX_CLIENTS; ++i) {
-				if(client_fds[i] != -1) {
-					char buff;
-					if(recv(client_fds[i],&buff, 1, MSG_PEEK | MSG_DONTWAIT) < 0)
-						remove_client(client_fds[i]);
-				}
-			}
 			timeout.tv_sec = 1;
 			timeout.tv_usec = 0;
 		}
@@ -404,15 +394,6 @@ int connectToZybo() {
 	}
 }
 
-void performCommand(char *cmdName, char * command) {
-	for(int i = 0; i < NUM_COMMANDS; ++i)
-	{
-		if(startsWith(registeredCommands[i].commandText, command)) {
-			fprintf(stdout, "\r\n You used cmd '%s'\n",registeredCommands[i].commandText);
-		}
-	}
-}
-
 int startsWith(const char *pre, const char *str) {
     size_t lenpre = strlen(pre),
            lenstr = strlen(str);
@@ -443,7 +424,7 @@ int safe_fd_clr(int fd, fd_set* fds, int* max_fd) {
 
 static ssize_t writeQuad(const char * buf, size_t count) {
 	ssize_t retval;
-	if (getenv(NOQUAD_ENV)) {
+	if (1) {//getenv(NOQUAD_ENV)) {
 		return count;
 	}
 	if (pthread_mutex_lock(&quadSocketMutex)) {
@@ -537,7 +518,6 @@ static void client_recv(int fd)
 	}
 	buffer[len_pre + r] = '\0';
 
-
 	/* Parse buffer and handle commands */
 	while (1) {
 		/* not using strtok because reasons */
@@ -554,16 +534,33 @@ static void client_recv(int fd)
 		if (newline == -1) {
 			break;
 		}
-
 		buffer[newline] = '\0';
+
 		unsigned char * packet;
-		fprintf(stderr, "Client sent: %s\n", buffer);
-		formatCommand((unsigned char *) buffer, &packet);
-		writeQuad((char *) packet, 4);
-		free(packet);
+		// fprintf(stderr, "newline =%li, Client sent: '%s'\n", newline, buffer);
+		if(formatCommand(buffer, &packet) != -1) {
+			fprintf(stdout, "Backend sees as: %f\n", getFloat(packet, 7));
+		} else {
+			fprintf(stderr, "Could not recognize command '%s'\n", buffer);
+		}
+		writeQuad((char *) packet, len);
+		//free(packet);
 		
 		char * rest = &buffer[newline] + 1;
+		size_t restLen = (strlen(rest) == 0) ? 1 : strlen(rest);
 		/* Delete parsed data and move the rest to the left */
-		memmove(buffer, rest, strlen(rest));
+		memmove(buffer, rest, restLen);
 	}
 }
+
+static int wasDisconnected(int fd) {
+	char buff;
+	if(recv(fd, &buff, 1, MSG_PEEK | MSG_DONTWAIT) == 0)
+	{
+		remove_client(fd);
+		safe_fd_clr(fd, &rfds_master, &max_fd);
+		fprintf(stderr, "fd %d has disconnect and was removed\n", fd);
+		return 1;
+	}
+	return 0;
+}
-- 
GitLab