first init
This commit is contained in:
8
.gitignore
vendored
Normal file
8
.gitignore
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
secrets.yml
|
||||||
|
__pycache__
|
||||||
|
venv
|
||||||
|
pids/
|
||||||
|
logs/
|
||||||
|
.ipynb_checkpoints
|
||||||
|
packages
|
||||||
|
*.ipynb
|
||||||
0
brain/__init__.py
Normal file
0
brain/__init__.py
Normal file
8
brain/brain.py
Normal file
8
brain/brain.py
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
from brain_openai import CloudChatBrain
|
||||||
|
|
||||||
|
|
||||||
|
brain = CloudChatBrain()
|
||||||
|
while True:
|
||||||
|
brain.listen()
|
||||||
|
brain.understand()
|
||||||
|
brain.command()
|
||||||
74
brain/brain_openai.py
Normal file
74
brain/brain_openai.py
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
import os
|
||||||
|
import sys
|
||||||
|
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||||
|
import json
|
||||||
|
import ast
|
||||||
|
|
||||||
|
import openai
|
||||||
|
|
||||||
|
from commander.commands import CommandHandler
|
||||||
|
from settings.config import settings
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class CloudSTTBrain:
|
||||||
|
def __init__(self):
|
||||||
|
print("not implemented")
|
||||||
|
|
||||||
|
|
||||||
|
class CloudChatBrain:
|
||||||
|
def __init__(self):
|
||||||
|
openai.api_key = settings.OPENAI_API_KEY
|
||||||
|
self.command_handler = CommandHandler()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def sys_prompt(self):
|
||||||
|
return self._read_prompt()
|
||||||
|
|
||||||
|
def _read_prompt(self):
|
||||||
|
prompt_file_name = "prompt.txt"
|
||||||
|
for root, dirs, files in os.walk("./"):
|
||||||
|
if prompt_file_name in files:
|
||||||
|
prompt_filepath = os.path.join(root, prompt_file_name)
|
||||||
|
with open(prompt_filepath, "r") as f:
|
||||||
|
return f.read()
|
||||||
|
|
||||||
|
def _is_valid_json(self, answer):
|
||||||
|
try:
|
||||||
|
response_json = json.loads(answer)
|
||||||
|
return True
|
||||||
|
except ValueError as e:
|
||||||
|
print(f"chatgpt failed to return json obj: {answer}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
def _gc(self):
|
||||||
|
self.cmd_prompt = None
|
||||||
|
self.response = None
|
||||||
|
|
||||||
|
def listen(self):
|
||||||
|
self.cmd_prompt = input("\n\nwhat should I do now?\n\t")
|
||||||
|
|
||||||
|
def understand(self):
|
||||||
|
self.response = openai.ChatCompletion.create(
|
||||||
|
model="gpt-3.5-turbo",
|
||||||
|
temperature=0.2,
|
||||||
|
messages=[
|
||||||
|
{"role": "system", "content": self.sys_prompt},
|
||||||
|
{"role": "user", "content": self.cmd_prompt}
|
||||||
|
])
|
||||||
|
|
||||||
|
def command(self):
|
||||||
|
answer = self.response.choices[0].message.content
|
||||||
|
if self._is_valid_json(answer):
|
||||||
|
command = ast.literal_eval(answer)
|
||||||
|
if command == {}:
|
||||||
|
print(f"I failed to understand: {command}")
|
||||||
|
else:
|
||||||
|
print(f"I will send this command: {command}")
|
||||||
|
self.command_handler.handle(command)
|
||||||
|
else:
|
||||||
|
print(f"\tI will skip this:\n {command}")
|
||||||
|
self._gc()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
18
brain/prompt.txt
Normal file
18
brain/prompt.txt
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
You are a flight controller API endpoint in a quadcopter.
|
||||||
|
Your receive commands are in Turkish.
|
||||||
|
Only provide a RFC8259 compliant JSON response following this format without deviation in order to translate regular speech commands. If you get a command not related to below schema you return empty JSON object {} and nothing else.
|
||||||
|
CommandSchema:
|
||||||
|
"command" : string
|
||||||
|
"direction": string
|
||||||
|
"distance_angle": int
|
||||||
|
|
||||||
|
You only recognize,
|
||||||
|
- commands: move, turn, takeoff, land
|
||||||
|
- direction: up, down, left, right, forward, back
|
||||||
|
- distance_angle: ant integer value
|
||||||
|
|
||||||
|
For any "move" command distance_angle should be defaulted to 25.
|
||||||
|
for any "turn" command the distance_angle should be defaulted to 30.
|
||||||
|
Never mention being a Language Model AI or any notes. You must only respond with JSON. Do no write normal text.
|
||||||
|
|
||||||
|
The JSON response:
|
||||||
0
commander/__init__.py
Normal file
0
commander/__init__.py
Normal file
26
commander/commander.py
Normal file
26
commander/commander.py
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
# source: https://djitellopy.readthedocs.io/en/latest/tello/
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
|
|
||||||
|
from fastapi import FastAPI
|
||||||
|
import uvicorn
|
||||||
|
|
||||||
|
from routes.base import api_router
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def start_application():
|
||||||
|
app = FastAPI()
|
||||||
|
app.include_router(api_router)
|
||||||
|
return app
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
if len(sys.argv) == 1:
|
||||||
|
port = 8889
|
||||||
|
else:
|
||||||
|
port = int(sys.argv[1])
|
||||||
|
|
||||||
|
app = start_application()
|
||||||
|
uvicorn.run(app, host="0.0.0.0", port=port, log_level="debug")
|
||||||
56
commander/commands.py
Normal file
56
commander/commands.py
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
import requests
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class CommandHandler:
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.COMMANDER_ROOT_URL = "http://0.0.0.0:8889"
|
||||||
|
self.COMMANDER_COMMANDS_URL = f"{self.COMMANDER_ROOT_URL}/command"
|
||||||
|
self._check_commander_health()
|
||||||
|
|
||||||
|
def _check_commander_health(self):
|
||||||
|
response = requests.get(f"{self.COMMANDER_ROOT_URL}/test/health")
|
||||||
|
status = response.json()
|
||||||
|
if status["msg"] != "ok":
|
||||||
|
raise Exception(f"commander service is unavailable: {self.COMMANDER_ROOT_URL}")
|
||||||
|
|
||||||
|
def _move(self, direction, distance):
|
||||||
|
response = requests.get(f"{self.COMMANDER_COMMANDS_URL}/move/{direction}/{distance}")
|
||||||
|
print(response.json())
|
||||||
|
|
||||||
|
def _turn(self, direction, degree):
|
||||||
|
response = requests.get(f"{self.COMMANDER_COMMANDS_URL}/turn/{direction}/{degree}")
|
||||||
|
print(response.json())
|
||||||
|
|
||||||
|
def _takeoff(self):
|
||||||
|
response = requests.get(f"{self.COMMANDER_COMMANDS_URL}/takeoff")
|
||||||
|
print(response.json())
|
||||||
|
|
||||||
|
def _land(self):
|
||||||
|
response = requests.get(f"{self.COMMANDER_COMMANDS_URL}/land")
|
||||||
|
print(response.json())
|
||||||
|
|
||||||
|
def _end_session(self):
|
||||||
|
response = requests.get(f"{self.COMMANDER_COMMANDS_URL}/end")
|
||||||
|
print(response.json())
|
||||||
|
|
||||||
|
def handle(self, cmd: dict):
|
||||||
|
#print(f"commanding for: {cmd}")
|
||||||
|
if cmd["command"] == "move":
|
||||||
|
self._move(
|
||||||
|
direction=cmd["direction"],
|
||||||
|
distance=cmd["distance_angle"]
|
||||||
|
)
|
||||||
|
elif cmd["command"] == "turn":
|
||||||
|
self._turn(
|
||||||
|
direction=cmd["direction"],
|
||||||
|
degree=cmd["distance_angle"]
|
||||||
|
)
|
||||||
|
elif cmd["command"] == "takeoff":
|
||||||
|
self._takeoff()
|
||||||
|
elif cmd["command"] == "land":
|
||||||
|
self._land()
|
||||||
|
else:
|
||||||
|
raise ValueError(f"Uknown command object: {cmd}")
|
||||||
0
commander/routes/__init__.py
Normal file
0
commander/routes/__init__.py
Normal file
9
commander/routes/base.py
Normal file
9
commander/routes/base.py
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
from fastapi import APIRouter
|
||||||
|
from routes import route_test, route_command
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
api_router = APIRouter()
|
||||||
|
|
||||||
|
api_router.include_router(route_test.router, prefix="/test", tags=["tests"])
|
||||||
|
api_router.include_router(route_command.router, prefix="/command", tags=["commands"])
|
||||||
106
commander/routes/route_command.py
Normal file
106
commander/routes/route_command.py
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
import asyncio, time
|
||||||
|
import threading
|
||||||
|
|
||||||
|
from fastapi import APIRouter, Query, BackgroundTasks
|
||||||
|
from djitellopy import Tello
|
||||||
|
|
||||||
|
|
||||||
|
class FlightStatsCollector:
|
||||||
|
def __init__(self):
|
||||||
|
self.stats_thread = None
|
||||||
|
self.stop_event = threading.Event()
|
||||||
|
|
||||||
|
def start_collecting(self):
|
||||||
|
self.stats_thread = threading.Thread(target=self.collect_stats)
|
||||||
|
self.stats_thread.start()
|
||||||
|
|
||||||
|
def stop_collecting(self):
|
||||||
|
self.stop_event.set()
|
||||||
|
if self.stats_thread:
|
||||||
|
self.stats_thread.join()
|
||||||
|
|
||||||
|
def collect_stats(self):
|
||||||
|
while not self.stop_event.is_set():
|
||||||
|
tello.send_command_with_return("command")
|
||||||
|
bat = tello.get_battery()
|
||||||
|
temp = tello.get_temperature()
|
||||||
|
# wsnr = tello.query_wifi_signal_noise_ratio()
|
||||||
|
print(f"bat: {bat} - temp: {temp}") #- wsnr: {wsnr}")
|
||||||
|
time.sleep(5)
|
||||||
|
|
||||||
|
router = APIRouter()
|
||||||
|
tello = Tello()
|
||||||
|
stats_collector = FlightStatsCollector()
|
||||||
|
|
||||||
|
|
||||||
|
def land_on_low_battery():
|
||||||
|
bat_level = tello.get_battery()
|
||||||
|
if bat_level < 20:
|
||||||
|
tello.land()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/takeoff")
|
||||||
|
def takeoff():
|
||||||
|
try:
|
||||||
|
tello.connect()
|
||||||
|
except Exception as e:
|
||||||
|
return {"msg": "failed to connect"}
|
||||||
|
|
||||||
|
if tello.is_flying:
|
||||||
|
return {"msg": "already flying"}
|
||||||
|
|
||||||
|
tello.takeoff()
|
||||||
|
stats_collector.start_collecting()
|
||||||
|
|
||||||
|
if tello.is_flying:
|
||||||
|
return {"msg": "ok"}
|
||||||
|
else:
|
||||||
|
return {"msg": "takeoff failed"}
|
||||||
|
|
||||||
|
@router.get("/land")
|
||||||
|
def land():
|
||||||
|
if not tello.is_flying:
|
||||||
|
return {"msg": "already on land"}
|
||||||
|
|
||||||
|
tello.land()
|
||||||
|
stats_collector.stop_collecting()
|
||||||
|
|
||||||
|
if not tello.is_flying:
|
||||||
|
return {"msg": "ok"}
|
||||||
|
|
||||||
|
@router.get("/turn/{direction}/{degree}")
|
||||||
|
def turn(direction: str, degree: int):
|
||||||
|
if direction not in ["left", "right"]:
|
||||||
|
return {"direction must be only left or right"}
|
||||||
|
if degree < 1 or degree > 360:
|
||||||
|
return {"degree must be between 1 and 360"}
|
||||||
|
|
||||||
|
if direction == "right":
|
||||||
|
tello.rotate_clockwise(degree)
|
||||||
|
elif direction == "left":
|
||||||
|
tello.rotate_counter_clockwise(degree)
|
||||||
|
|
||||||
|
return {"msg": "ok"}
|
||||||
|
|
||||||
|
@router.get("/move/{direction}/{distance}")
|
||||||
|
def turn(direction: str, distance: int):
|
||||||
|
if direction not in ["back", "forward", "left", "right", "up" , "down"]:
|
||||||
|
return {"direction must be only back, forward, left, right up or down"}
|
||||||
|
if distance < 20 or distance > 200:
|
||||||
|
return {"distance must be between 20 and 500"}
|
||||||
|
|
||||||
|
try:
|
||||||
|
tello.move(direction, distance)
|
||||||
|
except Exception as e:
|
||||||
|
return {
|
||||||
|
"msg": "command failed",
|
||||||
|
"reason": e
|
||||||
|
}
|
||||||
|
|
||||||
|
return {"msg": "ok"}
|
||||||
|
|
||||||
|
@router.get("/end")
|
||||||
|
def end_flight_session():
|
||||||
|
tello.end()
|
||||||
|
return {"msg": "ok"}
|
||||||
74
commander/routes/route_test.py
Normal file
74
commander/routes/route_test.py
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
import asyncio, time
|
||||||
|
|
||||||
|
from fastapi.websockets import WebSocket
|
||||||
|
from fastapi.responses import HTMLResponse
|
||||||
|
from fastapi import APIRouter
|
||||||
|
from djitellopy import Tello
|
||||||
|
|
||||||
|
|
||||||
|
router = APIRouter()
|
||||||
|
tello = Tello()
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/health")
|
||||||
|
def test():
|
||||||
|
return {"msg": "ok"}
|
||||||
|
|
||||||
|
@router.get("/flight")
|
||||||
|
def test_flight():
|
||||||
|
try:
|
||||||
|
tello.connect()
|
||||||
|
except Exception as e:
|
||||||
|
return {"msg": "failed to connect"}
|
||||||
|
tello.takeoff()
|
||||||
|
if not tello.is_flying:
|
||||||
|
return {"msg": "failed to take off"}
|
||||||
|
tello.rotate_counter_clockwise(180)
|
||||||
|
time.sleep(2)
|
||||||
|
tello.rotate_clockwise(180)
|
||||||
|
time.sleep(5)
|
||||||
|
tello.land()
|
||||||
|
if not tello.is_flying:
|
||||||
|
return {"msg": "succesfully landed"}
|
||||||
|
else:
|
||||||
|
return {"msg": "landing failed, still flying!!!"}
|
||||||
|
|
||||||
|
@router.get("/continuous-response")
|
||||||
|
async def test_continuous_response():
|
||||||
|
return HTMLResponse(html_template)
|
||||||
|
|
||||||
|
@router.websocket("/ws")
|
||||||
|
async def websocket_endpoint(websocket: WebSocket):
|
||||||
|
await websocket.accept()
|
||||||
|
async for message in generate_output():
|
||||||
|
await websocket.send_text(message)
|
||||||
|
|
||||||
|
|
||||||
|
async def generate_output():
|
||||||
|
for i in range(10):
|
||||||
|
await asyncio.sleep(1)
|
||||||
|
yield f"Progress: {i + 1}\n"
|
||||||
|
yield "Done!\n"
|
||||||
|
|
||||||
|
|
||||||
|
html_template = """
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Websocket Example</title>
|
||||||
|
<script>
|
||||||
|
var ws = new WebSocket("ws://" + window.location.host + "/test/ws");
|
||||||
|
|
||||||
|
ws.onmessage = function(event) {
|
||||||
|
var progress_log = document.getElementById("progress-log");
|
||||||
|
progress_log.innerHTML += event.data + "<br>";
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Websocket Example</h1>
|
||||||
|
<p>Progress:</p>
|
||||||
|
<div id="progress-log"></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
"""
|
||||||
25
install.sh
Executable file
25
install.sh
Executable file
@@ -0,0 +1,25 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
|
||||||
|
ARCH=$(uname -m)
|
||||||
|
|
||||||
|
if [ "$ARCH" = "x86_64" ]; then
|
||||||
|
ARCH="amd64"
|
||||||
|
|
||||||
|
elif [ "$ARCH" = "armv6l" ]; then
|
||||||
|
ARCH="arm"
|
||||||
|
|
||||||
|
fi
|
||||||
|
echo "found architecture $ARCH"; sleep 3
|
||||||
|
|
||||||
|
rm yq_linux_* && \
|
||||||
|
wget https://github.com/mikefarah/yq/releases/download/v4.33.3/yq_linux_$ARCH && \
|
||||||
|
mv yq_linux_$ARCH yq && \
|
||||||
|
chmod +x yq && \
|
||||||
|
mv yq /home/uad/.local/bin
|
||||||
|
|
||||||
|
echo "installing virtualenv"; sleep 3
|
||||||
|
|
||||||
|
virtualenv venv
|
||||||
|
pip install -r requirements.txt
|
||||||
|
|
||||||
158
manage.sh
Executable file
158
manage.sh
Executable file
@@ -0,0 +1,158 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
|
||||||
|
DRONE_INTERFACE=$(yq '.commander.drone_interface' < config.yml)
|
||||||
|
DRONE_WPA_SUPP_CONF=$(yq '.commander.drone_wpa_supp' < config.yml)
|
||||||
|
NET_INTERFACE=$(yq '.commander.net_interface' < config.yml)
|
||||||
|
NET_WPA_SUPP_CONF=$(yq '.commander.net_wpa_supp' < config.yml)
|
||||||
|
|
||||||
|
|
||||||
|
list_related_network_interface_status() {
|
||||||
|
networkctl list
|
||||||
|
}
|
||||||
|
|
||||||
|
list_wifi_ssid(){
|
||||||
|
sudo iw dev $DRONE_INTERFACE scan | grep "SSID: "
|
||||||
|
}
|
||||||
|
|
||||||
|
connect_using_wpa_supp() {
|
||||||
|
sudo wpa_supplicant -D nl80211 -i $DRONE_INTERFACE -c network/$DRONE_WPA_SUPP_CONF
|
||||||
|
}
|
||||||
|
|
||||||
|
get_dhcp_ip () {
|
||||||
|
sudo dhclient $DRONE_INTERFACE
|
||||||
|
}
|
||||||
|
|
||||||
|
start_jupyter() {
|
||||||
|
venv/bin/python -m jupyter lab --ip='0.0.0.0' --NotebookApp.token='' --NotebookApp.password='' --no-browser --port=8888
|
||||||
|
}
|
||||||
|
|
||||||
|
start_codeserver(){
|
||||||
|
packages/code-server/code-server-4.12.0-linux-amd64/bin/code-server --config /home/uad/misc/tello-commander/packages/code-server/config.yaml --disable-getting-started-override --disable-workspace-trust --disable-telemetry ./
|
||||||
|
}
|
||||||
|
|
||||||
|
start_commander_service() {
|
||||||
|
venv/bin/python commander/commander.py $1
|
||||||
|
}
|
||||||
|
|
||||||
|
kill_everything() {
|
||||||
|
for p in $pids_dir/*.txt; do echo "killing $p"; pkill $(cat "$p"); done
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
pids_dir='./pids'
|
||||||
|
if [[ ! -d "$pids_dir" ]]; then
|
||||||
|
mkdir $pids_dir
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## NETWORK
|
||||||
|
if [ "$1" == "list-network" ]; then
|
||||||
|
list_related_network_interface_status
|
||||||
|
|
||||||
|
elif [ "$1" == "list-wifis" ]; then
|
||||||
|
list_wifi_ssid #connect $2 $3
|
||||||
|
|
||||||
|
elif [ "$1" == "connect-drone" ]; then
|
||||||
|
connect_using_wpa_supp > logs/wpa_supp.log 2>&1 &
|
||||||
|
wpa_supp_pid=$!
|
||||||
|
echo "started wpa supplicant to connect drone network with PID $wpa_supp_pid"
|
||||||
|
echo $wpa_supp_pid > $pids_dir/wpa_supp_pid.txt
|
||||||
|
|
||||||
|
elif [ "$1" == "disconnect-drone" ]; then
|
||||||
|
wpa_supp_pid_file="$pids_dir/wpa_supp_pid.txt"
|
||||||
|
if [ -f "$wpa_supp_pid_file" ]; then
|
||||||
|
pkill -P $(cat $wpa_supp_pid_file)
|
||||||
|
echo "stopped drone connection via wpa_supp"
|
||||||
|
fi
|
||||||
|
|
||||||
|
elif [ "$1" == "get-dhcp" ]; then
|
||||||
|
get_dhcp_ip > logs/dhcp_ip.log 2>&1 &
|
||||||
|
dhcp_ip_pid=$!
|
||||||
|
echo "requested ip address from drone router with PID $dhcp_ip_pid"
|
||||||
|
echo $dhcp_ip_pid > $pids_dir/dhcp_ip_pid.txt
|
||||||
|
|
||||||
|
elif [ "$1" == "kill-dhcp" ]; then
|
||||||
|
dhcp_ip_pid_file="$pids_dir/dhcp_ip_pid.txt"
|
||||||
|
if [ -f "$dhcp_ip_pid_file" ]; then
|
||||||
|
pkill -P $(cat $dhcp_ip_pid_file)
|
||||||
|
echo "killed dhcp client"
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
## DEV
|
||||||
|
elif [ "$1" == "start-jupyter" ]; then
|
||||||
|
start_jupyter > logs/jupyter.log 2>&1 &
|
||||||
|
jupyter_pid=$!
|
||||||
|
echo "started jupyter with PID $jupyter_pid"
|
||||||
|
echo $jupyter_pid > $pids_dir/jupyter_pid.txt
|
||||||
|
#tail -f logs/jupyter.log
|
||||||
|
|
||||||
|
elif [ "$1" == "stop-jupyter" ]; then
|
||||||
|
jupyter_pid_file="$pids_dir/jupyter_pid.txt"
|
||||||
|
if [ -f "$jupyter_pid_file" ]; then
|
||||||
|
pkill -P $(cat $jupyter_pid_file)
|
||||||
|
echo "stopped jupyter"
|
||||||
|
fi
|
||||||
|
|
||||||
|
elif [ "$1" == "start-cs" ]; then
|
||||||
|
start_codeserver > logs/codeserver.log 2>&1 &
|
||||||
|
codeserver_pid=$!
|
||||||
|
echo "started code server with PID $codeserver_pid"
|
||||||
|
echo $codeserver_pid > $pids_dir/codeserver_pid.txt
|
||||||
|
#tail -f logs/codeserver.log
|
||||||
|
|
||||||
|
elif [ "$1" == "stop-cs" ]; then
|
||||||
|
codeserver_pid_file="$pids_dir/codeserver_pid.txt"
|
||||||
|
if [ -f "$codeserver_pid_file" ]; then
|
||||||
|
pkill -P $(cat $codeserver_pid_file)
|
||||||
|
echo "stopped code server"
|
||||||
|
fi
|
||||||
|
|
||||||
|
elif [ "$1" == "stop-all" ]; then
|
||||||
|
kill_everything
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## DRONE
|
||||||
|
elif [ "$1" == "start-commander" ]; then
|
||||||
|
start_commander_service $2 > logs/commander.log 2>&1 &
|
||||||
|
commander_pid=$!
|
||||||
|
echo "started commander with PID $commander_pid"
|
||||||
|
echo $commander_pid > $pids_dir/commander_pid.txt
|
||||||
|
#tail -f logs/commander.log
|
||||||
|
|
||||||
|
elif [ "$1" == "stop-commander" ]; then
|
||||||
|
commander_pid_file="$pids_dir/commander_pid.txt"
|
||||||
|
if [ -f "$commander_pid_file" ]; then
|
||||||
|
pkill -P $(cat $commander_pid_file)
|
||||||
|
echo "stopped commander"
|
||||||
|
fi
|
||||||
|
|
||||||
|
elif [ "$1" == "prepare-flight" ]; then
|
||||||
|
./manage.sh connect-drone
|
||||||
|
./manage.sh get-dhcp
|
||||||
|
./manage.sh start-commander
|
||||||
|
echo "prepared to flight"
|
||||||
|
|
||||||
|
elif [ "$1" == "finish-flight" ]; then
|
||||||
|
./manage.sh disconnect-drone
|
||||||
|
./manage.sh kill-dhcp
|
||||||
|
./manage.sh stop-commander
|
||||||
|
echo "flight finished"
|
||||||
|
exit 0
|
||||||
|
|
||||||
|
else
|
||||||
|
echo "Invalid command. Please use one of:
|
||||||
|
- list-network
|
||||||
|
- list-wifis
|
||||||
|
- connect-/ disconnect-drone
|
||||||
|
- get-/ kill-dhcp
|
||||||
|
- start-/ stop-jupyter
|
||||||
|
- start-/ stop-cs
|
||||||
|
- start-/ stop-commander [port]
|
||||||
|
- stop-all
|
||||||
|
- prepare-/ finish-flight"
|
||||||
|
fi
|
||||||
4
network/wpa_supp_djituad0_plus.conf
Normal file
4
network/wpa_supp_djituad0_plus.conf
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
network={
|
||||||
|
ssid="djituad0_plus"
|
||||||
|
psk="0000000000"
|
||||||
|
}
|
||||||
4
network/wpa_supp_uadis.conf
Normal file
4
network/wpa_supp_uadis.conf
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
network={
|
||||||
|
ssid="uadis"
|
||||||
|
psk="0000000000"
|
||||||
|
}
|
||||||
0
requirements.txt
Normal file
0
requirements.txt
Normal file
12
settings/config.py
Normal file
12
settings/config.py
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
from dynaconf import Dynaconf
|
||||||
|
|
||||||
|
# --- DynaConf ---------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
settings = Dynaconf(
|
||||||
|
envvar_prefix="TELLO_COMMANDER",
|
||||||
|
environments=True,
|
||||||
|
settings_files=[
|
||||||
|
'settings/secrets.yml',
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
10
settings/config.yml
Normal file
10
settings/config.yml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
commander:
|
||||||
|
drone_interface:
|
||||||
|
wlx14cc201488aa
|
||||||
|
net_interface:
|
||||||
|
wlan0
|
||||||
|
drone_wpa_supp:
|
||||||
|
wpa_supp_djituad0_plus.conf
|
||||||
|
net_wpa_supp:
|
||||||
|
wpa_supp_uadis.conf
|
||||||
|
|
||||||
Reference in New Issue
Block a user