Skip to content
Snippets Groups Projects
Unverified Commit 709342d5 authored by Jake Drahos's avatar Jake Drahos
Browse files

Merge remote-tracking branch 'origin/groundStation-dev-comp_graph-commands' into gui-dev

parents a5faab83 cdbd0fd5
No related branches found
No related tags found
No related merge requests found
Showing
with 574 additions and 620 deletions
...@@ -6,15 +6,10 @@ GXX=g++ ...@@ -6,15 +6,10 @@ GXX=g++
CFLAGS= -Wall -pedantic -Wextra -Werror -std=gnu99 -g -Wno-unused-parameter -Wno-unused-variable -Wno-unused-function -Wno-unused-but-set-variable CFLAGS= -Wall -pedantic -Wextra -Werror -std=gnu99 -g -Wno-unused-parameter -Wno-unused-variable -Wno-unused-function -Wno-unused-but-set-variable
CXXFLAGS= -Wall -pedantic -Wextra -Werror -Wno-reorder -Wno-unused-variable -std=c++0x -g CXXFLAGS= -Wall -pedantic -Wextra -Werror -Wno-reorder -Wno-unused-variable -std=c++0x -g
INCLUDES = $(foreach dir, $(INCDIR), -I$(dir)) INCLUDES = $(foreach dir, $(INCDIR), -I$(dir))
INCDIR=inc src/vrpn src/vrpn/quat src/vrpn/build $(COMSRCDIR) $(BESRCDIR) $(CLISRCDIR) $(FESRCDIR) INCDIR= src/vrpn src/vrpn/quat src/vrpn/build $(BESRCDIR) $(CLISRCDIR) $(FESRCDIR) ../quad/inc
LIBS= -lpthread -lbluetooth -lvrpn -lquat -Lsrc/vrpn/build -Lsrc/vrpn/build/quat LIBS= -lpthread -lbluetooth -lvrpn -lquat -Lsrc/vrpn/build -Lsrc/vrpn/build/quat -L../quad/lib -lquad_app -lcommands -lgraph_blocks -lcomputation_graph
OBJDIR=obj OBJDIR=obj
# Common Objects
COMSRCDIR=../common
COMSOURCES := $(wildcard $(COMSRCDIR)/*.c )
COMOBJECTS = $(COMSOURCES:$(COMSRCDIR)/%.c=$(OBJDIR)/%.o)
# Backend Specific Variables # Backend Specific Variables
BEBINARY=BackEnd BEBINARY=BackEnd
BESRCDIR=src/backend BESRCDIR=src/backend
...@@ -28,7 +23,7 @@ CLIBINARY=Cli ...@@ -28,7 +23,7 @@ CLIBINARY=Cli
CLISRCDIR=src/cli CLISRCDIR=src/cli
CLISOURCES := $(wildcard $(CLISRCDIR)/*.c) CLISOURCES := $(wildcard $(CLISRCDIR)/*.c)
CLIOBJECTS = $(CLISOURCES:$(CLISRCDIR)/%.c=$(OBJDIR)/%.o) CLIOBJECTS = $(CLISOURCES:$(CLISRCDIR)/%.c=$(OBJDIR)/%.o)
SYMLINKS=monitor setpid getpid setsetpoint getsetpoint SYMLINKS= getnodes addnode getparam setparam getsource setsource getoutput
# Frontend-common stuff # Frontend-common stuff
FESRCDIR=src/frontend FESRCDIR=src/frontend
...@@ -36,10 +31,13 @@ FECSOURCES := $(wildcard $(FESRCDIR)/*.c ) ...@@ -36,10 +31,13 @@ FECSOURCES := $(wildcard $(FESRCDIR)/*.c )
FECOBJECTS = $(FECSOURCES:$(FESRCDIR)/%.c=$(OBJDIR)/%.o) FECOBJECTS = $(FECSOURCES:$(FESRCDIR)/%.c=$(OBJDIR)/%.o)
OBJECTS= $(COMOBJECTS) $(CLIOBJECTS) $(BECOBJECTS) $(BECPPOBJECTS) $(FECOBJECTS) OBJECTS=$(CLIOBJECTS) $(BECOBJECTS) $(BECPPOBJECTS) $(FECOBJECTS)
# Default target # Default target
all: logs objdir backend cli $(SYMLINKS) frontend.a all: quad logs objdir backend cli $(SYMLINKS) frontend.a
quad:
$(MAKE) -C ../quad
$(SYMLINKS): $(CLIBINARY) $(SYMLINKS): $(CLIBINARY)
$(foreach symlink, $(SYMLINKS), ln -s $(CLIBINARY) $(symlink);) $(foreach symlink, $(SYMLINKS), ln -s $(CLIBINARY) $(symlink);)
...@@ -55,13 +53,9 @@ cli: $(CLIOBJECTS) $(FECOBJECTS) ...@@ -55,13 +53,9 @@ cli: $(CLIOBJECTS) $(FECOBJECTS)
$(CLIOBJECTS) : $(OBJDIR)/%.o : $(CLISRCDIR)/%.c $(CLIOBJECTS) : $(OBJDIR)/%.o : $(CLISRCDIR)/%.c
$(GCC) $(CFLAGS) -c $^ -o $@ $(INCLUDES) $(LIBS) $(GCC) $(CFLAGS) -c $^ -o $@ $(INCLUDES) $(LIBS)
backend: $(BECPPOBJECTS) $(BECOBJECTS)
backend: $(COMOBJECTS) $(BECPPOBJECTS) $(BECOBJECTS)
$(GXX) $(CXXFLAGS) $^ -o $(BEBINARY) $(INCLUDES) $(LIBS) $(GXX) $(CXXFLAGS) $^ -o $(BEBINARY) $(INCLUDES) $(LIBS)
$(COMOBJECTS) : $(OBJDIR)/%.o : $(COMSRCDIR)/%.c
$(GCC) $(CFLAGS) -c $^ -o $@ $(INCLUDES) $(LIBS)
$(FECOBJECTS) : $(OBJDIR)/%.o : $(FESRCDIR)/%.c $(FECOBJECTS) : $(OBJDIR)/%.o : $(FESRCDIR)/%.c
$(GCC) $(CFLAGS) -c $^ -o $@ $(INCLUDES) $(LIBS) $(GCC) $(CFLAGS) -c $^ -o $@ $(INCLUDES) $(LIBS)
...@@ -85,7 +79,6 @@ clean_logs: ...@@ -85,7 +79,6 @@ clean_logs:
rm -f logs/* rm -f logs/*
clean: clean:
rm -rf $(OBJDIR)/ $(BEBINARY) $(CLIBINARY) rm -rf $(OBJDIR)/ $(BEBINARY) $(CLIBINARY) $(SYMLINKS)
debug: debug:
@echo $(COMOBJECTS)
...@@ -29,7 +29,7 @@ ...@@ -29,7 +29,7 @@
#include <netinet/tcp.h> #include <netinet/tcp.h>
//user created includes //user created includes
#include "../../../common/commands.h" #include "commands.h"
#include "vrpn_tracker.hpp" #include "vrpn_tracker.hpp"
#include "type_def.h" #include "type_def.h"
#include "packet.h" #include "packet.h"
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
#include "config.h" #include "config.h"
#include "source.h" #include "source.h"
#include "output.h" #include "output.h"
#include "nodes.h"
#include "bitwise.h" #include "bitwise.h"
#define QUAD_BT_ADDR "00:06:66:64:61:D6" #define QUAD_BT_ADDR "00:06:66:64:61:D6"
...@@ -81,7 +82,8 @@ static void quad_recv(); ...@@ -81,7 +82,8 @@ static void quad_recv();
static int wasDisconnected(int fd); static int wasDisconnected(int fd);
/* handle controller responses from quad to frontend */ /* handle controller responses from quad to frontend */
static void handleResponse(struct metadata *m, uint8_t * data); static void handleResponse(struct metadata *m, uint8_t * data);
/* Create new dynamic logfile name */
char * create_log_name(char * buffer, size_t max);
/* Thread-safe wrappers */ /* Thread-safe wrappers */
pthread_mutex_t quadSocketMutex; pthread_mutex_t quadSocketMutex;
...@@ -112,14 +114,13 @@ fd_set rfds_master; ...@@ -112,14 +114,13 @@ fd_set rfds_master;
int max_fd = 0; int max_fd = 0;
static FILE * quadlog_file; static FILE * quadlog_file;
static int quadlog_file_open;
static char user_specified_log_name[256] = "";
pthread_mutex_t quadResponseMutex, cliInputMutex ; pthread_mutex_t quadResponseMutex, cliInputMutex ;
unsigned char *commandBuf; unsigned char *commandBuf;
int newQuadResponse = 0, newCliInput = 0; int newQuadResponse = 0, newCliInput = 0;
// Structures to be used throughout
modular_structs_t structs;
// Callback to be ran whenever the tracker receives data. // Callback to be ran whenever the tracker receives data.
// Currently doing much more than it should. It will be slimmed down // Currently doing much more than it should. It will be slimmed down
// in the future. // in the future.
...@@ -133,8 +134,6 @@ int main(int argc, char **argv) ...@@ -133,8 +134,6 @@ int main(int argc, char **argv)
{ {
int activity; int activity;
FD_ZERO(&rfds_master); FD_ZERO(&rfds_master);
char log_file[256] = "logs/";
/* /*
* Create backend listening socket * Create backend listening socket
*/ */
...@@ -153,6 +152,8 @@ int main(int argc, char **argv) ...@@ -153,6 +152,8 @@ int main(int argc, char **argv)
err(-1, "socket"); err(-1, "socket");
} }
printf("backendSocket = %d\n", backendSocket);
/* Create sockaddr and bind */ /* Create sockaddr and bind */
struct sockaddr_un sa; struct sockaddr_un sa;
sa.sun_family = AF_UNIX; sa.sun_family = AF_UNIX;
...@@ -191,6 +192,8 @@ int main(int argc, char **argv) ...@@ -191,6 +192,8 @@ int main(int argc, char **argv)
exit(1); exit(1);
} }
printf("zyboSocket = %d\n", zyboSocket);
if (pthread_mutex_unlock(&quadSocketMutex)) { if (pthread_mutex_unlock(&quadSocketMutex)) {
err(-2, "pthrtead_mutex_unlock (%s:%d):", __FILE__, __LINE__); err(-2, "pthrtead_mutex_unlock (%s:%d):", __FILE__, __LINE__);
} }
...@@ -205,40 +208,27 @@ int main(int argc, char **argv) ...@@ -205,40 +208,27 @@ int main(int argc, char **argv)
if(argc >= 2) if(argc >= 2)
{ {
strncat(log_file, argv[1], strlen(argv[1])); strncat(user_specified_log_name, argv[1], strlen(argv[1]));
} else {
time_t rawtime;
char timestr [30];
time(&rawtime);
sprintf(timestr,"%s",ctime(&rawtime));
// Lets convert space to _ in
char *p = timestr;
size_t i = 0;
while(i < strlen(timestr))
{
if (*p == ' ')
*p = '_';
i++;
p++;
}
// timestr has a weird char at the end of it.
// we will not include it in our file name
strncat(log_file, timestr, strlen(timestr) -1 );
strcat(log_file, ".txt");
} }
char log_file[256];
create_log_name(log_file, 256);
printf("Creating log file '%s'...\n",log_file); printf("Creating log file '%s'...\n",log_file);
quadlog_file = fopen(log_file, "a"); quadlog_file = fopen(log_file, "a");
quadlog_file_open = 1;
// Tell the quad we are ready to send it vrpn data // Tell the quad we are ready to send it vrpn data
sendStartPacket(); sendStartPacket();
if(!getenv(NOVRPN_ENV)){ if(!getenv(NOVRPN_ENV)){
printf("Creating VRPN tracker...\n");
// create vrpnTracker instance // create vrpnTracker instance
tracker = ucart_vrpn_tracker_createInstance(TRACKER_IP); tracker = ucart_vrpn_tracker_createInstance(TRACKER_IP);
// this function will be called whenever tracker receives data // this function will be called whenever tracker receives data
ucart_vrpn_tracker_addCallback(tracker, cb); ucart_vrpn_tracker_addCallback(tracker, cb);
} else {
printf("Ignoring VRPN information...\n");
} }
struct timeval timeout = { struct timeval timeout = {
...@@ -358,28 +348,48 @@ void printVrpnData(struct ucart_vrpn_TrackerData * td) { ...@@ -358,28 +348,48 @@ void printVrpnData(struct ucart_vrpn_TrackerData * td) {
int connectToZybo() { int connectToZybo() {
int sock; int sock;
int status = 0; int status = -1;
if (getenv(NOQUAD_ENV)) { if (getenv(NOQUAD_ENV)) {
return 0; return 0;
} }
/* Use bluetooth by default */ /* Use wifi by default */
if (!getenv(QUAD_WIFI_ENV)) { if (getenv(QUAD_COMM_ENV)) {
printf("Using BT Settings\n"); /* Determine if we are using bluetooth or local */
struct sockaddr_rc addr; if(strcmp(getenv(QUAD_COMM_ENV), "local") == 0) {
printf("Using Local Socket Settings\n");
struct sockaddr_un remote;
char str[100];
// allocate a socket if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
sock = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM); perror("socket");
exit(1);
}
//set the connection params ie. who to connect to remote.sun_family = AF_UNIX;
addr.rc_family = AF_BLUETOOTH; char * sock_env = getenv(QUAD_LOCAL_SOCKET);
addr.rc_channel = (uint8_t) QUAD_BT_CHANNEL; strcpy(remote.sun_path, sock_env ? sock_env : QUAD_DEFAULT_LOCAL_SOCKET);
str2ba( QUAD_BT_ADDR, &addr.rc_bdaddr ); printf("Attempting to connect to local socket at '%s'. please be patiend.\n", remote.sun_path);
printf("Attempting to connect to zybo. Please be patient...\n"); status = connect(sock, (struct sockaddr *)&remote, sizeof(remote));
// blocking call to connect to socket sock ie. zybo board } else if (strcmp(getenv(QUAD_COMM_ENV), "bluetooth") == 0) {
status = connect(sock, (struct sockaddr *)&addr, sizeof(addr)); printf("Using BT Settings\n");
struct sockaddr_rc addr;
// allocate a socket
sock = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
//set the connection params ie. who to connect to
addr.rc_family = AF_BLUETOOTH;
addr.rc_channel = (uint8_t) QUAD_BT_CHANNEL;
str2ba( QUAD_BT_ADDR, &addr.rc_bdaddr );
printf("Attempting to connect to zybo. Please be patient...\n");
// blocking call to connect to socket sock ie. zybo board
status = connect(sock, (struct sockaddr *)&addr, sizeof(addr));
}
} else { } else {
printf("Using WIFI settings\n"); printf("Using WIFI settings\n");
struct sockaddr_in addr; struct sockaddr_in addr;
...@@ -629,15 +639,18 @@ static void client_recv(int fd) { ...@@ -629,15 +639,18 @@ static void client_recv(int fd) {
char * first_word; char * first_word;
char * tmp = strdup(buffer); char * tmp = strdup(buffer);
// printf("tmpbuff = '%s'\n", tmp);
first_word = strtok(tmp, " "); first_word = strtok(tmp, " ");
free(tmp); // printf("first word = '%s'\n", first_word);
ssize_t msg_type, i; ssize_t msg_type, i;
for (i = 0; i < MAX_TYPE_ID; ++i) { for (i = 0; i < MAX_TYPE_ID; ++i) {
if ((msg_type = findCommand(first_word)) != -1) if ((msg_type = findCommand(first_word)) != -1)
break; break;
} }
free(tmp);
if (msg_type == -1) { if (msg_type == -1) {
/* buffer was not a quad command, handling internally to /* buffer was not a quad command, handling internally to
* backend instead of forwarding to quad * backend instead of forwarding to quad
...@@ -675,10 +688,12 @@ static void client_recv(int fd) { ...@@ -675,10 +688,12 @@ static void client_recv(int fd) {
} else { } else {
uint8_t packet[64]; uint8_t packet[64];
struct metadata m; struct metadata m;
uint8_t data[128]; uint8_t *data = malloc(sizeof(*data) * 128);
ssize_t result; ssize_t result;
ssize_t psize; ssize_t psize;
printf(" found a msg_type of %ld\n", msg_type);
switch (msg_type) { switch (msg_type) {
case SETPARAM_ID: case SETPARAM_ID:
result = EncodeSetParam(&m, data, 128, buffer); result = EncodeSetParam(&m, data, 128, buffer);
...@@ -696,8 +711,10 @@ static void client_recv(int fd) { ...@@ -696,8 +711,10 @@ static void client_recv(int fd) {
result = EncodeGetOutput(&m, data, 128, buffer); result = EncodeGetOutput(&m, data, 128, buffer);
break; break;
case GETNODES_ID: 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; break;
default: default:
result = -1; result = -1;
...@@ -706,6 +723,7 @@ static void client_recv(int fd) { ...@@ -706,6 +723,7 @@ static void client_recv(int fd) {
if (result < 0) { if (result < 0) {
warnx("Big problems. client_recv. EncodeMetaData"); warnx("Big problems. client_recv. EncodeMetaData");
free(data);
return; return;
} }
...@@ -713,11 +731,13 @@ static void client_recv(int fd) { ...@@ -713,11 +731,13 @@ static void client_recv(int fd) {
if ((psize = EncodePacket(packet, 64, &m, data)) < 0) { if ((psize = EncodePacket(packet, 64, &m, data)) < 0) {
warnx("Big problems. client_recv. EncodePacket"); warnx("Big problems. client_recv. EncodePacket");
free(data);
return; return;
} }
/* Only add the client to the pending responses if it was a getparam command */ /* 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) { if (clientAddPendResponses(fd, BytesTo16(packet[ID_L], packet[ID_H])) == -1) {
warnx("Ran out of room! Consider increasing CLIENT_MAX_PENDING_RESPONSES!\n"); warnx("Ran out of room! Consider increasing CLIENT_MAX_PENDING_RESPONSES!\n");
} }
...@@ -729,8 +749,9 @@ static void client_recv(int fd) { ...@@ -729,8 +749,9 @@ static void client_recv(int fd) {
// } // }
// printf("'\n"); // printf("'\n");
writeQuad(packet, psize); int retval = writeQuad(packet, psize);
// printf("sent %d bytes\n", retval);
free(data);
} }
char * rest = &buffer[newline] + 1; char * rest = &buffer[newline] + 1;
...@@ -804,19 +825,33 @@ static void quad_recv() { ...@@ -804,19 +825,33 @@ static void quad_recv() {
switch (m.msg_type) { switch (m.msg_type) {
case LOG_ID: case LOG_ID:
/* something like this */ if (!quadlog_file_open) {
printf("(Quad) : Log found\n"); char log_file[256];
create_log_name(log_file, 256);
printf("New log file created: '%s'\n", log_file);
quadlog_file = fopen(log_file, "a");
quadlog_file_open = 1;
}
//printf("(Quad) : Log found\n");
fwrite((char *) data, sizeof(char), m.data_len, quadlog_file); fwrite((char *) data, sizeof(char), m.data_len, quadlog_file);
// fflush(quadlog_file);
break; break;
case RESPPARAM_ID: case RESPPARAM_ID:
case RESPSOURCE_ID: case RESPSOURCE_ID:
case RESPOUTPUT_ID: case RESPOUTPUT_ID:
case RESPNODES_ID:
case RESPADDNODE_ID:
handleResponse(&m, data); handleResponse(&m, data);
break; break;
case RESPNODES_ID: case LOG_END_ID:
if (quadlog_file_open) {
fclose(quadlog_file);
quadlog_file_open = 0;
}
printf("(Quad) : Log End found\n");
break;
default: default:
printf("(Backend): message type %d ignored from quad\n", m.msg_type); printf("(Backend): message type %d ignored from quad\n", m.msg_type);
break;
} }
} }
} }
...@@ -824,33 +859,45 @@ static void quad_recv() { ...@@ -824,33 +859,45 @@ static void quad_recv() {
static void handleResponse(struct metadata *m, uint8_t * data) static void handleResponse(struct metadata *m, uint8_t * data)
{ {
ssize_t result; ssize_t result;
char buffer[128]; char *buffer = malloc(sizeof(*buffer) * 128);
switch (m->msg_type) { switch (m->msg_type) {
case RESPPARAM_ID: case RESPPARAM_ID:
result = DecodeResponseParam(buffer, m, data); result = DecodeResponseParam(buffer, 128, m, data);
break; break;
case RESPSOURCE_ID: case RESPSOURCE_ID:
result = DecodeResponseSource(buffer, m, data); result = DecodeResponseSource(buffer, 128, m, data);
break; break;
case RESPOUTPUT_ID: 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; break;
default: default:
result = -1; result = -1;
break;
} }
if (result < 0) { if (result < 0) {
warnx("DecodeResponse error"); warnx("DecodeResponse error");
free(buffer);
return; return;
} }
// printf("msg to client = '%s'\n", buffer);
for(int fd = 0; fd <= max_fd; ++fd) { for(int fd = 0; fd <= max_fd; ++fd) {
if (get_client_index(fd) < 0) { if (get_client_index(fd) > -1) {
clientRemovePendResponses(fd, m->msg_id); clientRemovePendResponses(fd, m->msg_id);
write(fd, buffer, result); write(fd, buffer, result);
} }
} }
free(buffer);
} }
static int wasDisconnected(int fd) { static int wasDisconnected(int fd) {
...@@ -891,3 +938,25 @@ void findTimeDiff(int respID) { ...@@ -891,3 +938,25 @@ void findTimeDiff(int respID) {
timeval_subtract(&result, &tend, &timeArr[respID%MAX_HASH_SIZE]); timeval_subtract(&result, &tend, &timeArr[respID%MAX_HASH_SIZE]);
printf("(BackEnd): Elapsed time = %ld ms\n", result.tv_usec/1000); printf("(BackEnd): Elapsed time = %ld ms\n", result.tv_usec/1000);
} }
char * create_log_name(char * buffer, size_t max) {
static const char * prefix = "logs";
static size_t num_logs = 0;
static const char * format_string = "%Y-%m-%e_%-l:%M";
time_t curr_time;
char c_time_string[256];
struct tm * tmp;
curr_time = time(NULL);
tmp = localtime(&curr_time);
strftime(c_time_string, 256, format_string, tmp);
if(strcmp(user_specified_log_name, "") == 0) {
sprintf(buffer, "%s/%s_%lu.txt", prefix, c_time_string, num_logs++);
} else {
sprintf(buffer, "%s/%s_%lu.txt", prefix, user_specified_log_name, num_logs++);
}
return buffer;
}
...@@ -2,10 +2,7 @@ ...@@ -2,10 +2,7 @@
#define __CONFIG_H #define __CONFIG_H
#ifndef DEFAULT_SOCKET #define DEFAULT_SOCKET "./ucart.socket"
#define DEFAULT_SOCKET "/var/run/ucart.socket"
#endif
#define SOCKET_ENV "UCART_SOCKET" #define SOCKET_ENV "UCART_SOCKET"
#define NOQUAD_ENV "UCART_NO_QUAD" #define NOQUAD_ENV "UCART_NO_QUAD"
#define NOVRPN_ENV "UCART_NO_VRPN" #define NOVRPN_ENV "UCART_NO_VRPN"
...@@ -14,7 +11,10 @@ ...@@ -14,7 +11,10 @@
// If you are planning on using any of these env vars and you have // If you are planning on using any of these env vars and you have
// exported them with normal user rights. You will need to run the // exported them with normal user rights. You will need to run the
// backend with sudo elevation and with the --preserve-env flag or -E // backend with sudo elevation and with the --preserve-env flag or -E
#define QUAD_WIFI_ENV "UCART_USE_WIFI" #define QUAD_COMM_ENV "UCART_COMM_CHANNEL"
#define QUAD_DEFAULT_LOCAL_SOCKET "./virtquad.socket"
#define QUAD_LOCAL_SOCKET "UCART_LOCAL_SOCKET"
#define QUAD_IP_ENV "UCART_QUAD_IP" #define QUAD_IP_ENV "UCART_QUAD_IP"
#define QUAD_IP_DEFAULT "192.168.1.1" #define QUAD_IP_DEFAULT "192.168.1.1"
#define QUAD_PORT_ENV "UCART_QUAD_PORT" #define QUAD_PORT_ENV "UCART_QUAD_PORT"
......
#include <sys/types.h>
#include <inttypes.h>
#include "nodes.h"
#include "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
};
static int resizeMsg(char **msg_ptr, int *curr_max, int check_val) {
/* resize the msg if necessary */
if (*curr_max < check_val) {
*curr_max = *curr_max * 4;
*msg_ptr = realloc(*msg_ptr, sizeof(**msg_ptr) * *curr_max);
if (!msg_ptr) {
return -1;
}
}
return 0;
}
/* 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]);
if (resizeMsg(&msg, (int *)&max_len, (m->data_len *2)) == -1) {
return -1;
}
int16_t val;
char name[512] = "";/* Corresponding to the maximum name len that the frontend will accept */
size_t i;
int msg_len = 0, msg_offset = 0, data_offset = RESP_GN_MIN_DATA_SIZE;
sprintf(msg, "getnodes %hu %n", num_nodes, &msg_offset);
msg_len += 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[msg_len], "%" PRId16 " %n", val, &msg_offset);
} else {
strncpy(name, (char *) (data + data_offset), 512);
data_offset += strlen(name) + 1;
sprintf(&msg[msg_len], "'%s' %n", name, &msg_offset);
}
msg_len += msg_offset;
if (resizeMsg(&msg, (int *)&max_len, msg_len + (msg_offset *2)) == -1) {
return -1;
}
}
strcat(&msg[msg_len], "\n");
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\n",
BytesTo16(data[RESP_AN_BLOCK_ID_L], data[RESP_AN_BLOCK_ID_H]));
}
\ No newline at end of file
#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
#include <sys/types.h> #include <sys/types.h>
#include <inttypes.h>
#include "output.h" #include "output.h"
#include "../../../common/commands.h" #include "commands.h"
#include "bitwise.h" #include "bitwise.h"
...@@ -29,9 +30,9 @@ ssize_t EncodeGetOutput( ...@@ -29,9 +30,9 @@ ssize_t EncodeGetOutput(
return -1; 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_L] = LSByte16(block);
data[GO_BLOCK_ID_H] = MSByte16(block); data[GO_BLOCK_ID_H] = MSByte16(block);
...@@ -58,6 +59,7 @@ enum ResponseData { ...@@ -58,6 +59,7 @@ enum ResponseData {
*/ */
int DecodeResponseOutput( int DecodeResponseOutput(
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 struct metadata * m, /* Metadata to aid in decoding */
const uint8_t * data) /* Data to decode */ const uint8_t * data) /* Data to decode */
{ {
...@@ -68,7 +70,7 @@ int DecodeResponseOutput( ...@@ -68,7 +70,7 @@ int DecodeResponseOutput(
return -1; return -1;
} }
return sprintf(msg, "getoutput %hu %hu %f\n", return snprintf(msg, max_len, "getoutput %" PRId16 " %" PRId16 " %f\n",
BytesTo16(data[RESP_BLOCK_ID_L], data[RESP_BLOCK_ID_H]), BytesTo16(data[RESP_BLOCK_ID_L], data[RESP_BLOCK_ID_H]),
BytesTo16(data[RESP_OUTPUT_ID_L], data[RESP_OUTPUT_ID_H]), BytesTo16(data[RESP_OUTPUT_ID_L], data[RESP_OUTPUT_ID_H]),
BytesToFloat(data[RESP_VAL_1], data[RESP_VAL_2], BytesToFloat(data[RESP_VAL_1], data[RESP_VAL_2],
......
...@@ -21,6 +21,7 @@ ssize_t EncodeGetOutput( ...@@ -21,6 +21,7 @@ ssize_t EncodeGetOutput(
*/ */
int DecodeResponseOutput( int DecodeResponseOutput(
char * msg, /* Out */ char * msg, /* Out */
size_t max_len, /* msg buffer max size */
const struct metadata *m, /* In */ const struct metadata *m, /* In */
const uint8_t * data); /* In */ const uint8_t * data); /* In */
......
#include <sys/types.h> #include <sys/types.h>
#include <inttypes.h>
#include "param.h" #include "param.h"
#include "../../../common/commands.h" #include "commands.h"
#include "bitwise.h" #include "bitwise.h"
enum GetparamData { enum GetparamData {
...@@ -28,8 +29,8 @@ ssize_t EncodeGetParam( ...@@ -28,8 +29,8 @@ ssize_t EncodeGetParam(
return -1; return -1;
} }
uint16_t block, param; int16_t block, param;
sscanf(msg, "getparam %hu %hu", &block, &param); sscanf(msg, "getparam %" SCNd16 " %" SCNd16, &block, &param);
data[GP_BLOCK_ID_L] = LSByte16(block); data[GP_BLOCK_ID_L] = LSByte16(block);
...@@ -69,10 +70,10 @@ ssize_t EncodeSetParam( ...@@ -69,10 +70,10 @@ ssize_t EncodeSetParam(
return -1; return -1;
} }
uint16_t block, param; int16_t block, param;
float val; 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_L] = LSByte16(block);
data[SP_BLOCK_ID_H] = MSByte16(block); data[SP_BLOCK_ID_H] = MSByte16(block);
...@@ -107,7 +108,8 @@ enum ResponseData { ...@@ -107,7 +108,8 @@ enum ResponseData {
* Returns bytes written to msg, -1 on failure. * Returns bytes written to msg, -1 on failure.
*/ */
int DecodeResponseParam( 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 struct metadata * m, /* Metadata to aid in decoding */
const uint8_t * data) /* Data to decode */ const uint8_t * data) /* Data to decode */
{ {
...@@ -118,7 +120,7 @@ int DecodeResponseParam( ...@@ -118,7 +120,7 @@ int DecodeResponseParam(
return -1; return -1;
} }
return sprintf(msg, "getparam %hu %hu %f\n", return snprintf(msg, max_len, "getparam %" PRId16 " %" PRId16 " %f\n",
BytesTo16(data[RESP_BLOCK_ID_L], data[RESP_BLOCK_ID_H]), BytesTo16(data[RESP_BLOCK_ID_L], data[RESP_BLOCK_ID_H]),
BytesTo16(data[RESP_PARAM_ID_L], data[RESP_PARAM_ID_H]), BytesTo16(data[RESP_PARAM_ID_L], data[RESP_PARAM_ID_H]),
BytesToFloat(data[RESP_VAL_1], data[RESP_VAL_2], BytesToFloat(data[RESP_VAL_1], data[RESP_VAL_2],
......
...@@ -29,6 +29,7 @@ ssize_t EncodeSetParam( ...@@ -29,6 +29,7 @@ ssize_t EncodeSetParam(
*/ */
int DecodeResponseParam( int DecodeResponseParam(
char * msg, /* Out */ char * msg, /* Out */
size_t max_len, /* msg buffer max size */
const struct metadata *m, /* In */ const struct metadata *m, /* In */
const uint8_t * data); /* In */ const uint8_t * data); /* In */
......
#include <sys/types.h> #include <sys/types.h>
#include <inttypes.h>
#include "source.h" #include "source.h"
#include "../../../common/commands.h" #include "commands.h"
#include "bitwise.h" #include "bitwise.h"
...@@ -28,9 +29,9 @@ ssize_t EncodeGetSource( ...@@ -28,9 +29,9 @@ ssize_t EncodeGetSource(
if (data_size < GS_DATA_SIZE) { if (data_size < GS_DATA_SIZE) {
return -1; 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_L] = LSByte16(block);
data[GS_BLOCK_ID_H] = MSByte16(block); data[GS_BLOCK_ID_H] = MSByte16(block);
...@@ -68,10 +69,10 @@ ssize_t EncodeSetSource( ...@@ -68,10 +69,10 @@ ssize_t EncodeSetSource(
return -1; return -1;
} }
uint16_t dst_block, dst_input; int16_t dst_block, dst_input;
uint16_t src_block, src_output; 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_L] = LSByte16(dst_block);
data[SS_DST_BLOCK_ID_H] = MSByte16(dst_block); data[SS_DST_BLOCK_ID_H] = MSByte16(dst_block);
...@@ -88,10 +89,14 @@ ssize_t EncodeSetSource( ...@@ -88,10 +89,14 @@ ssize_t EncodeSetSource(
enum ResponseData { enum ResponseData {
RESP_DST_BLOCK_ID, RESP_DST_BLOCK_ID_L,
RESP_DST_INPUT_ID, RESP_DST_BLOCK_ID_H,
RESP_SRC_BLOCK_ID, RESP_DST_INPUT_ID_L,
RESP_SRC_OUTPUT_ID, RESP_DST_INPUT_ID_H,
RESP_SRC_BLOCK_ID_L,
RESP_SRC_BLOCK_ID_H,
RESP_SRC_OUTPUT_ID_L,
RESP_SRC_OUTPUT_ID_H,
RESP_DATA_SIZE RESP_DATA_SIZE
}; };
...@@ -100,6 +105,7 @@ enum ResponseData { ...@@ -100,6 +105,7 @@ enum ResponseData {
*/ */
int DecodeResponseSource( int DecodeResponseSource(
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 struct metadata * m, /* Metadata to aid in decoding */
const uint8_t * data) /* Data to decode */ const uint8_t * data) /* Data to decode */
{ {
...@@ -110,5 +116,9 @@ int DecodeResponseSource( ...@@ -110,5 +116,9 @@ int DecodeResponseSource(
return -1; return -1;
} }
return sprintf(msg, "getsource %d %d\n", data[RESP_SRC_BLOCK_ID], data[RESP_SRC_OUTPUT_ID]); return snprintf(msg, max_len, "getsource %" PRId16 " %" PRId16 " %" PRId16" %" PRId16 "\n",
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]),
BytesTo16(data[RESP_SRC_OUTPUT_ID_L], data[RESP_SRC_OUTPUT_ID_H]));
} }
...@@ -29,6 +29,7 @@ ssize_t EncodeSetSource( ...@@ -29,6 +29,7 @@ ssize_t EncodeSetSource(
*/ */
int DecodeResponseSource( int DecodeResponseSource(
char * msg, /* Out */ char * msg, /* Out */
size_t max_len, /* msg buffer max size */
const struct metadata *m, /* In */ const struct metadata *m, /* In */
const uint8_t * data); /* In */ const uint8_t * data); /* In */
......
#include "update.h" #include "update.h"
#include "../../../common/commands.h" #include "commands.h"
#include "bitwise.h" #include "bitwise.h"
#include <sys/types.h> #include <sys/types.h>
......
...@@ -52,9 +52,8 @@ int main(int argc, char **argv) ...@@ -52,9 +52,8 @@ int main(int argc, char **argv)
// recognize which cli command the user has entered // recognize which cli command the user has entered
if (cmdID == -1) { if (cmdID == -1) {
command = argv[1]; command = argv[1];
for(i = 0; i < MAX_COMMANDS; ++i) { for (i = 0; i < MAX_COMMANDS; ++i) {
if (strncmp(command, commandNames[i], strlen(commandNames[i])) == 0) if (strncmp(command, commandNames[i], strlen(commandNames[i])) == 0) {
{
cmdID = i; cmdID = i;
} }
} }
...@@ -78,7 +77,7 @@ int main(int argc, char **argv) ...@@ -78,7 +77,7 @@ int main(int argc, char **argv)
} }
/** /**
* I the user has asked for help, and we have already found * If the user has asked for help, and we have already found
* the command that they are trying to use. Then we need * the command that they are trying to use. Then we need
* to be able to provide the help info wihtout the * to be able to provide the help info wihtout the
* requirement of the backend * requirement of the backend
...@@ -100,7 +99,7 @@ int main(int argc, char **argv) ...@@ -100,7 +99,7 @@ int main(int argc, char **argv)
// Call the appropriate function // Call the appropriate function
if (useSymlink) { if (useSymlink) {
(*cli_functions[cmdID]) (conn, argc, &argv[0]); (*cli_functions[cmdID]) (conn, argc, &argv[0]);
}else { } else {
(*cli_functions[cmdID]) (conn, argc-1, &argv[1]); (*cli_functions[cmdID]) (conn, argc-1, &argv[1]);
} }
...@@ -109,4 +108,130 @@ int main(int argc, char **argv) ...@@ -109,4 +108,130 @@ int main(int argc, char **argv)
ucart_backendDisconnect(conn); ucart_backendDisconnect(conn);
} }
return 0; return 0;
}
/* This function is called by other cli functions to check for a help condition */
int help_check(int argc, char ** argv) {
int c;
static int needHelp = 0;
static struct option long_options[] = {
/* These options don’t set a flag. We distinguish them by their indices. */
{"help", no_argument, &needHelp, 1},
{0, 0, 0, 0}
};
while (1)
{
/* getopt_long stores the option index here. */
int option_index = 0;
c = getopt_long(argc, argv, "h", long_options, &option_index);
/* Detect the end of the options. */
if (c == -1)
break;
if (c == 'h') {
needHelp = 1;
}
}
return needHelp;
}
int isNumber(char *number) {
int i = 0;
//checking for negative numbers
if (number[0] == '-')
i = 1;
for (; number[i] != 0; i++)
{
//if (number[i] > '9' || number[i] < '0')
if (!isdigit(number[i]))
return 0;
}
return 1;
}
int convert_to_id(struct backend_conn * conn, char **argv, struct convert_data * convert_data, int conversion_requirement) {
/* variables used to search for id values */
size_t num_nodes = 0, i;
struct frontend_node_data* search_data;
int search_1 = 0, search_2 = 0;
const struct graph_node_type * node_definition;
if (!isNumber(argv[1])) {
search_1 = 1;
} else {
convert_data->val_1 = atoi(argv[1]);
}
if (!isNumber(argv[2])) {
search_2 = 1;
} else {
convert_data->val_2 = atoi(argv[2]);
}
if (!search_1 && !search_2) {
return 0;
}
search_data = malloc(sizeof((*search_data)) * num_nodes);
if (frontend_getnodes(conn, &search_data, &num_nodes)) {
return 1;
}
if (search_1) {
for (i = 0; i < num_nodes; ++i) {
if (strncasecmp(search_data[i].name, argv[1], strlen(search_data[i].name)) == 0) {
convert_data->val_1 = search_data[i].block;
node_definition = blockDefs[search_data[i].type];
break;
}
}
}
if (i == num_nodes)
return 1;
if (search_2) {
const int *num_s2_options;
const char* const* s2_options_arr;
if (!search_1) {
node_definition = blockDefs[search_data[convert_data->val_1].type];
}
switch (conversion_requirement) {
case PARAM:
num_s2_options = &node_definition->n_params;
s2_options_arr = node_definition->param_names;
break;
case INPUT:
num_s2_options = &node_definition->n_inputs;
s2_options_arr = node_definition->input_names;
break;
case OUTPUT:
num_s2_options = &node_definition->n_outputs;
s2_options_arr = node_definition->output_names;
break;
}
for (i = 0; i < (size_t)*num_s2_options; ++i) {
if (strncasecmp(s2_options_arr[i],
argv[2],
strlen(s2_options_arr[i])) == 0) {
convert_data->val_2 = i;
search_2 = 0;
break;
}
}
}
for(i = 0; i < num_nodes; ++i) {
free(search_data[i].name);
}
free(search_data);
return search_2;
} }
\ No newline at end of file
#ifndef __CLI_H #ifndef _CLI_H
#define __CLI_H #define _CLI_H
#include "cli_monitor.h" #include "frontend_common.h"
#include "cli_source.h" #include "cli_source.h"
#include "cli_param.h" #include "cli_param.h"
#include "cli_output.h" #include "cli_output.h"
#include "cli_nodes.h"
struct backend_conn;
enum CommandNameIds{ enum CommandNameIds{
CMD_MONITOR,
CMD_GETSOURCE, CMD_GETSOURCE,
CMD_SETSOURCE, CMD_SETSOURCE,
CMD_GETPARAM, CMD_GETPARAM,
CMD_SETPARAM, CMD_SETPARAM,
CMD_GETOUTPUT, CMD_GETOUTPUT,
CMD_GETNODES,
CMD_ADDNODE,
MAX_COMMANDS MAX_COMMANDS
}; };
typedef int (*cli_function_ptr)(struct backend_conn *, int, char **); typedef int (*cli_function_ptr)(struct backend_conn *, int, char **);
static cli_function_ptr cli_functions[] = { static cli_function_ptr cli_functions[] = {
&cli_monitor,
&cli_getsource, &cli_getsource,
&cli_setsource, &cli_setsource,
&cli_getparam, &cli_getparam,
&cli_setparam, &cli_setparam,
&cli_getoutput, &cli_getoutput,
&cli_getnodes,
&cli_addnode
}; };
static char* commandNames[MAX_COMMANDS] = { static char* commandNames[MAX_COMMANDS] = {
"monitor",
"getsource", "getsource",
"setsource", "setsource",
"getparam", "getparam",
"setparam", "setparam",
"getoutput" "getoutput",
"getnodes",
"addnode"
};
/**
* generic two short struct for use with 'convert_to_id()'
*/
struct convert_data {
int16_t val_1;
int16_t val_2;
}; };
#endif /* __CLI_H */ enum conversion_requirements {
\ No newline at end of file INPUT,
PARAM,
OUTPUT
};
/**
* isNumber takes a char * such as argv[n] and checks to see if it is a number.
* @param number null terminating string (ex. argv[1])
* @return 1 if 'number' is a number
* 0 if 'number' is not a number
*/
int isNumber(char *number);
/**
* convert_to_id will take in the convert_data struct and either use the values from argv or
* find the correct values by using the optional strings passed in from argv
* @param conn backend connection struct
* @param argv argv from the cmd line
* @param convert_data saves the necissary converted data in this struct for later use.
* @return returns an error integer
*/
int convert_to_id(struct backend_conn * conn, char **argv, struct convert_data * convert_data, int conversion_requirement);
/* This function is called by other cli functions to check for a help condition */
/**
* determine if the user asked for help
* @return 1 if help is needed, else 0.
*/
int help_check(int argc, char ** argv);
#endif /* _CLI_H */
\ No newline at end of file
#include <stdio.h>
#include <unistd.h>
#include <getopt.h>
#include "cli_getpid.h"
int cli_getpid(struct backend_conn * conn, int argc, char **argv) {
int c;
static int getRoll = 0, getPitch = 0, getYaw = 0, getAll = 0;
static int getRollV = 0, getPitchV = 0, getYawV = 0;
static int getHeight = 0, getLat = 0, getLong = 0;
static int needHelp = 0;
struct frontend_pid_data pid_data;
static struct option long_options[] = {
/* These options don’t set a flag. We distinguish them by their indices. */
{"roll", no_argument, &getRoll, 1},
{"pitch", no_argument, &getPitch, 1},
{"yaw", no_argument, &getYaw, 1},
{"rollv", no_argument, &getRollV, 1},
{"pitchv", no_argument, &getPitchV, 1},
{"yawv", no_argument, &getYawV, 1},
{"height", no_argument, &getHeight, 1},
{"lat", no_argument, &getLat, 1},
{"long", no_argument, &getLong, 1},
{"help", no_argument, &needHelp, 1},
{0, 0, 0, 0}
};
while (1)
{
/* getopt_long stores the option index here. */
int option_index = 0;
c = getopt_long(argc, argv, "a", long_options, &option_index);
/* Detect the end of the options. */
if (c == -1)
break;
if (c == 'a') {
getAll = 1;
}
}
if (needHelp) {
printf("Getpid gets the p, i , and d constant values of any single controller\n");
printf("Usage Syntax : \n\t./Cli getpid controller [options...]\n");
printf("Symlink Usage Syntax : \n\t./getpid controller [options...]\n\n");
printf("Available 'controllers' include the following\n");
printf("\t[--pitch] : Pitch\n\t[--roll] : Roll\n\t[--yaw] : Yaw\n");
printf("\t[--pitchv] : Pitch Velocity\n\t[--rollv] : Roll Velocity\n\t[--yawv] : Yaw Velocity\n");
printf("\t[--height] : Z\n\t[--lat] : X\n\t[--long] : Y\n\n");
return 0;
}
if (argc < 2) {
printf("Incorrect Usage, run './cli getpid --help' for correct usage.\n");
return 1;
}
int result;
if(getAll) {
for(int i = 0; i < PID_NUM_PIDS; ++i) {
pid_data.controller = i;
if ((result = getPidValues(conn, &pid_data))) {
return result;
}
}
} else {
if(getPitch) {
pid_data.controller = PID_PITCH;
if ((result = getPidValues(conn, &pid_data))) {
return result;
}
}
if(getRoll) {
pid_data.controller = PID_ROLL;
if ((result = getPidValues(conn, &pid_data))) {
return result;
}
}
if(getYaw) {
pid_data.controller = PID_YAW;
if ((result = getPidValues(conn, &pid_data))) {
return result;
}
}
if(getPitchV) {
pid_data.controller = PID_PITCH_RATE;
if ((result = getPidValues(conn, &pid_data))) {
return result;
}
}
if(getRollV) {
pid_data.controller = PID_ROLL_RATE;
if ((result = getPidValues(conn, &pid_data))) {
return result;
}
}
if(getYawV) {
pid_data.controller = PID_YAW_RATE;
if ((result = getPidValues(conn, &pid_data))) {
return result;
}
}
if(getHeight) {
pid_data.controller = PID_HEIGHT;
if ((result = getPidValues(conn, &pid_data))) {
return result;
}
}
if(getLat) {
pid_data.controller = PID_LAT;
if ((result = getPidValues(conn, &pid_data))) {
return result;
}
}
if(getLong) {
pid_data.controller = PID_LONG;
if ((result = getPidValues(conn, &pid_data))) {
return result;
}
}
}
return 0;
}
int getPidValues(struct backend_conn * conn, struct frontend_pid_data * pid_data) {
if(frontend_getpid(conn, pid_data)) {
return 1;
}
switch(pid_data->controller) {
case PID_PITCH :
printf("Pitch Constants: P = %f\tI = %f\tD = %f\n",
pid_data->p, pid_data->i, pid_data->d);
break;
case PID_ROLL :
printf("Roll Constants: P = %f\tI = %f\tD = %f\n",
pid_data->p, pid_data->i, pid_data->d);
break;
case PID_YAW :
printf("Yaw Constants: P = %f\tI = %f\tD = %f\n",
pid_data->p, pid_data->i, pid_data->d);
break;
case PID_PITCH_RATE :
printf("Pitch Rate Constants: P = %f\tI = %f\tD = %f\n",
pid_data->p, pid_data->i, pid_data->d);
break;
case PID_ROLL_RATE :
printf("Roll Rate Constants: P = %f\tI = %f\tD = %f\n",
pid_data->p, pid_data->i, pid_data->d);
break;
case PID_YAW_RATE :
printf("Yaw Rate Constants: P = %f\tI = %f\tD = %f\n",
pid_data->p, pid_data->i, pid_data->d);
break;
case PID_HEIGHT :
printf("Height Constants: P = %f\tI = %f\tD = %f\n",
pid_data->p, pid_data->i, pid_data->d);
break;
case PID_LAT :
printf("Latitude Constants: P = %f\tI = %f\tD = %f\n",
pid_data->p, pid_data->i, pid_data->d);
break;
case PID_LONG :
printf("Longitude Constants: P = %f\tI = %f\tD = %f\n",
pid_data->p, pid_data->i, pid_data->d);
break;
default :
break;
}
return 0;
}
#ifndef __CLI_GETPID_H
#define __CLI_GETPID_H
#include "frontend_getpid.h"
int getPidValues(struct backend_conn *, struct frontend_pid_data *);
int cli_getpid(struct backend_conn * conn, int argc, char ** argv);
#endif /* __CLI_GETPID_H */
\ No newline at end of file
#include <stdio.h>
#include <unistd.h>
#include <getopt.h>
#include "cli_getsetpoint.h"
int cli_getsetpoint(struct backend_conn * conn, int argc, char **argv) {
int c;
static int getheight = 0, getlat = 0, getlong = 0;
static int getpitch = 0, getroll = 0, getyaw = 0;
struct frontend_setpoint_data setpoint_data;
static int needHelp = 0;
static int mask;
static struct option long_options[] = {
/* These options don’t set a flag. We distinguish them by their indices. */
{"help", no_argument, &needHelp, 1},
{"height", no_argument, &getheight, 1},
{"long", no_argument, &getlong, 1},
{"lat", no_argument, &getlat, 1},
{"pitch", no_argument, &getpitch, 1},
{"roll", no_argument, &getroll, 1},
{"yaw", no_argument, &getyaw, 1},
{0, 0, 0, 0}
};
while (1)
{
/* getopt_long stores the option index here. */
int option_index = 0;
c = getopt_long(argc, argv, "a", long_options, &option_index);
/* Detect the end of the options. */
if (c == -1)
break;
if (c == 'a') {
getheight = 1;
getlat = 1;
getlong = 1;
getpitch = 1;
getroll = 1;
getyaw = 1;
}
}
if (needHelp) {
printf("Getsetpoint gets the height, lat, long, pitch, roll and yaw set point values for the quad.\n");
printf("Usage Syntax : \n\t./Cli getsetpoint [options...]\n");
printf("Symlink Usage Syntax : \n\t./getsetpoint [options...]\n\n");
printf("Available options include the following\n");
printf("\t[-a] : Gets all of the following setpoints\n");
printf("\t[--height] : Gets the height setpoint\n");
printf("\t[--lat] : Gets the latitude setpoint\n");
printf("\t[--long] : Gets the longitude setpoint\n");
printf("\t[--pitch] : Gets the pitch setpoint\n");
printf("\t[--roll] : Gets the roll setpoint\n");
printf("\t[--yaw] : Gets the yaw setpoint\n");
return 0;
}
if (argc < 2) {
printf("Incorrect Usage, run './cli getsetpoint --help' for correct usage.\n");
return 1;
}
int result;
if(getheight) {
if ((result = getSetPointValues(conn, &setpoint_data, HEIGHT))) {
return result;
}
}
if(getlat) {
if ((result = getSetPointValues(conn, &setpoint_data, LAT))) {
return result;
}
}
if(getlong) {
if ((result = getSetPointValues(conn, &setpoint_data, LONGG))) {
return result;
}
}
if(getpitch) {
if ((result = getSetPointValues(conn, &setpoint_data, PITCH))) {
return result;
}
}
if(getroll) {
if ((result = getSetPointValues(conn, &setpoint_data, ROLL))) {
return result;
}
}
if(getyaw) {
if ((result = getSetPointValues(conn, &setpoint_data, YAW))) {
return result;
}
}
return 0;
}
int getSetPointValues(struct backend_conn * conn, struct frontend_setpoint_data * setpoint_data, int type) {
if(frontend_getsetpoint(conn, setpoint_data, type)) {
return 1;
}
switch(type) {
case HEIGHT :
printf("Height: %f\n",
setpoint_data->height);
break;
case LAT :
printf("Latitude: %f\n",
setpoint_data->lat);
case LONGG :
printf("Longitude: %f\n",
setpoint_data->longg);
break;
case PITCH :
printf("Pitch: %f\n",
setpoint_data->pitch);
break;
case ROLL :
printf("Roll: %f\n",
setpoint_data->roll);
break;
case YAW :
printf("Yaw: %f\n",
setpoint_data->yaw);
break;
default :
break;
}
return 0;
}
#ifndef __CLI_GETSETPOINT_H
#define __CLI_GETSETPOINT_H
#include "frontend_getsetpoint.h"
enum {
HEIGHT,
LAT,
LONGG,
PITCH,
ROLL,
YAW
};
int getSetPointValues(struct backend_conn *, struct frontend_setpoint_data *, int type);
int cli_getsetpoint(struct backend_conn * conn, int argc, char ** argv);
#endif /* __CLI_GETSETPOINT_H */
\ No newline at end of file
#define _GNU_SOURCE
#include <stdio.h>
#include <unistd.h>
#include <getopt.h>
#include <time.h>
#include <unistd.h>
#include <err.h>
#include "cli_monitor.h"
#include "frontend_tracker.h"
#include "frontend_getpid.h"
#include "pid_common.h"
int rate = 10;
static int pidcounter = 0;
static int monitorcounter = 0;
int cli_monitor(struct backend_conn * conn, int argc, char **argv) {
int c, result;
int countFlag = 0;
int count;
int forever = 0;
static int needHelp = 0;
static struct option long_options[] = {
/* These options don’t set a flag. We distinguish them by their indices. */
{"help", no_argument, &needHelp, 1},
{0, 0, 0, 0}
};
while (1)
{
/* getopt_long stores the option index here. */
int option_index = 0;
// If you change this VVV please also update the help message
c = getopt_long(argc, argv, "fc:r:", long_options, &option_index);
if (c == -1)
break;
switch(c) {
case 'c' :
count = atoi(optarg);
countFlag = 1;
break;
case 'r' :
rate = atoi(optarg) + 1;
break;
case 'f' :
forever = 1;
break;
default :
break;
}
}
if (needHelp) {
printf("Monitor provides real time information about the quad. Including positional data as well as controller constants\n\n");
printf("Usage Syntax : \n\t./Cli monitor [options...]\n");
printf("Symlink Usage Syntax : \n\t./monitor [options...]\n\n");
printf("Available options include the following\n");
printf("\t[-f] : Run monitor continuously until you kill the program. (ctrl-C)\n");
printf("\t[-c] 'count' : Sets the number of times the monitor will refresh\n");
printf("\t[-r] 'rate' : Sets the 'rate' at which the monitor will refresh per second\n");
return 0;
}
if (forever) {
for (;;) {
struct timespec req;
if (rate == 1) {
req.tv_sec = 1;
req.tv_nsec = 0;
} else {
req.tv_sec = 0;
req.tv_nsec = 1000000000 / rate;
}
nanosleep(&req, NULL);
monitor(conn);
}
} else if (countFlag) {
for (int i = 0; i < count; i++) {
result = monitor(conn);
struct timespec req;
if (rate == 1) {
req.tv_sec = 1;
req.tv_nsec = 0;
} else {
req.tv_sec = 0;
req.tv_nsec = 1000000000 / rate;
}
nanosleep(&req, NULL);
}
} else {
return monitor(conn);
}
return result;
}
int monitor(struct backend_conn * conn) {
static struct frontend_pid_data pid_data[PID_NUM_PIDS];
/* Get tracker data */
struct frontend_tracker_data td;
if (frontend_track(conn, &td)) {
errx(1, "Error reading tracker data");
}
if (monitorcounter == 0) {
for(int i = 0; i < PID_NUM_PIDS; ++i) {
pid_data[i].controller = i;
if (frontend_getpid(conn, &pid_data[i])) {
errx(1, "Error reading pid values");
}
}
} else {
if ((monitorcounter % (rate * 5)) == 0) {
pid_data[pidcounter].controller = pidcounter;
if (frontend_getpid(conn, &pid_data[pidcounter])) {
errx(1, "Error reading pid values");
}
}
}
/* Print stuff on screen */
/* Assuming a tab width of 8 columns */
printf("\033[2J");
printf("STATUS: NA\n");
printf("CTRLR : P R Y P_V R_V Y_V H LAT LON\n");
printf(" P :%10.3lf %10.3lf %10.3lf %10.3lf %10.3lf %10.3lf %10.3lf %10.3lf %10.3lf\n",
pid_data[0].p, pid_data[1].p, pid_data[2].p, pid_data[3].p, pid_data[4].p,
pid_data[5].p, pid_data[6].p, pid_data[7].p, pid_data[8].p);
printf(" I :%10.3lf %10.3lf %10.3lf %10.3lf %10.3lf %10.3lf %10.3lf %10.3lf %10.3lf\n",
pid_data[0].i, pid_data[1].i, pid_data[2].i, pid_data[3].i, pid_data[4].i,
pid_data[5].i, pid_data[6].i, pid_data[7].i, pid_data[8].i);
printf(" D :%10.3lf %10.3lf %10.3lf %10.3lf %10.3lf %10.3lf %10.3lf %10.3lf %10.3lf\n",
pid_data[0].d, pid_data[1].d, pid_data[2].d, pid_data[3].d, pid_data[4].d,
pid_data[5].d, pid_data[6].d, pid_data[7].d, pid_data[8].d);
printf("PosAtt: H LAT LON P R Y\n");
printf(" :%10.3lf%10.3lf%10.3lf%10.3lf%10.3lf%10.3lf\n",
td.height, td.lateral, td.longitudinal,
td.pitch, td.roll, td.yaw); //TODO: Tracker data long and lat are backwards
monitorcounter++;
pidcounter = ((pidcounter + 1) % PID_NUM_PIDS);
return 0;
}
#ifndef __CLI_MONITOR_H
#define __CLI_MONITOR_H
#include <time.h>
#include "frontend_getpid.h"
#define SECOND_IN_NANO 1000000000
int cli_monitor(struct backend_conn * conn, int argc, char **argv);
// Return 0 on success and 1 otherwise
int monitor(struct backend_conn * conn);
#endif /* __CLI_MONITOR_H */
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment