From c76cba50c532857f40323f3fe6eb60f3b03f32bf Mon Sep 17 00:00:00 2001
From: burneykb <burneykb@iastate.edu>
Date: Wed, 22 Mar 2017 17:36:39 -0500
Subject: [PATCH] Communication from FE -> BE seems to be in order.

Next I will implement a local socket to act as the receiving from the BE and responding to the BE
---
 groundStation/Makefile                       |   4 +-
 groundStation/getoutput                      |   1 -
 groundStation/getparam                       |   1 -
 groundStation/getsource                      |   1 -
 groundStation/setparam                       |   1 -
 groundStation/setsource                      |   1 -
 groundStation/src/backend/backend.c          |  35 +++--
 groundStation/src/backend/nodes.c            | 153 +++++++++++++++++++
 groundStation/src/backend/nodes.h            |  47 ++++++
 groundStation/src/backend/output.c           |   8 +-
 groundStation/src/backend/output.h           |   1 +
 groundStation/src/backend/param.c            |  14 +-
 groundStation/src/backend/param.h            |   1 +
 groundStation/src/backend/source.c           |  14 +-
 groundStation/src/backend/source.h           |   1 +
 groundStation/src/cli/cli.h                  |  11 +-
 groundStation/src/cli/cli_nodes.c            |  66 ++++++++
 groundStation/src/cli/cli_nodes.h            |   9 ++
 groundStation/src/cli/cli_output.c           |   3 +-
 groundStation/src/cli/cli_param.c            |   3 +-
 groundStation/src/cli/cli_source.c           |   3 +-
 groundStation/src/frontend/frontend_common.h |  22 ++-
 groundStation/src/frontend/frontend_nodes.c  | 107 +++++++++++++
 groundStation/src/frontend/frontend_nodes.h  |  25 +++
 groundStation/src/frontend/frontend_output.c |   5 +-
 groundStation/src/frontend/frontend_param.c  |   7 +-
 groundStation/src/frontend/frontend_source.c |   7 +-
 27 files changed, 498 insertions(+), 53 deletions(-)
 delete mode 120000 groundStation/getoutput
 delete mode 120000 groundStation/getparam
 delete mode 120000 groundStation/getsource
 delete mode 120000 groundStation/setparam
 delete mode 120000 groundStation/setsource
 create mode 100644 groundStation/src/backend/nodes.c
 create mode 100644 groundStation/src/backend/nodes.h
 create mode 100644 groundStation/src/cli/cli_nodes.c
 create mode 100644 groundStation/src/cli/cli_nodes.h
 create mode 100644 groundStation/src/frontend/frontend_nodes.c
 create mode 100644 groundStation/src/frontend/frontend_nodes.h

