Skip to content

Commit

Permalink
Merge pull request #107 from Native-Planet/nallux_dev
Browse files Browse the repository at this point in the history
v1.0.3
  • Loading branch information
nallux-dozryl authored Jan 6, 2023
2 parents 253da48 + fc5c904 commit 37a7f86
Show file tree
Hide file tree
Showing 20 changed files with 618 additions and 93 deletions.
142 changes: 132 additions & 10 deletions api/groundseg.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,21 @@
import sys
import requests
import urllib.request
import nmcli
import subprocess
import html_templates

from datetime import datetime
from flask import Flask, jsonify, request, make_response
from flask import Flask, jsonify, request, make_response, render_template
from flask_cors import CORS
from werkzeug.utils import secure_filename
from PyAccessPoint import pyaccesspoint

from utils import Log
from utils import Log, Network
from orchestrator import Orchestrator

# Create flask app
app = Flask(__name__)
app = Flask(__name__, static_folder='/opt/nativeplanet/groundseg/static')
CORS(app, supports_credentials=True)

# Announce
Expand All @@ -28,6 +32,50 @@
# Load GroundSeg
orchestrator = Orchestrator("/opt/nativeplanet/groundseg/settings/system.json")

ssids = None
ap = pyaccesspoint.AccessPoint(wlan=orchestrator._wifi_device, ssid='NativePlanet_c2c', password='nativeplanet')

# Handle Connect to Connect
if orchestrator._c2c_mode:
try:
Log.log_groundseg(f"Turning wireless adapter {orchestrator._wifi_device} on")
nmcli.radio.wifi_on()
wifi_on = nmcli.radio.wifi()
while not wifi_on:
Log.log_groundseg("Wireless adapter not turned on yet. Trying again..")
nmcli.radio.wifi.on()
time.sleep(1)
wifi_on = nmcli.radio.wifi()

time.sleep(1)
Log.log_groundseg("Scanning for available SSIDs")
nmcli.device.wifi_rescan()
time.sleep(8)

ssids = Network.list_wifi_ssids()

if len(ssids) < 1:
Log.log_groundseg("No SSIDs available, exiting..")
sys.exit()

Log.log_groundseg(f"Available SSIDs: {ssids}")
Log.log_groundseg("Stopping systemd-resolved")
x = subprocess.check_output("systemctl stop systemd-resolved", shell=True)
if x.decode('utf-8') == '':
if ap.stop():
if ap.start():
Log.log_groundseg("Access Point enabled")
else:
Log.log_groundseg("Unable to start Access Point. Exiting..")
sys.exit()
else:
Log.log_groundseg("Something went wrong. Exiting..")
sys.exit()
except Exception as e:
Log.log_groundseg(f"Connect to connect error: {e}")
Log.log_groundseg("Exiting..")
sys.exit()

# Docker Updater
def check_docker_updates():
Log.log_groundseg("Docker updater thread started")
Expand Down Expand Up @@ -62,7 +110,6 @@ def check_docker_updates():
if img == minio:
Log.log_groundseg("Updating MinIOs")
orchestrator.reload_minios()

except:
pass

Expand Down Expand Up @@ -215,12 +262,24 @@ def meld_loop():

time.sleep(30)

def c2c_kill_switch():
interval = orchestrator.config['c2cInterval']
if interval != 0:
Log.log_groundseg(f"Connect to connect interval detected! Restarting device in {interval} seconds")
time.sleep(orchestrator.config['c2cInterval'])
os.system("reboot")
else:
Log.log_groundseg("Connect to connect interval not set!")

# Threads
threading.Thread(target=check_docker_updates).start() # Docker updater
threading.Thread(target=check_bin_updates).start() # Binary updater
threading.Thread(target=sys_monitor).start() # System monitoring
threading.Thread(target=meld_loop).start() # Meld loop
threading.Thread(target=anchor_information).start() # Anchor information
if not orchestrator._c2c_mode:
threading.Thread(target=check_docker_updates).start() # Docker updater
threading.Thread(target=check_bin_updates).start() # Binary updater
threading.Thread(target=sys_monitor).start() # System monitoring
threading.Thread(target=meld_loop).start() # Meld loop
threading.Thread(target=anchor_information).start() # Anchor information
else:
threading.Thread(target=c2c_kill_switch).start # Reboot device after delay

#
# Endpoints
Expand Down Expand Up @@ -464,6 +523,69 @@ def setup():

return jsonify(res)

# c2c
@app.route("/", methods=['GET','POST'])
def c2c():
if orchestrator._c2c_mode:
if request.method == 'GET':
return html_templates.home_page(ssids) ##render_template('connect.html', ssids=ssids)
if request.method == 'POST':
Log.log_groundseg("Connect to Connect: Restarting device")
os.system("reboot")
return jsonify(200)

return jsonify(404)

@app.route("/connect/<ssid>", methods=['GET','POST'])
def c2ssid(ssid=None):
if orchestrator._c2c_mode:

if request.method == 'GET':
return html_templates.connect_page(ssid)

if request.method == 'POST':
Log.log_groundseg(f"Requested to connect to SSID: {ssid}")
Log.log_groundseg(f"Turning off Access Point")

# turn off ap
try:
if ap.stop():
Log.log_groundseg("Starting systemd-resolved")
x = subprocess.check_output("systemctl start systemd-resolved", shell=True)
if x.decode('utf-8') == '':
nmcli.radio.wifi_on()
wifi_on = nmcli.radio.wifi()

