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

View File

@ -3678,6 +3678,7 @@ class SidebandApp(MDApp):
###################################### ######################################
def repository_action(self, sender=None, direction="left"): def repository_action(self, sender=None, direction="left"):
if self.repository_ready: if self.repository_ready:
self.repository_update_info()
self.repository_open(direction=direction) self.repository_open(direction=direction)
else: else:
self.loader_action(direction=direction) 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 += "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" 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 self.sideband.webshare_server != None:
if RNS.vendor.platformutils.is_android(): def getIP():
def getIP(): adrs = []
adrs = [] if RNS.vendor.platformutils.is_android():
try: try:
from jnius import autoclass from jnius import autoclass
import ipaddress import ipaddress
@ -3739,24 +3740,30 @@ class SidebandApp(MDApp):
RNS.log("Error while getting repository IP address: "+str(e), RNS.LOG_ERROR) RNS.log("Error while getting repository IP address: "+str(e), RNS.LOG_ERROR)
return None 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: else:
ipstr = "" import socket
for ip in ips: adrs.append(socket.gethostbyname(socket.gethostname()))
ipstr += "http://"+str(ip)+":4444/\n"
self.reposository_url = ipstr
ms = "" if len(ips) == 1 else "es" return adrs
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)
self.repository_screen.ids.repository_enable_button.disabled = True ips = getIP()
self.repository_screen.ids.repository_disable_button.disabled = False 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: else:
self.repository_screen.ids.repository_enable_button.disabled = False self.repository_screen.ids.repository_enable_button.disabled = False
@ -3778,39 +3785,85 @@ class SidebandApp(MDApp):
def update_job(sender=None): def update_job(sender=None):
try: try:
import requests 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 except Exception as e:
apk_version = None self.repository_screen.ids.repository_update.text = f"Downloading RNode firmware release info failed with the error:\n"+str(e)
apk_url = None return
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
self.repository_screen.ids.repository_update.text = "Downloading: "+str(apk_url) try:
with requests.get(apk_url, stream=True) as response: for download in downloads:
with open("./dl_tmp", "wb") as tmp_file: fw_url = download[0]
cs = 32*1024 pkgname = download[1]
tds = 0 self.repository_screen.ids.repository_update.text = "Downloading: "+str(pkgname)
for chunk in response.iter_content(chunk_size=cs): with requests.get(fw_url, stream=True) as response:
tmp_file.write(chunk) with open("./dl_tmp", "wb") as tmp_file:
tds += cs cs = 32*1024
self.repository_screen.ids.repository_update.text = "Downloaded "+RNS.prettysize(tds)+" of "+str(pkgname) 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: except Exception as e:
self.repository_screen.ids.repository_update.text = f"Downloading contents failed with the error:\n"+str(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.root.ids.screen_manager.add_widget(self.repository_screen)
self.repository_screen.ids.repository_scrollview.effect_cls = ScrollEffect self.repository_screen.ids.repository_scrollview.effect_cls = ScrollEffect
self.repository_update_info() 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 self.repository_ready = True
def close_repository_action(self, sender=None): 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> </head>
<body> <body>
<span class="logo">Guides</span> <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. Welcome to the <b>Guide Section</b>!<br/><br/>From here, you can browse or download various included manuals, documentation, references and guides.
<ul> <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_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> <li><a href="./mirrors/reticulum.network/index.html">Browse a local copy of the Reticulum website</a></li>
</ul> </ul>
<br/>
<hr> <hr>
<p><center></p> <p><center></p>
</body></html> </body></html>

View File

@ -10,7 +10,7 @@
</head> </head>
<body> <body>
<span class="logo">Sideband Repo</span> <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;"> <table style="margin-bottom: 1.5em;">
<tbody> <tbody>
<tr> <tr>

View File

@ -9,10 +9,10 @@
</head> </head>
<body> <body>
<span class="logo">Software</span> <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. 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 id="filelist">
</ul> </ul><br/>
<hr> <hr>
<p><center></p> <p><center></p>
</body></html> </body></html>

View File

@ -233,7 +233,11 @@ class SidebandCore():
self.log_dir = self.app_dir+"/app_storage/" self.log_dir = self.app_dir+"/app_storage/"
self.tmp_dir = self.app_dir+"/app_storage/tmp" self.tmp_dir = self.app_dir+"/app_storage/tmp"
self.exports_dir = self.app_dir+"/exports" 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.first_run = True
self.saving_configuration = False self.saving_configuration = False
@ -4653,7 +4657,7 @@ class SidebandCore():
self.send_response(200) self.send_response(200)
self.send_header("Content-type", "text/json") self.send_header("Content-type", "text/json")
self.end_headers() 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")) self.wfile.write(json_result.encode("utf-8"))
except Exception as e: except Exception as e:
self.send_response(500) self.send_response(500)
@ -4668,6 +4672,8 @@ class SidebandCore():
self.send_response(200) self.send_response(200)
if path.lower().endswith(".apk"): if path.lower().endswith(".apk"):
self.send_header("Content-type", "application/vnd.android.package-archive") 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.end_headers()
self.wfile.write(data) self.wfile.write(data)
except Exception as e: except Exception as e:
@ -4677,6 +4683,7 @@ class SidebandCore():
es = "Error" es = "Error"
self.wfile.write(es.encode("utf-8")) self.wfile.write(es.encode("utf-8"))
socketserver.TCPServer.allow_reuse_address = True
with socketserver.TCPServer(("", port), RequestHandler) as webserver: with socketserver.TCPServer(("", port), RequestHandler) as webserver:
self.webshare_server = webserver self.webshare_server = webserver
webserver.serve_forever() webserver.serve_forever()

View File

@ -9,6 +9,8 @@ from kivy.utils import escape_markup
from kivymd.uix.recycleview import MDRecycleView from kivymd.uix.recycleview import MDRecycleView
from kivymd.uix.list import OneLineIconListItem from kivymd.uix.list import OneLineIconListItem
from kivymd.uix.pickers import MDColorPicker 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.icon_definitions import md_icons
from kivymd.toast import toast from kivymd.toast import toast
from kivy.properties import StringProperty, BooleanProperty from kivy.properties import StringProperty, BooleanProperty
@ -48,6 +50,33 @@ class Utilities():
self.screen.ids.utilities_info.text = info 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 ### rnstatus screen
###################################### ######################################
@ -194,6 +223,17 @@ MDScreen:
on_release: root.delegate.logviewer_action(self) on_release: root.delegate.logviewer_action(self)
disabled: False 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: MDRectangleFlatIconButton:
id: advanced_button id: advanced_button
icon: "network-pos" icon: "network-pos"