diff --git a/groundStation/Makefile b/groundStation/Makefile
index 7a62e3752..47356c05d 100644
--- a/groundStation/Makefile
+++ b/groundStation/Makefile
@@ -28,7 +28,7 @@ CLIBINARY=Cli
 CLISRCDIR=src/cli
 CLISOURCES := $(wildcard $(CLISRCDIR)/*.c)
 CLIOBJECTS = $(CLISOURCES:$(CLISRCDIR)/%.c=$(OBJDIR)/%.o)
-SYMLINKS= getparam setparam getsource setsource getoutput
+SYMLINKS= getnodes addnode getparam setparam getsource setsource getoutput
 
 # Frontend-common stuff
 FESRCDIR=src/frontend
@@ -82,7 +82,7 @@ clean_logs:
 	rm -f logs/*
 
 clean:
-	rm -rf $(OBJDIR)/ $(BEBINARY) $(CLIBINARY)
+	rm -rf $(OBJDIR)/ $(BEBINARY) $(CLIBINARY) $(SYMLINKS)
 
 debug:
 	@echo $(COMOBJECTS)
diff --git a/groundStation/getoutput b/groundStation/getoutput
deleted file mode 120000
index 83c63a5d9..000000000
--- a/groundStation/getoutput
+++ /dev/null
@@ -1 +0,0 @@
-Cli
\ No newline at end of file
diff --git a/groundStation/getparam b/groundStation/getparam
deleted file mode 120000
index 83c63a5d9..000000000
--- a/groundStation/getparam
+++ /dev/null
@@ -1 +0,0 @@
-Cli
\ No newline at end of file
diff --git a/groundStation/getsource b/groundStation/getsource
deleted file mode 120000
index 83c63a5d9..000000000
--- a/groundStation/getsource
+++ /dev/null
@@ -1 +0,0 @@
-Cli
\ No newline at end of file
diff --git a/groundStation/setparam b/groundStation/setparam
deleted file mode 120000
index 83c63a5d9..000000000
--- a/groundStation/setparam
+++ /dev/null
@@ -1 +0,0 @@
-Cli
\ No newline at end of file
diff --git a/groundStation/setsource b/groundStation/setsource
deleted file mode 120000
index 83c63a5d9..000000000
--- a/groundStation/setsource
+++ /dev/null
@@ -1 +0,0 @@
-Cli
\ No newline at end of file
diff --git a/groundStation/src/backend/backend.c b/groundStation/src/backend/backend.c
index 5b8535dcc..382a525c0 100644
--- a/groundStation/src/backend/backend.c
+++ b/groundStation/src/backend/backend.c
@@ -38,6 +38,7 @@
 #include "config.h"
 #include "source.h"
 #include "output.h"
+#include "nodes.h"
 #include "bitwise.h"
 
 #define QUAD_BT_ADDR  "00:06:66:64:61:D6"
@@ -674,7 +675,7 @@ static void client_recv(int fd) {
 		} else {
 			uint8_t packet[64];
 			struct metadata m;
-			uint8_t data[128];
+			uint8_t *data = malloc(sizeof(*data) * 128);
 			ssize_t result;  
 			ssize_t psize;
 
@@ -697,8 +698,10 @@ static void client_recv(int fd) {
 					result = EncodeGetOutput(&m, data, 128, buffer);
 					break;
 				case GETNODES_ID:
-					result = -1;
-					// result = EncodeGetnodes(&m, data, 128, buffer);
+					result = EncodeGetNodes(&m, data, 128, buffer);
+					break;
+				case ADDNODE_ID:
+					result = EncodeAddNode(&m, data, 128, buffer);
 					break;
 				default:
 					result = -1;
@@ -707,6 +710,7 @@ static void client_recv(int fd) {
 
 			if (result < 0) {
 				warnx("Big problems. client_recv. EncodeMetaData");
+				free(data);
 				return;
 			}
 
@@ -714,11 +718,13 @@ static void client_recv(int fd) {
 
 			if ((psize = EncodePacket(packet, 64, &m, data)) < 0) {
 				warnx("Big problems. client_recv. EncodePacket");
+				free(data);
 				return;
 			}
 
 			/* Only add the client to the pending responses if it was a getparam command */
-			if (m.msg_type == GETPARAM_ID || m.msg_type == GETOUTPUT_ID || m.msg_type == GETSOURCE_ID) {
+			if (m.msg_type == GETPARAM_ID || m.msg_type == GETOUTPUT_ID || 
+				m.msg_type == GETSOURCE_ID || m.msg_type == GETNODES_ID || m.msg_type == ADDNODE_ID) {
 				if (clientAddPendResponses(fd, BytesTo16(packet[ID_L], packet[ID_H])) == -1) {
 					warnx("Ran out of room! Consider increasing CLIENT_MAX_PENDING_RESPONSES!\n");
 				}
@@ -731,7 +737,7 @@ static void client_recv(int fd) {
 			printf("'\n");
 			
 			writeQuad(packet, psize);
-
+			free(data);
 		}
 
 		char * rest = &buffer[newline] + 1;
@@ -813,9 +819,10 @@ static void quad_recv() {
 			case RESPPARAM_ID:
 			case RESPSOURCE_ID:
 			case RESPOUTPUT_ID:
+			case RESPNODES_ID:
+			case RESPADDNODE_ID:
 				handleResponse(&m, data);
 				break;
-			case RESPNODES_ID:
 			default:
 				printf("(Backend): message type %d ignored from quad\n", m.msg_type);
 		}
@@ -825,17 +832,23 @@ static void quad_recv() {
 static void handleResponse(struct metadata *m, uint8_t * data)
 {
 	ssize_t result;
-	char buffer[128];
+	char *buffer = malloc(sizeof(*buffer) * 128);
 
 	switch (m->msg_type) {
 		case RESPPARAM_ID:
-			result = DecodeResponseParam(buffer, m, data);
+			result = DecodeResponseParam(buffer, 128, m, data);
 			break;
 		case RESPSOURCE_ID:
-			result = DecodeResponseSource(buffer, m, data);
+			result = DecodeResponseSource(buffer, 128, m, data);
 			break;
 		case RESPOUTPUT_ID:
-			result = DecodeResponseOutput(buffer, m, data);
+			result = DecodeResponseOutput(buffer, 128, m, data);
+			break;
+		case RESPNODES_ID:
+			result = DecodeResponseGetNodes(buffer, 128, m, data);
+			break;
+		case RESPADDNODE_ID:
+			result = DecodeResponseAddNode(buffer, 128, m, data);
 			break;
 		default:
 			result = -1;
@@ -843,6 +856,7 @@ static void handleResponse(struct metadata *m, uint8_t * data)
 
 	if (result < 0) {
 		warnx("DecodeResponse error");
+		free(buffer);
 		return;
 	}
 
@@ -852,6 +866,7 @@ static void handleResponse(struct metadata *m, uint8_t * data)
 			write(fd, buffer, result);
 		}
 	}
+	free(buffer);
 }
 
 static int wasDisconnected(int fd) {
diff --git a/groundStation/src/backend/nodes.c b/groundStation/src/backend/nodes.c
new file mode 100644
index 000000000..4db73c6f4
--- /dev/null
+++ b/groundStation/src/backend/nodes.c
@@ -0,0 +1,153 @@
+#include <sys/types.h>
+#include <inttypes.h>
+
+#include "nodes.h"
+#include "../../../common/commands.h"
+#include "bitwise.h"
+
+
+enum GetnodeData {
+	GN_DATA_SIZE
+};
+
+
+/* Creates data and metadata for a getnodes packet.
+ * Returns data size.
+ */
+ssize_t EncodeGetNodes(
+		struct metadata *m, /* Out */
+		uint8_t *data,      /* Out */
+		size_t data_size,   /* Data buffer max size */
+		const char * msg)  /* Value is not used; only IDs */
+{
+	m->msg_type = GETNODES_ID;
+	m->data_len = GN_DATA_SIZE;
+
+	return GN_DATA_SIZE;
+}
+
+enum AddnodeData {
+	AN_TYPE_ID_L,
+	AN_TYPE_ID_H,
+	AN_NAME,
+	AN_MIN_DATA_SIZE
+};
+
+/* Creates data and metadata for a addnode packet
+ * Returns data size.
+ */
+ssize_t EncodeAddNode(
+		struct metadata * m,        /* data_len and msg_type will be populated*/
+		uint8_t * data,             /* Output buffer */
+		size_t data_size,           /* Max buffer size */
+		const char * msg)      /* Message to encode */
+{
+	m->msg_type = ADDNODE_ID;
+	
+	if (data_size < AN_MIN_DATA_SIZE) {
+		return -1;
+	}
+
+	int16_t type;
+	char name[512];
+
+	sscanf(msg, "addnode %" SCNd16 "%s\n", &type, name);
+
+	data[AN_TYPE_ID_L] = LSByte16(type);
+	data[AN_TYPE_ID_H] = MSByte16(type);
+	
+	memcpy(&data[AN_NAME], name, strlen(name) + 1); // We want to include the null byte
+	
+	m->data_len = AN_MIN_DATA_SIZE + strlen(name);
+
+	return m->data_len;
+}
+
+enum ResponseGetnodesData {
+	RESP_GN_NUM_NODES_L,
+	RESP_GN_NUM_NODES_H,
+	RESP_GN_MIN_DATA_SIZE
+};
+
+/* Decode a metadata and data to populate a.
+ * Returns bytes written to msg, -1 on failure.
+ */
+int DecodeResponseGetNodes(
+		char * msg, 				   /* Out */
+		size_t max_len,				   /* msg buffer max size */
+		const struct metadata *m,      /* In */
+		const uint8_t * data)	      /* In */
+{
+	/* See if we have the min. amount */
+	if (m->data_len < RESP_GN_MIN_DATA_SIZE) {
+		return -1;
+	}
+	if (m->msg_type != RESPNODES_ID) {
+		return -1;
+	}
+
+	uint16_t num_nodes = BytesTo16(data[RESP_GN_NUM_NODES_L], data[RESP_GN_NUM_NODES_H]);
+
+	/* resize the msg if necessary */
+	if (max_len < (m->data_len * 2)) {
+		max_len = max_len * 2;
+		msg = realloc(msg, sizeof(*msg) * max_len);
+		if (!msg) {
+			return -1;
+		}
+	}
+
+
+
+	int16_t val;
+	char name[512]; /* Corresponding to the maximum name len that the frontend will accept */
+	size_t i;
+	int msg_offset = 0;
+	int data_offset = RESP_GN_MIN_DATA_SIZE;
+
+
+	sprintf(msg, "getnodes %hu %n", num_nodes, &msg_offset);
+	msg += msg_offset;
+
+	for(i = 0; i < num_nodes * 3; ++i) {
+		if (i < num_nodes * 2) {
+			val = BytesTo16(data[data_offset], data[data_offset+1]);
+			data_offset += 2;
+			sprintf(msg, "%" PRId16 " %n", val, &msg_offset);
+		} else {
+			strncpy(name, (char *) &data[data_offset], 512);
+			data_offset += strlen(name) + 1;
+			sprintf(msg, "%s %n", name, &msg_offset);
+		}
+
+		msg += msg_offset;	
+	}
+
+	return strlen(msg);
+}
+
+enum ResponseAddnodeData {
+	RESP_AN_BLOCK_ID_L,
+	RESP_AN_BLOCK_ID_H,
+	RESP_AN_DATA_SIZE
+};
+
+/* Decode a metadata and data to populate a controller.
+ * Returns bytes written to msg, -1 on failure.
+ */
+int DecodeResponseAddNode(
+		char * msg, 				   /* Out */
+		size_t max_len,				   /* msg buffer max size */
+		const struct metadata *m,      /* In */
+		const uint8_t * data)         /* In */
+{
+	if (m->data_len < RESP_AN_DATA_SIZE) {
+		return -1;
+	}
+	if (m->msg_type != RESPADDNODE_ID) {
+		return -1;
+	}
+	
+	return sprintf(msg, "addnode %d", 
+		BytesTo16(data[RESP_AN_BLOCK_ID_L], data[RESP_AN_BLOCK_ID_H]));
+}
\ No newline at end of file
diff --git a/groundStation/src/backend/nodes.h b/groundStation/src/backend/nodes.h
new file mode 100644
index 000000000..18f57c9a3
--- /dev/null
+++ b/groundStation/src/backend/nodes.h
@@ -0,0 +1,47 @@
+#ifndef _nodes_h
+#define _nodes_h
+
+#include "packet.h"
+
+#include <sys/types.h>
+
+
+/* Creates data and metadata for a getnodes packet.
+ * Returns data size.
+ */
+ssize_t EncodeGetNodes(
+		struct metadata *m, /* Out */
+		uint8_t *data,      /* Out */
+		size_t data_size,   /* Data buffer max size */
+		const char * msg); /* Value is not used; only IDs */
+
+/* Creates data and metadata for a addnode packet
+ * Returns data size.
+ */
+ssize_t EncodeAddNode(
+		struct metadata * m,        /* data_len and msg_type will be populated*/
+		uint8_t * data,             /* Output buffer */
+		size_t data_size,           /* Max buffer size */
+		const char * msg);      /* Message to encode */
+
+
+/* Decode a metadata and data to populate a.
+ * Returns bytes written to msg, -1 on failure.
+ */
+int DecodeResponseGetNodes(
+		char * msg, 				   /* Out */
+		size_t max_len,				   /* msg buffer max size */
+		const struct metadata *m,      /* In */
+		const uint8_t * data);         /* In */
+
+
+/* Decode a metadata and data to populate a controller.
+ * Returns bytes written to msg, -1 on failure.
+ */
+int DecodeResponseAddNode(
+		char * msg, 				   /* Out */
+		size_t max_len,				   /* msg buffer max size */
+		const struct metadata *m,      /* In */
+		const uint8_t * data);         /* In */
+
+#endif
\ No newline at end of file
diff --git a/groundStation/src/backend/output.c b/groundStation/src/backend/output.c
index 0c3195c95..f293f3ec7 100644
--- a/groundStation/src/backend/output.c
+++ b/groundStation/src/backend/output.c
@@ -1,4 +1,5 @@
 #include <sys/types.h>
+#include <inttypes.h>
 
 #include "output.h"
 #include "../../../common/commands.h"
@@ -29,9 +30,9 @@ ssize_t EncodeGetOutput(
 		return -1;
 	}
 
-	uint16_t block, output;
+	int16_t block, output;
 
-	sscanf(msg, "getoutput %hu %hu", &block, &output);
+	sscanf(msg, "getoutput %" SCNd16 " %" SCNd16, &block, &output);
 
 	data[GO_BLOCK_ID_L] = LSByte16(block);
 	data[GO_BLOCK_ID_H] = MSByte16(block);
@@ -58,6 +59,7 @@ enum ResponseData {
  */
 int DecodeResponseOutput(
         char * msg,     /* Decoded controller message */
+		size_t max_len,				   /* msg buffer max size */
         const struct metadata * m,          /* Metadata to aid in decoding */
         const uint8_t * data)               /* Data to decode */
 {
@@ -68,7 +70,7 @@ int DecodeResponseOutput(
 		return -1;
 	}
 
-	return sprintf(msg, "getoutput %hu %hu %f\n", 
+	return snprintf(msg, max_len, "getoutput %" PRId16 " %" PRId16 " %f", 
 		BytesTo16(data[RESP_BLOCK_ID_L], data[RESP_BLOCK_ID_H]), 
 		BytesTo16(data[RESP_OUTPUT_ID_L], data[RESP_OUTPUT_ID_H]), 
 		BytesToFloat(data[RESP_VAL_1], data[RESP_VAL_2],
diff --git a/groundStation/src/backend/output.h b/groundStation/src/backend/output.h
index 034d6ec15..df923ab54 100644
--- a/groundStation/src/backend/output.h
+++ b/groundStation/src/backend/output.h
@@ -21,6 +21,7 @@ ssize_t EncodeGetOutput(
  */
 int DecodeResponseOutput(
 		char * msg, 				   /* Out */
+		size_t max_len,				   /* msg buffer max size */
 		const struct metadata *m,      /* In */
 		const uint8_t * data);         /* In */
 
diff --git a/groundStation/src/backend/param.c b/groundStation/src/backend/param.c
index 749960fe4..15b049dba 100644
--- a/groundStation/src/backend/param.c
+++ b/groundStation/src/backend/param.c
@@ -1,4 +1,5 @@
 #include <sys/types.h>
+#include <inttypes.h>
 
 #include "param.h"
 #include "../../../common/commands.h"
@@ -28,8 +29,8 @@ ssize_t EncodeGetParam(
 		return -1;
 	}
 
-	uint16_t block, param;
-	sscanf(msg, "getparam %hu %hu", &block, &param);
+	int16_t block, param;
+	sscanf(msg, "getparam %" SCNd16 " %" SCNd16, &block, &param);
 
 
 	data[GP_BLOCK_ID_L] = LSByte16(block);
@@ -69,10 +70,10 @@ ssize_t EncodeSetParam(
 		return -1;
 	}
 
-	uint16_t block, param;
+	int16_t block, param;
 	float val;
 
-	sscanf(msg, "setparam %hu %hu %f", &block, &param, &val);
+	sscanf(msg, "setparam %" SCNd16 " %" SCNd16 " %f", &block, &param, &val);
 
 	data[SP_BLOCK_ID_L] = LSByte16(block);
 	data[SP_BLOCK_ID_H] = MSByte16(block);
@@ -107,7 +108,8 @@ enum ResponseData {
  * Returns bytes written to msg, -1 on failure.
  */
 int DecodeResponseParam(
-        char * msg,     /* Decoded controller message */
+        char * msg,     			/* Decoded controller message */
+		size_t max_len,				   /* msg buffer max size */
         const struct metadata * m,          /* Metadata to aid in decoding */
         const uint8_t * data)               /* Data to decode */
 {
@@ -118,7 +120,7 @@ int DecodeResponseParam(
 		return -1;
 	}
 
-	return sprintf(msg, "getparam %hu %hu %f\n", 
+	return snprintf(msg, max_len, "getparam %" PRId16 " %" PRId16 " %f", 
 		BytesTo16(data[RESP_BLOCK_ID_L], data[RESP_BLOCK_ID_H]), 
 		BytesTo16(data[RESP_PARAM_ID_L], data[RESP_PARAM_ID_H]), 
 		BytesToFloat(data[RESP_VAL_1], data[RESP_VAL_2],
diff --git a/groundStation/src/backend/param.h b/groundStation/src/backend/param.h
index 96ecc6332..b8b03429e 100644
--- a/groundStation/src/backend/param.h
+++ b/groundStation/src/backend/param.h
@@ -29,6 +29,7 @@ ssize_t EncodeSetParam(
  */
 int DecodeResponseParam(
 		char * msg, 				   /* Out */
+		size_t max_len,				   /* msg buffer max size */
 		const struct metadata *m,      /* In */
 		const uint8_t * data);         /* In */
 
diff --git a/groundStation/src/backend/source.c b/groundStation/src/backend/source.c
index a0e5ed9c3..ab319d251 100644
--- a/groundStation/src/backend/source.c
+++ b/groundStation/src/backend/source.c
@@ -1,4 +1,5 @@
 #include <sys/types.h>
+#include <inttypes.h>
 
 #include "source.h"
 #include "../../../common/commands.h"
@@ -28,9 +29,9 @@ ssize_t EncodeGetSource(
 	if (data_size < GS_DATA_SIZE) {
 		return -1;
 	}
-	uint16_t block, input;
+	int16_t block, input;
 
-	sscanf(msg, "getsource %hu %hu", &block, &input);
+	sscanf(msg, "getsource %" SCNd16 " %" SCNd16, &block, &input);
 
 	data[GS_BLOCK_ID_L] = LSByte16(block);
 	data[GS_BLOCK_ID_H] = MSByte16(block);
@@ -68,10 +69,10 @@ ssize_t EncodeSetSource(
 		return -1;
 	}
 	
-	uint16_t dst_block, dst_input;
-	uint16_t src_block, src_output;
+	int16_t dst_block, dst_input;
+	int16_t src_block, src_output;
 
-	sscanf(msg, "setsource %hu %hu %hu %hu", &dst_block, &dst_input, &src_block, &src_output);
+	sscanf(msg, "setsource %" SCNd16 " %" SCNd16 " %" SCNd16 " %" SCNd16, &dst_block, &dst_input, &src_block, &src_output);
 
 	data[SS_DST_BLOCK_ID_L] = LSByte16(dst_block);
 	data[SS_DST_BLOCK_ID_H] = MSByte16(dst_block);
@@ -104,6 +105,7 @@ enum ResponseData {
  */
 int DecodeResponseSource(
         char * msg,     /* Decoded controller message */
+		size_t max_len,				   /* msg buffer max size */
         const struct metadata * m,          /* Metadata to aid in decoding */
         const uint8_t * data)               /* Data to decode */
 {
@@ -114,7 +116,7 @@ int DecodeResponseSource(
 		return -1;
 	}
 
-	return sprintf(msg, "getsource %hu %hu %hu %hu\n", 
+	return snprintf(msg, max_len, "getsource %" PRId16 " %" PRId16 " %" PRId16" %" PRId16, 
 		BytesTo16(data[RESP_DST_BLOCK_ID_L], data[RESP_DST_BLOCK_ID_H]),
 		BytesTo16(data[RESP_DST_INPUT_ID_L], data[RESP_DST_INPUT_ID_H]),
 		BytesTo16(data[RESP_SRC_BLOCK_ID_L], data[RESP_SRC_BLOCK_ID_H]),
diff --git a/groundStation/src/backend/source.h b/groundStation/src/backend/source.h
index 577f27717..40a78f0c3 100644
--- a/groundStation/src/backend/source.h
+++ b/groundStation/src/backend/source.h
@@ -29,6 +29,7 @@ ssize_t EncodeSetSource(
  */
 int DecodeResponseSource(
 		char * msg, 				   /* Out */
+		size_t max_len,				   /* msg buffer max size */
 		const struct metadata *m,      /* In */
 		const uint8_t * data);         /* In */
 
diff --git a/groundStation/src/cli/cli.h b/groundStation/src/cli/cli.h
index edd3ebc85..7a7d4fdf8 100644
--- a/groundStation/src/cli/cli.h
+++ b/groundStation/src/cli/cli.h
@@ -5,6 +5,7 @@
 #include "cli_source.h"
 #include "cli_param.h"
 #include "cli_output.h"
+#include "cli_nodes.h"
 
 struct backend_conn;
 
@@ -14,6 +15,8 @@ enum CommandNameIds{
 	CMD_GETPARAM,
 	CMD_SETPARAM,
 	CMD_GETOUTPUT,
+	CMD_GETNODES,
+	CMD_ADDNODE,
 	MAX_COMMANDS
 };
 
@@ -23,7 +26,9 @@ static cli_function_ptr cli_functions[] = {
 	&cli_setsource,
 	&cli_getparam,
 	&cli_setparam,
-	&cli_getoutput
+	&cli_getoutput,
+	&cli_getnodes,
+	&cli_addnode
 };
 
 static char* commandNames[MAX_COMMANDS] = {
@@ -31,7 +36,9 @@ static char* commandNames[MAX_COMMANDS] = {
 	"setsource",
 	"getparam",
 	"setparam",
-	"getoutput"
+	"getoutput",
+	"getnodes",
+	"addnode"
 };
 /* This function is called by other cli functions to check for a help condition */
 int help_check(int argc, char ** argv);
diff --git a/groundStation/src/cli/cli_nodes.c b/groundStation/src/cli/cli_nodes.c
new file mode 100644
index 000000000..ff067dd57
--- /dev/null
+++ b/groundStation/src/cli/cli_nodes.c
@@ -0,0 +1,66 @@
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <inttypes.h>
+
+#include "cli.h"
+#include "cli_nodes.h"
+#include "frontend_nodes.h"
+
+int cli_getnodes(struct backend_conn * conn, int argc, char ** argv) {
+	size_t num_nodes = 0;
+	struct frontend_node_data * node_data;
+
+	int needHelp = 0;
+	
+	if ((needHelp = help_check(argc, argv))) {
+		printf("getnodes gets the number of nodes along with the block_id, type_id and name of each node\n");
+		printf("Usage Syntax : \n\t./Cli getnodes\n");
+		printf("Symlink Usage Syntax : \n\t./getnodes\n\n");
+		return 0;
+	}
+
+	if (argc > 1) {
+		printf("Incorrect Usage, run './cli getnodes --help' for correct usage.\n");
+		return 1;
+	}
+
+	node_data = malloc(sizeof(*node_data) * num_nodes);
+
+
+	if (frontend_getnodes(conn, node_data, &num_nodes)) {
+		free(node_data);
+		return 1;
+	}
+
+	printf("unimplemented\n");
+	free(node_data);
+	return 0;
+}
+
+int cli_addnode(struct backend_conn * conn, int argc, char ** argv) {
+	struct frontend_node_data node_data;
+	int needHelp = 0;
+	
+	if ((needHelp = help_check(argc, argv))) {
+		printf("addnodes adds a node of specified type_id and name to the comp_graph\n");
+		printf("Usage Syntax : \n\t./Cli addnode type_id name\n");
+		printf("Symlink Usage Syntax : \n\t./addnode type_id name\n\n");
+		return 0;
+	}
+
+	if (argc < 3) {
+		printf("Incorrect Usage, run './cli addnode --help' for correct usage.\n");
+		return 1;
+	}
+	
+	node_data.type = atoi(argv[1]);
+	strncpy(node_data.name, argv[2], 512/* this value matches the max space of name */ );
+
+	if (frontend_addnode(conn, &node_data)) {
+		return 1;
+	}
+
+	printf("Node created with block_id : %" PRId16 "\n", node_data.block);
+	return 0;
+}
diff --git a/groundStation/src/cli/cli_nodes.h b/groundStation/src/cli/cli_nodes.h
new file mode 100644
index 000000000..2d9bb1372
--- /dev/null
+++ b/groundStation/src/cli/cli_nodes.h
@@ -0,0 +1,9 @@
+#ifndef  _CLI_NODES_H
+#define  _CLI_NODES_H
+
+#include "frontend_nodes.h"
+
+int cli_getnodes(struct backend_conn * conn, int argc, char ** argv);
+int cli_addnode(struct backend_conn * conn, int argc, char ** argv);
+
+#endif /* _CLI_NODES_H */
\ No newline at end of file
diff --git a/groundStation/src/cli/cli_output.c b/groundStation/src/cli/cli_output.c
index f48266f41..273b749c3 100644
--- a/groundStation/src/cli/cli_output.c
+++ b/groundStation/src/cli/cli_output.c
@@ -1,5 +1,6 @@
 #include <stdio.h>
 #include <unistd.h>
+#include <inttypes.h>
 
 #include "cli.h"
 #include "cli_output.h"
@@ -29,7 +30,7 @@ int cli_getoutput(struct backend_conn * conn, int argc, char ** argv) {
 	}
 
 	printf("BLOCK.OUTPUT = VAL\n" \
-		   "  %hu.%hu   =  %lf\n",
+		   "  %" PRId16 ".%" PRId16 "   =  %lf\n",
 		   output_data.block,
 		   output_data.output,
 		   output_data.value);
diff --git a/groundStation/src/cli/cli_param.c b/groundStation/src/cli/cli_param.c
index d123a088c..478682cce 100644
--- a/groundStation/src/cli/cli_param.c
+++ b/groundStation/src/cli/cli_param.c
@@ -1,5 +1,6 @@
 #include <stdio.h>
 #include <unistd.h>
+#include <inttypes.h>
 
 #include "cli.h"
 #include "cli_param.h"
@@ -29,7 +30,7 @@ int cli_getparam(struct backend_conn * conn, int argc, char ** argv) {
 	}
 
 	printf("BLOCK.PARAM = VAL\n" \
-		   "  %hu.%hu   =  %lf\n",
+		   "  %" PRId16 ".%" PRId16 "   =  %lf\n",
 		   param_data.block,
 		   param_data.param,
 		   param_data.value);
diff --git a/groundStation/src/cli/cli_source.c b/groundStation/src/cli/cli_source.c
index 86f47a922..c7168a6fb 100644
--- a/groundStation/src/cli/cli_source.c
+++ b/groundStation/src/cli/cli_source.c
@@ -1,5 +1,6 @@
 #include <stdio.h>
 #include <unistd.h>
+#include <inttypes.h>
 
 #include "cli.h"
 #include "cli_source.h"
@@ -29,7 +30,7 @@ int cli_getsource(struct backend_conn * conn, int argc, char ** argv) {
 	}
 
 	printf("SRC BLOCK.OUTPUT  --->  DST BLOCK.INPUT\n" \
-		   "      %hu.%hu     --->        %hu.%hu\n",
+		   "      %" PRId16 ".%" PRId16 "     --->        %" PRId16 ".%" PRId16 "\n",
 		source_data.src_block, source_data.src_output,
 		source_data.dst_block, source_data.dst_input);
 	return 0;
diff --git a/groundStation/src/frontend/frontend_common.h b/groundStation/src/frontend/frontend_common.h
index 4986d859c..f4ed6b740 100644
--- a/groundStation/src/frontend/frontend_common.h
+++ b/groundStation/src/frontend/frontend_common.h
@@ -20,22 +20,28 @@ char * ucart_backendGetline(struct backend_conn * conn);
 int ucart_backendWrite(struct backend_conn * backend, const char * line);
 
 struct frontend_output_data {
-	unsigned short block;
-	unsigned short output;
+	int16_t block;
+	int16_t output;
 	float value;
 };
 
 struct frontend_param_data {
-	unsigned short block;
-	unsigned short param;
+	int16_t block;
+	int16_t param;
 	float value;
 };
 
 struct frontend_source_data {
-	unsigned short dst_block;
-	unsigned short dst_input;
-	unsigned short src_block;
-	unsigned short src_output;
+	int16_t dst_block;
+	int16_t dst_input;
+	int16_t src_block;
+	int16_t src_output;
+};
+
+struct frontend_node_data {
+	int16_t block;
+	int16_t type;
+	char name[512]; /* This should be more than enough room for a node name */
 };
 
 #endif /* __FRONTEND_COMMON_H */
\ No newline at end of file
diff --git a/groundStation/src/frontend/frontend_nodes.c b/groundStation/src/frontend/frontend_nodes.c
new file mode 100644
index 000000000..b1284b409
--- /dev/null
+++ b/groundStation/src/frontend/frontend_nodes.c
@@ -0,0 +1,107 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <err.h>
+#include <inttypes.h>
+
+#include "frontend_nodes.h"
+
+/* Get the block_id, type_id and name of
+ * all of the nodes in the current comp_graph.
+ *
+ * Returns 0 on success, 1 on error
+ */
+int frontend_getnodes(
+		struct backend_conn * conn,
+		struct frontend_node_data * node_data,
+		size_t * num_nodes) {
+
+	char msg[64] = "";
+	int written;
+
+	snprintf(msg, 64, "getnodes\n");
+
+	if((written = ucart_backendWrite(conn, msg)) < 0) {
+		return 1;
+	}
+
+	size_t pendingResponses = 1;
+	char * response;
+
+	while (pendingResponses) {
+		response = ucart_backendGetline(conn);
+		if (response == NULL) {
+			warnx("Line not returned from backend");
+			return 1;
+		}
+
+		if (strncmp(response, "getnodes", 8) != 0) {
+			continue;
+		}
+
+		size_t num_nodes_ret = 0;
+		size_t offset = 0;
+
+		sscanf(response, "getnodes %lu %n", &num_nodes_ret,  (int * )&offset);
+		response += offset;
+
+		/* Resize if necessary */
+		if (num_nodes_ret != *num_nodes) {
+			*num_nodes = num_nodes_ret;
+			node_data = realloc(node_data, sizeof(*node_data) * (*num_nodes));
+			if (!node_data) {
+				return 1;
+			}
+		}
+
+		for (size_t i = 0; i < *num_nodes; ++i) {
+			sscanf(response, "%" SCNd16 " %" SCNd16 " %s %n",
+				&node_data[i].block, &node_data[i].type, (char *) &node_data[i].name,
+				(int *)&offset);
+			response += offset;
+		}
+
+		pendingResponses--;
+	}
+	
+	return 0;
+}
+
+/* Set the value of block.param
+ *
+ * Returns 0 on success, 1 on error
+ */
+int frontend_addnode(
+		struct backend_conn * conn,
+		struct frontend_node_data * node_data) {
+	
+	char msg[16 + strlen(node_data->name)];
+	int written;
+
+	snprintf(msg, 16 + strlen(node_data->name), "addnode %" PRId16 " %s\n", node_data->type, node_data->name);
+
+	if((written = ucart_backendWrite(conn, msg)) < 0) {
+		return 1;
+	}
+
+	size_t pendingResponses = 1;
+	char * response;
+
+	while (pendingResponses) {
+		response = ucart_backendGetline(conn);
+		if (response == NULL) {
+			warnx("Line not returned from backend");
+			return 1;
+		}
+
+		if (strncmp(response, "addnode", 7) != 0) {
+			continue;
+		}
+
+		sscanf(response, "addnode %" SCNd16, &node_data->block);
+
+		pendingResponses--;
+	}
+	
+	return 0;
+}
\ No newline at end of file
diff --git a/groundStation/src/frontend/frontend_nodes.h b/groundStation/src/frontend/frontend_nodes.h
new file mode 100644
index 000000000..430301308
--- /dev/null
+++ b/groundStation/src/frontend/frontend_nodes.h
@@ -0,0 +1,25 @@
+#ifndef _FRONTEND_NODES_H
+#define _FRONTEND_NODES_H
+
+#include "frontend_common.h"
+
+/* Get the block_id, type_id and name of
+ * all of the nodes in the current comp_graph.
+ *
+ * Returns 0 on success, 1 on error
+ */
+int frontend_getnodes(
+		struct backend_conn * conn,
+		struct frontend_node_data * node_data,
+		size_t * num_nodes);
+
+
+/* Adds a node of specified type_id
+ *
+ * Returns 0 on success, 1 on error
+ */
+int frontend_addnode(
+		struct backend_conn * conn,
+		struct frontend_node_data * node_data);
+
+#endif /* __FRONTEND_NODES_H */
\ No newline at end of file
diff --git a/groundStation/src/frontend/frontend_output.c b/groundStation/src/frontend/frontend_output.c
index a93bb0403..54cd6cf88 100644
--- a/groundStation/src/frontend/frontend_output.c
+++ b/groundStation/src/frontend/frontend_output.c
@@ -2,6 +2,7 @@
 #include <string.h>
 #include <stdlib.h>
 #include <err.h>
+#include <inttypes.h>
 
 #include "frontend_output.h"
 
@@ -17,7 +18,7 @@ int frontend_getoutput(
 	char msg[64] = "";
 	int written;
 
-	snprintf(msg, 64, "getoutput %hu %hu\n", output_data->block, output_data->output);
+	snprintf(msg, 64, "getoutput %" PRId16 " %" PRId16 "\n", output_data->block, output_data->output);
 
 	if((written = ucart_backendWrite(conn, msg)) < 0) {
 		return 1;
@@ -34,7 +35,7 @@ int frontend_getoutput(
 		}
 
 		if (strncmp(response, "getoutput", 9) == 0) {
-			sscanf(response, "getoutput %hu %hu %f\n", 
+			sscanf(response, "getoutput %" SCNd16 " %" SCNd16" %f", 
 				&output_data->block, &output_data->output,
 				&output_data->value);
 			pendingResponses--;
diff --git a/groundStation/src/frontend/frontend_param.c b/groundStation/src/frontend/frontend_param.c
index c98972031..d16faa644 100644
--- a/groundStation/src/frontend/frontend_param.c
+++ b/groundStation/src/frontend/frontend_param.c
@@ -2,6 +2,7 @@
 #include <string.h>
 #include <stdlib.h>
 #include <err.h>
+#include <inttypes.h>
 
 #include "frontend_param.h"
 
@@ -17,7 +18,7 @@ int frontend_getparam(
 	char msg[64] = "";
 	int written;
 
-	snprintf(msg, 64, "getparam %hu %hu\n", param_data->block, param_data->param);
+	snprintf(msg, 64, "getparam %" PRId16 " %" PRId16 "\n", param_data->block, param_data->param);
 
 	if((written = ucart_backendWrite(conn, msg)) < 0) {
 		return 1;
@@ -34,7 +35,7 @@ int frontend_getparam(
 		}
 
 		if (strncmp(response, "getparam", 8) == 0) {
-			sscanf(response, "getparam %hu %hu %f\n", 
+			sscanf(response, "getparam %" SCNd16 " %" SCNd16 " %f", 
 				&param_data->block, &param_data->param,
 				&param_data->value);
 			pendingResponses--;
@@ -55,7 +56,7 @@ int frontend_setparam(
 	char msg[64] = "";
 	int written;
 
-	snprintf(msg, 64, "setparam %hu %hu %f\n", param_data->block, param_data->param, param_data->value);
+	snprintf(msg, 64, "setparam %" PRId16 " %" PRId16 " %f\n", param_data->block, param_data->param, param_data->value);
 
 	if((written = ucart_backendWrite(conn, msg)) < 0) {
 		return 1;
diff --git a/groundStation/src/frontend/frontend_source.c b/groundStation/src/frontend/frontend_source.c
index 4016de3e1..809696fc0 100644
--- a/groundStation/src/frontend/frontend_source.c
+++ b/groundStation/src/frontend/frontend_source.c
@@ -2,6 +2,7 @@
 #include <string.h>
 #include <stdlib.h>
 #include <err.h>
+#include <inttypes.h>
 
 #include "frontend_source.h"
 
@@ -18,7 +19,7 @@ int frontend_getsource(
 	char msg[64] = "";
 	int written;
 
-	snprintf(msg, 64, "getsource %hu %hu\n", source_data->dst_block, source_data->dst_input);
+	snprintf(msg, 64, "getsource %" PRId16 " %" PRId16 "\n", source_data->dst_block, source_data->dst_input);
 
 	if((written = ucart_backendWrite(conn, msg)) < 0) {
 		return 1;
@@ -35,7 +36,7 @@ int frontend_getsource(
 		}
 
 		if (strncmp(response, "getsource", 9) == 0) {
-			sscanf(response, "getsource %hu %hu %hu %hu\n", 
+			sscanf(response, "getsource %" SCNd16 " %" SCNd16 " %" SCNd16 " %" SCNd16, 
 				&source_data->dst_block, &source_data->dst_input,
 				&source_data->src_block, &source_data->src_output);
 			pendingResponses--;
@@ -56,7 +57,7 @@ int frontend_setsource(
 	char msg[64] = "";
 	int written;
 
-	snprintf(msg, 64, "setsource %hu %hu %hu %hu\n", 
+	snprintf(msg, 64, "setsource %" PRId16 " %" PRId16 " %" PRId16 " %" PRId16 "\n", 
 		source_data->dst_block, source_data->dst_input, 
 		source_data->src_block, source_data->src_output);
 
-- 
GitLab