while not wifi_on:
Log.log_groundseg("Wireless adapter not turned on yet. Trying again..")
nmcli.radio.wifi.on()
time.sleep(1)
wifi_on = nmcli.radio.wifi()

time.sleep(1)
Log.log_groundseg("Scanning for available SSIDs")
nmcli.device.wifi_rescan()
time.sleep(8)
Log.log_groundseg(f"Available SSIDs: {Network.list_wifi_ssids()}")

completed = Network.wifi_connect(ssid, request.form['password'])
Log.log_groundseg(f"Connection to wifi network {completed}")

if completed == "success" and orchestrator.config['c2cInterval'] == 0:
orchestrator.config['c2cInterval'] = 600
orchestrator.save_config()

os.system("reboot")
return jsonify(200)
except Exception as e:
Log.log_groundseg(f"An error has occurred: {e}")
Log.log_groundseg("Restarting device..")
os.system("reboot")
return jsonify(404)

if __name__ == '__main__':
port = 27016
if orchestrator._c2c_mode:
port = 80
debug_mode = False
app.run(host='0.0.0.0', port=27016, threaded=True, debug=debug_mode, use_reloader=debug_mode)
app.run(host='0.0.0.0', port=port, threaded=True, debug=debug_mode, use_reloader=debug_mode)
213 changes: 213 additions & 0 deletions api/html_templates.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
head = """\n
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>GroundSeg Connect to Connect</title>
<style>
@font-face {
font-family: Inter;
src: url('/static/Inter-SemiBold.otf')
}
body {
font-family: Inter;
margin: 0;
width: 100vw;
height: 100vh;
background: url("/static/background.png") no-repeat center center fixed;
-webkit-background-size: contain;
-moz-background-size: contain;
-o-background-size: contain;
background-size: contain;
background-color: #040404;
}
.card::-webkit-scrollbar {display: none;}
.card {
font-family: inherit;
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: #fff;
border-radius: 20px;
background: #6d6d6d33;
backdrop-filter: blur(60px);
-moz-backdrop-filter: blur(60px);
-o-backdrop-filter: blur(60px);
-webkit-backdrop-filter: blur(60px);
-ms-overflow-style: none;
scrollbar-width: none;
overflow: scroll;
padding-bottom: 20px;
min-width: 400px;
max-width: 100vw;
max-height: 80vh;
}
.logo {
padding: 20px;
}
img {
height: 32px;
float: left;
}
.text {
font-size: 14px;
padding-left: 18px;
line-height: 32px;
}
.title {
font-size: 14px;
font-weight: 700;
padding-bottom: 12px;
text-align: center;
}
a.ssid {
display: block;
font-family: inherit;
font-size: 13px;
width: 400px;
-webkit-appearance: button;
-moz-appearance: button;
appearance: button;
text-decoration: none;
text-align: left;
border: none;
background: none;
color: white;
padding: 16px 0 16px 20px;
}
.ssid + .ssid:before {
border-top: solid 1px #ffffff4d;
}
a.back {
-webkit-appearance: button;
-moz-appearance: button;
appearance: button;
text-decoration: none;
background: #ffffff4d;
color: white;
font-family: inherit;
border-radius: 6px;
border: none;
padding: 8px 0 8px 0;
width: 80px;
font-size: 12px;
text-align: center;
margin-left: 20px;
}
a:hover {
cursor: pointer;
}
a.ssid:hover {
background: #0404044d;
}
form {
display: inline;
}
button.rescan {
float: right;
background: #ffffff4d;
color: white;
font-family: inherit;
border-radius: 6px;
border: none;
width: 80px;
padding: 8px;
font-size: 12px;
}
button.connect {
display: block;
float: right;
background: #008EFF;
color: white;
font-family: inherit;
border-radius: 6px;
border: none;
padding: 8px;
width: 80px;
margin-right: 20px;
font-size: 12px
}
input {
font-family: inherit;
color: white;
display: block;
text-align: center;
width: 400px;
margin: 0 20px 20px 20px;
padding: 8px;
font-size: 12px;
border: none;
border-radius: 8px;
background: #ffffff4d;
}
input::placeholder {
color: white;
}
input:focus {
outline: none;
}
button:hover {
cursor: pointer;
}
.sep {
height: 0;
width: 100%;
border-bottom: solid 1px #ffffff4d;
}
</style>
</head>
"""

def home_page(ssids):
formatted_ssids = ''.join(list(map(lambda z: f'<a class="ssid" href="/connect/{z}">{z}</a><div class="sep"></div>', ssids)))

body = f"""\n
{head}
<body>
<div class="card">
<!-- Header -->
<div class="logo">
<a href="/"><img src="/static/nplogo.svg" alt="Native Planet Logo" /></a>
<span class="text">Select a Wireless Network</span>
<form action="/" method="post">
<button class="rescan" type="submit">Restart</button>
</form>
</div>
<!-- List of SSIDs -->
<div class="title">Available Networks</div>
<div class="sep"></div>
{formatted_ssids}
</div>
</body>
"""

return body

def connect_page(ssid):

body = f"""\n
{head}
<body>
<div class="card">
<!-- Header -->
<div class="logo" >
<a href="/"><img src="/static/nplogo.svg" alt="Native Planet Logo" /></a>
<span class="text">{ssid}</span>
<form action="/" method="post">
<button class="rescan" type="submit">Restart</button>
</form>
</div>
<form method="post">
<input type="text" placeholder="Password for {ssid}" name="password" />
<a class="back" href="/">Back</a>
<button class="connect" type="submit">Connect</button>
</form>
</div>
</body>
"""

return body
Loading

0 comments on commit 37a7f86

Please sign in to comment.