Skip to content
Snippets Groups Projects
Commit 05915ddc authored by dmlarson's avatar dmlarson Committed by mkelly2
Browse files

Resolve "Create a Wifi Access Point on groundstation"

parent 8de60cfb
No related branches found
No related tags found
No related merge requests found
Showing
with 520 additions and 159 deletions
documentation/images/ls_output_wifiap.png

15.2 KiB

......@@ -92,14 +92,6 @@ There are a couple of already written bash scripts in the `scripts/` folder.
- [Getting Started](./documentation/getting_started.md)
- [Packet Information](./documentation/packets.md)
- [Manual Assist Mode](./src/manual_assist/README.md)
## Adapters
Adapters are the MicroCART way of connecting to generic trackables that are not one of the MicroCART quads. There is one
adapter created in house that allows the use of a Crazyflie through the Matt_test branch of [Custom_Crazyflie_Software](https://git.ece.iastate.edu/danc/Custom_CrazyFlie_Software/tree/Matt_test_branch) repo.
This repository is part of the DANC lab and can be access similar to the MicroCART repositry. This branch makes their ground
station allow connects in the same manner that our backend does. In order to use this adapter
you must first start the lateral on quad ground station in the repository mentioned above, then run the crazyflie adapter.
After this process is setup make sure that the backend config is set properly for this new trackable and it can be controlled
as if it were one of our quads.
- [Adapters](adapters/README.md)
- [WiFi Access Point](wifiap/README.md)
- [Manual Assist Mode](./src/manual_assist/README.md)
\ No newline at end of file
# ADAPTERS
Adapters are what allows for the current microcart groundstation to communicate with other vehicles. The adapters act as a translator by receiving packets from groundstation and then call the packets corrisponding callback. The developer can then modify callback functions to communicate.
Adapters are what allows for the current microcart groundstation to communicate with other vehicles. The adapters act as a translator by receiving packets from groundstation and then call the packets corresponding callback function. The developer can then modify callback functions to communicate.
There is one
adapter created in house that allows the use of a Crazyflie through the Matt_test branch of [Custom_Crazyflie_Software](https://git.ece.iastate.edu/danc/Custom_CrazyFlie_Software/tree/Matt_test_branch) repo.
This repository is part of the DANC lab and can be access similar to the MicroCART repositry. This branch makes their ground
station allow connects in the same manner that our backend does. In order to use this adapter
you must first start the lateral on quad ground station in the repository mentioned above, then run the crazyflie adapter.
After this process is setup make sure that the backend config is set properly for this new trackable and it can be controlled
as if it were one of our quads.
## CREATE NEW:
There are 3 major components that are provided for creation of a new custom adapter.
- adapterlib - has functions to retrieve single groundstation packets from a socket
- callbacks - has predefined functions for every type of instruction supported by groundstation
- demoadapter - example code to set up a unix socket, read from it, and call the corresponding callback function
These files rely upon groundstation header files and c files which are linked in the ./inc directory and should be included when compiling (for example see the crazyflie adapter makefile)
These files rely upon groundstation header files and c files which are linked by the makefile and should be included when compiling (for example see the crazyflie adapter makefile)
To create your own adapter:
......@@ -26,7 +35,7 @@ This is a list of what groundstation and quad software functions are required.
- commands.c - MessageTypes, findCommand()
- callbacks.h - Typedef for command_cb
###INCLUDES LOCATIONS:
### INCLUDES LOCATIONS:
This is a list of all the required files to include to be able to use the function listed above. *(Note these paths are relative to this README)*
- ../../quad/inc/biquad_filter.h
......
inc/*
bin/*
......@@ -23,7 +23,6 @@ all: inc obj lib
mkdir bin/
$(CC) obj/*.o -o bin/cf_adapter
obj: inc
$(CC) -c $(C) $(H) $(CFLAGS)
mkdir obj
......@@ -62,5 +61,3 @@ clean:
rm -rf *.o
rm -rf inc/*.gch
rm -rf src/*.gch
......@@ -413,11 +413,13 @@ void sendVrpnPacket(struct ucart_vrpn_TrackerData *info) {
void getVRPNPacket(struct ucart_vrpn_TrackerData *td) {
int status;
//for (int i = 0; i < NUM_TRACKABLES; i++) {
// if (strcmp(trackable, trackables[i].name) == 0) {
// break;
// }
//}
#if VRPN_DEBUG_PRINT == 1
for (int i = 0; i < NUM_TRACKABLES; i++) {
if (strcmp(trackable, trackables[i].name) == 0) {
break;
}
}
#endif
//if ((status = ucart_vrpn_tracker_getData(trackables[i].tracker, td)) < 0) {
// TODO - remove tracker instance
if((status = ucart_vrpn_tracker_getData(tracker, td)) < 0) {
......@@ -557,14 +559,15 @@ static ssize_t writeQuad(const uint8_t * buf, size_t count) {
for (int i = 0; i < NUM_TRACKABLES; i++) {
if (strcmp(trackables[i].name, trackable) == 0) {
index = i;
//printf("Index: %d\tName: %s\n", index, trackables[index].name);
//printf("packetToQuad = '");
//for(int i = 0; i < (int)count; ++i) {
// printf(" %.2x ", buf[i]);
//}
//printf("'\n");
#if BACKEND_DEBUG_PRINT == 1
printf("Index: %d\tName: %s\n", index, trackables[index].name);
printf("packetToQuad = '");
for(int i = 0; i < (int)count; ++i) {
printf(" %.2x ", buf[i]);
}
printf("'\n");
#endif
return writeQuadIndex(buf, count, index);
//break;
}
}
//FIXME - Should never reach here
......@@ -574,11 +577,13 @@ static ssize_t writeQuad(const uint8_t * buf, size_t count) {
static ssize_t writeQuadIndex(const uint8_t * buf, size_t count, int index) {
ssize_t retval;
//printf("packetToQuad = '");
//for(int i = 0; i < (int)count; ++i) {
// printf(" %.2x ", buf[i]);
//}
//printf("'\n");
#if BACKEND_DEBUG_PRINT == 1
printf("packetToQuad = '");
for(int i = 0; i < (int)count; ++i) {
printf(" %.2x ", buf[i]);
}
printf("'\n");
#endif
if (trackables[index].isAdapter == 0 && getenv(NOQUAD_ENV)) {
return count;
......@@ -760,10 +765,13 @@ static void client_recv(int fd) {
char * first_word;
char * tmp = strdup(buffer);
// printf("tmpbuff = '%s'\n", tmp);
#if BACKEND_DEBUG_PRINT == 1
printf("tmpbuff = '%s'\n", tmp);
#endif
first_word = strtok(tmp, " ");
// printf("first word = '%s'\n", first_word);
#if BACKEND_DEBUG_PRINT == 1
printf("first word = '%s'\n", first_word);
#endif
ssize_t msg_type, i;
for (i = 0; i < MAX_TYPE_ID; ++i) {
if ((msg_type = findCommand(first_word)) != -1)
......@@ -928,11 +936,13 @@ static void quad_recv(int index) {
}
respBufLen += respLen;
// printf("packetFromQuad = '");
// for(int i = 0; i < (int)respBufLen; ++i) {
// printf(" %.2x ", respBuf[i]);
// }
// printf("'\n");
#if BACKEND_DEBUG_PRINT == 1
printf("packetFromQuad = '");
for(int i = 0; i < (int)respBufLen; ++i) {
printf(" %.2x ", respBuf[i]);
}
printf("'\n");
#endif
while(respBufLen) {
datalen = DecodePacket(&m, data, CMD_MAX_LENGTH, respBuf, respBufLen);
......
......@@ -19,12 +19,14 @@
* count - number of bytes
*/
int adapterWrite(struct adapter_conn *conn, const char * line, size_t count) {
#if ADAPTER_DEBUG_PRINT == 1
//Print out packet being sent to the adapter.
//printf("packetToAdapter = '");
//for(int i = 0; i < count; ++i) {
// printf(" %.2x ", ((const uint8_t *) line)[i]);
//}
//printf("'\n");
printf("packetToAdapter = '");
for(int i = 0; i < count; ++i) {
printf(" %.2x ", ((const uint8_t *) line)[i]);
}
printf("'\n");
#endif
return fwrite((const uint8_t *) line, sizeof(uint8_t), count, conn->socket);
}
......
......@@ -16,6 +16,11 @@
#include <pthread.h>
#include <stdint.h>
#define FRONTEND_DEBUG_PRINT 0
#define ADAPTER_DEBUG_PRINT 0
#define VRPN_DEBUG_PRINT 0
#define BACKEND_DEBUG_PRINT 0
/**
* Socket used to communicate with the backend.
*/
......
......@@ -5,6 +5,7 @@
#include <inttypes.h>
#include "frontend_nodes.h"
#include "config.h"
/* Get the block_id, type_id and name of
* all of the nodes in the current comp_graph.
......@@ -17,80 +18,86 @@
*
*/
int frontend_getnodes(
struct backend_conn * conn,
struct frontend_node_data ** node_data,
size_t * num_nodes) {
if ((node_data == NULL) || (num_nodes == NULL)) {
return 1;
}
if ((*node_data != NULL) || (*num_nodes != 0)) {
return 1;
}
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;
}
}
struct frontend_node_data * arr = *node_data;
for (size_t i = 0; i < *num_nodes; ++i) {
sscanf(response, "%" SCNd16 " %n", &arr[i].block, (int*)&offset);
// printf("found block %d\n", arr[i].block);
response += offset;
}
for (size_t i = 0; i < *num_nodes; ++i) {
sscanf(response, "%" SCNd16 " %n", &arr[i].type, (int*)&offset);
// printf("found type %d\n", arr[i].type);
response += offset;
}
for (size_t i = 0; i < *num_nodes; ++i) {
char tmp_name[512];
sscanf(response, " '%[^\t\n']' %n", (char *)&tmp_name, (int *)&offset);
arr[i].name = malloc(sizeof(*arr[i].name) * strlen(tmp_name) + 1);
strcpy((char*)arr[i].name, tmp_name);
// printf("found name '%s'\n", arr[i].name);
response += offset;
}
pendingResponses--;
}
return 0;
struct backend_conn * conn,
struct frontend_node_data ** node_data,
size_t * num_nodes) {
if ((node_data == NULL) || (num_nodes == NULL)) {
return 1;
}
if ((*node_data != NULL) || (*num_nodes != 0)) {
return 1;
}
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;
}
}
struct frontend_node_data * arr = *node_data;
for (size_t i = 0; i < *num_nodes; ++i) {
sscanf(response, "%" SCNd16 " %n", &arr[i].block, (int*)&offset);
#if FRONTEND_DEBUG_PRINT == 1
printf("found block %d\n", arr[i].block);
#endif
response += offset;
}
for (size_t i = 0; i < *num_nodes; ++i) {
sscanf(response, "%" SCNd16 " %n", &arr[i].type, (int*)&offset);
#if FRONTEND_DEBUG_PRINT == 1
printf("found type %d\n", arr[i].type);
#endif
response += offset;
}
for (size_t i = 0; i < *num_nodes; ++i) {
char tmp_name[512];
sscanf(response, " '%[^\t\n']' %n", (char *)&tmp_name, (int *)&offset);
arr[i].name = malloc(sizeof(*arr[i].name) * strlen(tmp_name) + 1);
strcpy((char*)arr[i].name, tmp_name);
#if FRONTEND_DEBUG_PRINT == 1
printf("found name '%s'\n", arr[i].name);
#endif
response += offset;
}
pendingResponses--;
}
return 0;
}
/* Set the value of block.param
......@@ -98,46 +105,46 @@ int frontend_getnodes(
* 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;
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;
}
void frontend_free_node_data(
struct frontend_node_data *nd,
size_t num_nodes)
struct frontend_node_data *nd,
size_t num_nodes)
{
for (size_t i = 0; i < num_nodes; i++) {
free(nd[i].name);
}
free(nd);
for (size_t i = 0; i < num_nodes; i++) {
free(nd[i].name);
}
free(nd);
}
# WiFi Access Point
## Basic Setup
1. First install the necessary pacakges to the system
On Red Hat:
```bash
sudo yum install dhcp hostapd
```
2. Next navigate to the Microcart/groundStation/wifiap/ directory
3. Once you are in the directory make sure you have the necessary files
```bash
ls
```
4. The output should look something like the following image.
TODO image.
5. Next we will want to check for and backup the hostapd.conf file. The installer script will move the golden version of this file to the correct location.
```bash
ls /etc/hostapd/hostapd.conf
```
If the file exists you will see output that looks like the following move on to step 6
```bash
/etc/hostapd/hostapd.conf
```
If you get the following double check that hostapd is installed and if it is move on to step 7
```bash
ls: cannot access '/etc/hostapd/hostapd.conf': No such file or directory
```
6. Make a backup of the file with the following
```bash
sudo mv /etc/hostapd/hostapd.conf /etc/hostapd/hostapd.conf.backup
```
7. Next we will do the same for the dhcpd.conf file. Check that the file exists
```bash
ls /etc/dhcp/dhcpd.conf
```
If the file exists you will see output that looks like the following move on to step 8
```bash
/etc/dhcp/dhcpd.conf
```
If you get the following double check that dhcpd is installed and if it is move on to step 9
```bash
ls: cannot access '/etc/dhcp/dhcpd.conf': No such file or directory
```
8. Make a backup of the file with the following
```bash
sudo mv /etc/dhcp/dhcpd.conf /etc/dhcp/dhcpd.conf.backup
```
9. Next run the installerScript.sh with sudo rights
```bash
sudo ./installerScript.sh
```
10. You should now see output with all "OK" meaning that the script succeeded.
## How to Use
1. Run the start script with the following
```bash
sudo ./startAP.sh
```
You should now see a WiFi access point Microcart.
2. Make sure when you are done to run the following to stop
```bash
sudo ./stopAP.sh
```
INTERFACES="wlp2s0";
option domain-name "microcart.org";
subnet 192.168.1.0 netmask 255.255.255.0 {
range 192.168.1.10 192.168.1.20;
option subnet-mask 255.255.255.0;
option broadcast-address 192.168.1.255;
}
host quad1 {
hardware ethernet b8:d7:63:00:fe:ef;
fixed-address 192.168.1.2;
}
host quad2 {
hardware ethernet B8:D7:63:00:FE:F0;
fixed-address 192.168.1.3;
}
host phone {
hardware ethernet F4:09:D8:F1:6E:0E;
fixed-address 192.168.1.25;
}
#change wlan0 to your wireless device
interface=wlp2s0
driver=nl80211
ssid=MicroCART
hw_mode=g
channel=6
auth_algs=1
wpa=2
wpa_passphrase=m1cr0cart
wpa_key_mgmt=WPA-PSK
#!/bin/bash
if [[ $EUID -ne 0 ]]; then
printf "\nThis script must be run as root to move files around in etc and also run the hostapd service\n"
printf "\tRUN AS ROOT!\n"
exit 1
fi
printf "checking for hostapd..."
if ! type "hostapd" > /dev/null ; then
printf "\n\thostapd not found\n"
printf "\tINSTALL HOSTAPD PACKAGE!\n"
exit 1
fi
printf "\t OK!\n"
printf "moving golden_hostpad.conf to /etc/hostapd/hostapd.conf..."
if [ -f /etc/hostapd/hostapd.conf ]; then
printf "\n\tfile already exists! Please remove the hostapd.conf from the /etc/hostapd/ directory and try again!\n"
exit 1
fi
if [ ! -f ./golden_hostapd.conf ]; then
printf "\n\tcannot find the golden_hostapd.conf file in installer script's directory\n"
printf "\tRESTORE OR CREATE golden_hostapd.conf\n"
exit 1
fi
cp golden_hostapd.conf /etc/hostapd/hostapd.conf
#config must be owned by root root otherwise we get an SELinux violation
chown root /etc/hostapd/hostapd.conf
chgrp root /etc/hostapd/hostapd.conf
printf "\t OK!\n"
printf "checking for dhcpd..."
if ! type "dhcpd" > /dev/null ; then
printf "\n\tdhcpd not found\n"
printf "\tINSTALL DHCPD PACKAGE!\n"
exit 1
fi
printf "\t OK!\n"
printf "moving golden_dhcpd.conf to /etc/dhcp/dhcpd.conf..."
if [ -f /etc/dhcp/dhcpd.conf ]; then
printf "\n\tfile already exists! Please remove the dhcpd.conf from the /etc/dhcpd/ directory and try again!\n"
exit 1
fi
if [ ! -f ./golden_dhcpd.conf ]; then
printf "\n\tcannot find the golden_dhcpd.conf file in installer script's directory\n"
printf "\tRESTORE OR CREATE golden_dhcpd.conf\n"
exit 1
fi
cp golden_dhcpd.conf /etc/dhcp/dhcpd.conf
#config must be owned by root root otherwise we get an SELinux violation
chown root /etc/dhcp/dhcpd.conf
chgrp root /etc/dhcp/dhcpd.conf
printf "\t OK!\n"
#!/bin/bash
#SETTINGS
IP=192.168.1.1
if [[ $EUID -ne 0 ]]; then
printf "\nThis script must be run as root to run the hostapd service\n"
printf "\tRUN AS ROOT!\n"
exit 1
fi
printf "checking for hostapd...\n"
if ! type "hostapd" > /dev/null ; then
printf "\n\thostapd not found\n"
printf "\tINSTALL HOSTAPD PACKAGE AND RUN THE INSTALLER SCRIPT\n"
exit 1
fi
printf "\t OK!\n"
printf "checking for dhcpd...\n"
if ! type "dhcpd" > /dev/null ; then
printf "\n\thostapd not found\n"
printf "\tINSTALL DHCPD PACKAGE AND RUN THE INSTALLER SCRIPT\n"
exit 1
fi
printf "\t OK!\n"
printf "checking settings...\n"
if [ ! -f /etc/hostapd/hostapd.conf ]; then
printf "\n\tMISSING /etc/hostapd/hostapd.conf\n\tmodify golden_hostapd.conf and run the installer script\n"
exit 1
fi
printf "\t OK!\n"
printf "checking settings...\n"
if [ ! -f /etc/dhcp/dhcpd.conf ]; then
printf "\n\tMISSING /etc/dhcpd/dhcpd.conf\n\tmodify golden_dhcpd.conf and run the install script\n"
exit 1
fi
printf "\t OK!\n"
#printf "Setting ip to $IP\n"
#ifconfig wlp2s0 $IP
#printf "\t OK!\n"
printf "setting up wifi radio...\n"
nmcli radio wifi off
if [ $? -eq 0 ]; then
printf "\t OK!\n"
else
printf "\t FAIL!\n"
printf "\t \"nmcli radio wifi off\" command failed\n"
exit 1
fi
sleep 2
printf "setting up unblocking wifi...\n"
rfkill unblock wifi
if [ $? -eq 0 ]; then
printf "\t OK!\n"
else
printf "\t FAIL!\n"
printf "\t \"rfkill unblock wifi\" command failed\n\treverting wifi state\n"
nmcli radio wifi on
fi
printf "running the hostapd service...\n"
systemctl start hostapd.service
if [ $? -eq 0 ]; then
printf "\t OK!\n"
else
printf "\t FAIL!\n"
printf "\t failed to start hostapd service check run sudo systemctl start hostapd.service and check error messages\n\t reverting wifi state\n"
nmcli radio wifi on
exit 1
fi
printf "Setting ip to $IP\n"
ifconfig wlp2s0 $IP
printf "\t OK!\n"
printf "running the dhcpd service...\n"
systemctl start dhcpd.service
if [ $? -eq 0 ]; then
printf "\t OK!\n"
else
printf "\t FAIL!\n"
printf "\t failed to start dhcpd service check run sudo systemctl start dhcpd.service and check error messages\n\t reverting wifi state and stopping hostapd\n"
systemctl stop hostapd.service
nmcli radio wifi on
exit 1
fi
printf "hostapd and dhcpd should now be running, see if you can connect!\n"
#!/bin/bash
#SETTINGS
IP=192.168.0.1
if [[ $EUID -ne 0 ]]; then
printf "\nThis script must be run as root to run the hostapd service\n"
printf "\tRUN AS ROOT!\n"
exit 1
fi
printf "checking for and stopping running hostapd...\n"
if (( $(ps -ef | grep -v grep | grep hostapd | wc -l) > 0 )); then
systemctl stop hostapd.service
if [ $? -eq 0 ]; then
printf "\t OK!\n"
else
printf "\t FAIL!\n"
printf "\t failed to stop hostapd service may need to restart\n"
exit 1
fi
fi
printf "checking for and stopping the dhcpd service...\n"
if (( $(ps -ef | grep -v grep | grep dhcpd | wc -l) > 0 )); then
systemctl stop dhcpd.service
if [ $? -eq 0 ]; then
printf "\t OK!\n"
else
printf "\t FAIL!\n"
printf "\t failed to stop dhcpd service check run sudo systemct start dhcpd.service and check error messages\n"
exit 1
fi
fi
printf "setting up wifi radio...\n"
nmcli radio wifi on
if [ $? -eq 0 ]; then
printf "\t OK!\n"
else
printf "\t FAIL!\n"
printf "\t \"nmcli radio wifi on\" command failed\n"
exit 1
fi
printf "hostapd should now be off check to see if wifi is working!\n"
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