Enabled Repository server on desktop. Added RNode Flasher to utilities. Added RNode firmware downloads to repository update action.

This commit is contained in:
Mark Qvist 2024-12-10 20:24:09 +01:00
parent 79ad4bb353
commit 55baede2fc
8 changed files with 191 additions and 64 deletions

View File

@ -7,7 +7,7 @@ clean:
-(rm ./__pycache__ -r)
-(rm ./app_storage -r)
-(rm ./share/pkg/* -r)
-(rm ./share/mirrors/* -r)
-(rm ./share/mirrors/* -rf)
-(rm ./bin -r)
cleanlibs:
@ -64,13 +64,14 @@ fetchshare:
cp ../../dist_archive/lxmf-*-py3-none-any.whl ./share/pkg/
cp ../../dist_archive/nomadnet-*-py3-none-any.whl ./share/pkg/
cp ../../dist_archive/rnsh-*-py3-none-any.whl ./share/pkg/
# cp ../../dist_archive/sbapp-*-py3-none-any.whl ./share/pkg/
cp ../../dist_archive/RNode_Firmware_*_Source.zip ./share/pkg/
zip --junk-paths ./share/pkg/example_plugins.zip ../docs/example_plugins/*.py
cp -r ../../dist_archive/reticulum.network ./share/mirrors/
cp -r ../../dist_archive/unsigned.io ./share/mirrors/
cp ../../dist_archive/Reticulum\ Manual.pdf ./share/mirrors/Reticulum_Manual.pdf
cp ../../dist_archive/Reticulum\ Manual.epub ./share/mirrors/Reticulum_Manual.epub
cp -r ../../rnode-flasher ./share/mirrors/
-(rm ./share/mirrors/rnode-flasher/.git -rf)
release:
buildozer android release

View File

@ -3678,6 +3678,7 @@ class SidebandApp(MDApp):
######################################
def repository_action(self, sender=None, direction="left"):
if self.repository_ready:
self.repository_update_info()
self.repository_open(direction=direction)
else:
self.loader_action(direction=direction)
@ -3714,9 +3715,9 @@ class SidebandApp(MDApp):
info += "If you want to share the Sideband application itself via the repository server, you must first download it into the local repository, using the \"Update Content\" button below.\n\n"
info += "To make the repository available on your local network, simply start it below, and it will become browsable on a local IP address for anyone connected to the same WiFi or wired network.\n\n"
if self.sideband.webshare_server != None:
if RNS.vendor.platformutils.is_android():
def getIP():
adrs = []
def getIP():
adrs = []
if RNS.vendor.platformutils.is_android():
try:
from jnius import autoclass
import ipaddress
@ -3739,24 +3740,30 @@ class SidebandApp(MDApp):
RNS.log("Error while getting repository IP address: "+str(e), RNS.LOG_ERROR)
return None
return adrs
ips = getIP()
if ips == None or len(ips) == 0:
info += "The repository server is running, but the local device IP address could not be determined.\n\nYou can access the repository by pointing a browser to: http://DEVICE_IP:4444/"
self.reposository_url = None
else:
ipstr = ""
for ip in ips:
ipstr += "http://"+str(ip)+":4444/\n"
self.reposository_url = ipstr
import socket
adrs.append(socket.gethostbyname(socket.gethostname()))
ms = "" if len(ips) == 1 else "es"
info += "The repository server is running at the following address"+ms+":\n [u][ref=link]"+ipstr+"[/ref][u]"
self.repository_screen.ids.repository_info.bind(on_ref_press=self.repository_link_action)
return adrs
self.repository_screen.ids.repository_enable_button.disabled = True
self.repository_screen.ids.repository_disable_button.disabled = False
ips = getIP()
if ips == None or len(ips) == 0:
info += "The repository server is running, but the local device IP address could not be determined.\n\nYou can access the repository by pointing a browser to: http://DEVICE_IP:4444/"
self.reposository_url = None
else:
ipstr = ""
for ip in ips:
ipstr += "http://"+str(ip)+":4444/\n"
self.reposository_url = ipstr
ms = "" if len(ips) == 1 else "es"
info += "The repository server is running at the following address"+ms+":\n [u][ref=link]"+ipstr+"[/ref][u]"
self.repository_screen.ids.repository_info.bind(on_ref_press=self.repository_link_action)
def cb(dt):
self.repository_screen.ids.repository_enable_button.disabled = True
self.repository_screen.ids.repository_disable_button.disabled = False
Clock.schedule_once(cb, 0.1)
else:
self.repository_screen.ids.repository_enable_button.disabled = False
@ -3778,39 +3785,85 @@ class SidebandApp(MDApp):
def update_job(sender=None):
try:
import requests
### RNode Firmwares ###########
if True:
downloads = []
try:
release_url = "https://api.github.com/repos/markqvist/rnode_firmware/releases"
with requests.get(release_url) as response:
releases = response.json()
release = releases[0]
assets = release["assets"]
for asset in assets:
if asset["name"].lower().startswith("rnode_firmware"):
fw_url = asset["browser_download_url"]
pkgname = asset["name"]
fw_version = release["tag_name"]
RNS.log(f"Found version {fw_version} artefact {pkgname} at {fw_url}", RNS.LOG_DEBUG)
downloads.append([fw_url, pkgname, fw_version])
# Get release info
apk_version = None
apk_url = None
pkgname = None
try:
release_url = "https://api.github.com/repos/markqvist/sideband/releases"
with requests.get(release_url) as response:
releases = response.json()
release = releases[0]
assets = release["assets"]
for asset in assets:
if asset["name"].lower().endswith(".apk"):
apk_url = asset["browser_download_url"]
pkgname = asset["name"]
apk_version = release["tag_name"]
RNS.log(f"Found version {apk_version} artefact {pkgname} at {apk_url}")
except Exception as e:
self.repository_screen.ids.repository_update.text = f"Downloading release info failed with the error:\n"+str(e)
return
except Exception as e:
self.repository_screen.ids.repository_update.text = f"Downloading RNode firmware release info failed with the error:\n"+str(e)
return
self.repository_screen.ids.repository_update.text = "Downloading: "+str(apk_url)
with requests.get(apk_url, stream=True) as response:
with open("./dl_tmp", "wb") as tmp_file:
cs = 32*1024
tds = 0
for chunk in response.iter_content(chunk_size=cs):
tmp_file.write(chunk)
tds += cs
self.repository_screen.ids.repository_update.text = "Downloaded "+RNS.prettysize(tds)+" of "+str(pkgname)
try:
for download in downloads:
fw_url = download[0]
pkgname = download[1]
self.repository_screen.ids.repository_update.text = "Downloading: "+str(pkgname)
with requests.get(fw_url, stream=True) as response:
with open("./dl_tmp", "wb") as tmp_file:
cs = 32*1024
tds = 0
for chunk in response.iter_content(chunk_size=cs):
tmp_file.write(chunk)
tds += cs
self.repository_screen.ids.repository_update.text = "Downloaded "+RNS.prettysize(tds)+" of "+str(pkgname)
os.rename("./dl_tmp", f"{self.sideband.webshare_dir}/pkg/{pkgname}")
self.repository_screen.ids.repository_update.text = f"Added {pkgname} to the repository!"
except Exception as e:
self.repository_screen.ids.repository_update.text = f"Downloading RNode firmware failed with the error:\n"+str(e)
return
### Sideband APK File #########
if True:
# Get release info
apk_version = None
apk_url = None
pkgname = None
try:
release_url = "https://api.github.com/repos/markqvist/sideband/releases"
with requests.get(release_url) as response:
releases = response.json()
release = releases[0]
assets = release["assets"]
for asset in assets:
if asset["name"].lower().endswith(".apk"):
apk_url = asset["browser_download_url"]
pkgname = asset["name"]
apk_version = release["tag_name"]
RNS.log(f"Found version {apk_version} artefact {pkgname} at {apk_url}", RNS.LOG_DEBUG)
except Exception as e:
self.repository_screen.ids.repository_update.text = f"Downloading Sideband APK release info failed with the error:\n"+str(e)
return
self.repository_screen.ids.repository_update.text = "Downloading: "+str(pkgname)
with requests.get(apk_url, stream=True) as response:
with open("./dl_tmp", "wb") as tmp_file:
cs = 32*1024
tds = 0
for chunk in response.iter_content(chunk_size=cs):
tmp_file.write(chunk)
tds += cs
self.repository_screen.ids.repository_update.text = "Downloaded "+RNS.prettysize(tds)+" of "+str(pkgname)
os.rename("./dl_tmp", f"{self.sideband.webshare_dir}/pkg/{pkgname}")
self.repository_screen.ids.repository_update.text = f"Added {pkgname} to the repository!"
self.repository_screen.ids.repository_update.text = f"Repository contents updated successfully!"
os.rename("./dl_tmp", f"./share/pkg/{pkgname}")
self.repository_screen.ids.repository_update.text = f"Added {pkgname} to the repository!"
except Exception as e:
self.repository_screen.ids.repository_update.text = f"Downloading contents failed with the error:\n"+str(e)
@ -3827,15 +3880,7 @@ class SidebandApp(MDApp):
self.root.ids.screen_manager.add_widget(self.repository_screen)
self.repository_screen.ids.repository_scrollview.effect_cls = ScrollEffect
self.repository_update_info()
if not RNS.vendor.platformutils.is_android():
self.widget_hide(self.repository_screen.ids.repository_enable_button)
self.widget_hide(self.repository_screen.ids.repository_disable_button)
self.widget_hide(self.repository_screen.ids.repository_download_button)
self.repository_screen.ids.repository_info.text = "\nThe [b]Repository Webserver[/b] feature is currently only available on mobile devices."
self.repository_ready = True
def close_repository_action(self, sender=None):

33
sbapp/share/flasher.html Normal file
View File

@ -0,0 +1,33 @@
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="css/water.css">
<link rel="shortcut icon" type="image/x-icon" href="gfx/icon.png">
<meta charset="utf-8"/>
<title>Sideband Repository</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<span class="logo">RNode Flasher</span>
<p><center><span class="menu"><a href="index.html">Start</a> | <a href="flasher.html">RNode Flasher</a> | <a href="pkgs.html">Software</a> | <a href="guides.html">Guides</a></span></center></p><hr>
<br/>Sideband includes a copy of the web-based RNode Flasher developed by <a href="https://github.com/liamcottle/rnode-flasher">Liam Cottle</a>. You can use this flasher to install and provision the RNode firmware on any compatible boards.<br/>
<br/>
<b>Please note!</b> Your browser must support Web-USB for this to work.<br/>
<br/>
To use the flasher, you will need firmware packages for the boards you want use. You can obtain these in different ways:
<ul>
<li>Sideband can automatically download the latest release of these, and include them directly in this repository.
<ul>
<li>To do so, go to the <b>Repository</b> menu item, and select <b>Update Contents</b>.</li>
<li>After that, they will be available on the <a href="pkgs.html">Software</a> page of this repository.</li>
</ul>
</li>
<li>You can download them manually from <a href="https://github.com/markqvist/RNode_Firmware/releases/latest">the latest release page on GitHub</a>.</li>
<li>You can compile them yourself from the RNode Firmware source code package <a href="pkgs.html">included in this repository</a>.</li>
</ul>
<br/>
<center><a href="/mirrors/rnode-flasher/index.html"><button type="button" id="task-replicate">Launch Web Flasher</button></a></center>
<br/>
<hr>
<p><center></p>
</body></html>

View File

@ -9,7 +9,7 @@
</head>
<body>
<span class="logo">Guides</span>
<p><center><span class="menu"><a href="index.html">Start</a> | <a href="pkgs.html">Software</a> | <a href="guides.html">Guides</a></span></center></p><hr>
<p><center><span class="menu"><a href="index.html">Start</a> | <a href="flasher.html">RNode Flasher</a> | <a href="pkgs.html">Software</a> | <a href="guides.html">Guides</a></span></center></p><hr><br/>
Welcome to the <b>Guide Section</b>!<br/><br/>From here, you can browse or download various included manuals, documentation, references and guides.
<ul>
@ -19,6 +19,7 @@ Welcome to the <b>Guide Section</b>!<br/><br/>From here, you can browse or downl
<li><a href="./mirrors/Reticulum_Manual.epub">Download the Reticulum Manual in EPUB format</a></li>
<li><a href="./mirrors/reticulum.network/index.html">Browse a local copy of the Reticulum website</a></li>
</ul>
<br/>
<hr>
<p><center></p>
</body></html>

View File

@ -10,7 +10,7 @@
</head>
<body>
<span class="logo">Sideband Repo</span>
<p><center><span class="menu"><a href="index.html">Start</a> | <a href="pkgs.html">Software</a> | <a href="guides.html">Guides</a></span></center></p><hr><h2>Hello!</h2>
<p><center><span class="menu"><a href="index.html">Start</a> | <a href="flasher.html">RNode Flasher</a> | <a href="pkgs.html">Software</a> | <a href="guides.html">Guides</a></span></center></p><hr><h2>Hello!</h2>
<table style="margin-bottom: 1.5em;">
<tbody>
<tr>

View File

@ -9,10 +9,10 @@
</head>
<body>
<span class="logo">Software</span>
<p><center><span class="menu"><a href="index.html">Start</a> | <a href="pkgs.html">Software</a> | <a href="guides.html">Guides</a></span></center></p><hr>
<p><center><span class="menu"><a href="index.html">Start</a> | <a href="flasher.html">RNode Flasher</a> | <a href="pkgs.html">Software</a> | <a href="guides.html">Guides</a></span></center></p><hr><br/>
Welcome to the <b>Software Library</b>!<br/><br/>From here, you can download installable Python Wheel packages of Reticulum and various other auxillary programs and utilities.
<ul id="filelist">
</ul>
</ul><br/>
<hr>
<p><center></p>
</body></html>

View File

@ -233,7 +233,11 @@ class SidebandCore():
self.log_dir = self.app_dir+"/app_storage/"
self.tmp_dir = self.app_dir+"/app_storage/tmp"
self.exports_dir = self.app_dir+"/exports"
self.webshare_dir = "./share/"
if RNS.vendor.platformutils.is_android():
self.webshare_dir = "./share/"
else:
sideband_dir = os.path.dirname(os.path.abspath(__file__))
self.webshare_dir = os.path.abspath(os.path.join(sideband_dir, "..", "share"))
self.first_run = True
self.saving_configuration = False
@ -4653,7 +4657,7 @@ class SidebandCore():
self.send_response(200)
self.send_header("Content-type", "text/json")
self.end_headers()
json_result = json.dumps(os.listdir(serve_root+"/pkg"))
json_result = json.dumps(sorted(os.listdir(serve_root+"/pkg")))
self.wfile.write(json_result.encode("utf-8"))
except Exception as e:
self.send_response(500)
@ -4668,6 +4672,8 @@ class SidebandCore():
self.send_response(200)
if path.lower().endswith(".apk"):
self.send_header("Content-type", "application/vnd.android.package-archive")
elif path.lower().endswith(".js"):
self.send_header("Content-type", "text/javascript")
self.end_headers()
self.wfile.write(data)
except Exception as e:
@ -4677,6 +4683,7 @@ class SidebandCore():
es = "Error"
self.wfile.write(es.encode("utf-8"))
socketserver.TCPServer.allow_reuse_address = True
with socketserver.TCPServer(("", port), RequestHandler) as webserver:
self.webshare_server = webserver
webserver.serve_forever()

View File

@ -9,6 +9,8 @@ from kivy.utils import escape_markup
from kivymd.uix.recycleview import MDRecycleView
from kivymd.uix.list import OneLineIconListItem
from kivymd.uix.pickers import MDColorPicker
from kivymd.uix.button import MDRectangleFlatButton
from kivymd.uix.dialog import MDDialog
from kivymd.icon_definitions import md_icons
from kivymd.toast import toast
from kivy.properties import StringProperty, BooleanProperty
@ -48,6 +50,33 @@ class Utilities():
self.screen.ids.utilities_info.text = info
### RNode Flasher
######################################
def flasher_action(self, sender=None):
yes_button = MDRectangleFlatButton(text="Launch",font_size=dp(18), theme_text_color="Custom", line_color=self.app.color_accept, text_color=self.app.color_accept)
no_button = MDRectangleFlatButton(text="Back",font_size=dp(18))
dialog = MDDialog(
title="RNode Flasher",
text="You can use the included web-based RNode flasher, by starting Sideband's built-in repository server, and accessing the RNode Flasher page.",
buttons=[ no_button, yes_button ],
# elevation=0,
)
def dl_yes(s):
dialog.dismiss()
self.app.sideband.start_webshare()
def cb(dt):
self.app.repository_action()
Clock.schedule_once(cb, 0.6)
def dl_no(s):
dialog.dismiss()
yes_button.bind(on_release=dl_yes)
no_button.bind(on_release=dl_no)
dialog.open()
### rnstatus screen
######################################
@ -194,6 +223,17 @@ MDScreen:
on_release: root.delegate.logviewer_action(self)
disabled: False
MDRectangleFlatIconButton:
id: flasher_button
icon: "radio-handheld"
text: "RNode Flasher"
padding: [dp(0), dp(14), dp(0), dp(14)]
icon_size: dp(24)
font_size: dp(16)
size_hint: [1.0, None]
on_release: root.delegate.flasher_action(self)
disabled: False
MDRectangleFlatIconButton:
id: advanced_button
icon: "network-pos"