mirror of
https://github.com/janishutz/BiogasControllerApp.git
synced 2025-11-25 05:44:23 +00:00
Config, Lots of docs, Format
Added a config validator and documented code that was previously undocumented, for the plot_generator scripts, documented them.
This commit is contained in:
5
gui/README.md
Normal file
5
gui/README.md
Normal file
@@ -0,0 +1,5 @@
|
||||
# GUI
|
||||
This folder contains all files that are used for the GUI of the app.
|
||||
|
||||
It is written in KivyMD, so if you don't know what that is and you don't want to learn it,
|
||||
there isn't much of use in here for you! - Just so you're warned
|
||||
@@ -4,25 +4,35 @@ from kivymd.uix.button import MDFlatButton
|
||||
from kivy.lang import Builder
|
||||
import webbrowser
|
||||
|
||||
|
||||
# Simple about screen
|
||||
class AboutScreen(Screen):
|
||||
def __init__(self, **kw):
|
||||
# Prepare dialog
|
||||
self.opened_web_browser_dialog = MDDialog(
|
||||
title="Open Link",
|
||||
text="Your webbrowser has been opened. Continue there",
|
||||
buttons=[
|
||||
MDFlatButton(text="Ok", on_release=lambda _: self.opened_web_browser_dialog.dismiss()),
|
||||
MDFlatButton(
|
||||
text="Ok",
|
||||
on_release=lambda _: self.opened_web_browser_dialog.dismiss(),
|
||||
),
|
||||
],
|
||||
)
|
||||
super().__init__(**kw)
|
||||
|
||||
def goto(self, loc: str):
|
||||
# Open web browser with links
|
||||
if loc == "wiki":
|
||||
webbrowser.open('https://github.com/janishutz/BiogasControllerApp/wiki', new=2)
|
||||
webbrowser.open(
|
||||
"https://github.com/janishutz/BiogasControllerApp/wiki", new=2
|
||||
)
|
||||
elif loc == "issues":
|
||||
webbrowser.open('https://github.com/janishutz/BiogasControllerApp/issues', new=2)
|
||||
webbrowser.open(
|
||||
"https://github.com/janishutz/BiogasControllerApp/issues", new=2
|
||||
)
|
||||
elif loc == "repo":
|
||||
webbrowser.open('https://github.com/janishutz/BiogasControllerApp', new=2)
|
||||
webbrowser.open("https://github.com/janishutz/BiogasControllerApp", new=2)
|
||||
self.opened_web_browser_dialog.open()
|
||||
|
||||
Builder.load_file('./gui/about/about.kv')
|
||||
|
||||
Builder.load_file("./gui/about/about.kv")
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
from kivy.base import Clock
|
||||
from kivymd.app import MDApp
|
||||
from kivymd.uix.button import MDFlatButton
|
||||
from kivymd.uix.dialog import MDDialog
|
||||
@@ -48,9 +49,7 @@ class HomeScreen(MDScreen):
|
||||
text="Cancel",
|
||||
on_release=lambda _: self.quit_dialog.dismiss(),
|
||||
),
|
||||
MDFlatButton(
|
||||
text="Quit", on_release=lambda _: self._quit()
|
||||
),
|
||||
MDFlatButton(text="Quit", on_release=lambda _: self._quit()),
|
||||
],
|
||||
)
|
||||
super().__init__(**kw)
|
||||
@@ -59,9 +58,12 @@ class HomeScreen(MDScreen):
|
||||
self._com.close()
|
||||
MDApp.get_running_app().stop()
|
||||
|
||||
def start(self):
|
||||
Clock.schedule_once(lambda _: self._start())
|
||||
|
||||
# Go to the main screen if we can establish connection or the check was disabled
|
||||
# in the configs
|
||||
def start(self):
|
||||
def _start(self):
|
||||
if self._com.connect():
|
||||
self.manager.current = "main"
|
||||
self.manager.transition.direction = "right"
|
||||
@@ -94,7 +96,6 @@ class HomeScreen(MDScreen):
|
||||
"13"
|
||||
] = f"Incorrect permissions at {port}. Resolve by running 'sudo chmod 777 {port}'"
|
||||
|
||||
|
||||
if port == "":
|
||||
return information[operating_system]["NO_COM"]
|
||||
|
||||
|
||||
@@ -112,6 +112,7 @@ class MainScreen(MDScreen):
|
||||
self._event = None
|
||||
self._fast_mode = False
|
||||
|
||||
# Set up Dialog for erros
|
||||
self.connection_error_dialog = MDDialog(
|
||||
title="Connection",
|
||||
text="Failed to connect. Do you wish to retry?",
|
||||
@@ -144,28 +145,39 @@ class MainScreen(MDScreen):
|
||||
super().__init__(**kw)
|
||||
|
||||
def _prepare_reader(self):
|
||||
# Prepares the reader thread
|
||||
self._reader = ReaderThread()
|
||||
self._reader.daemon = True
|
||||
self._reader.set_com(self._com)
|
||||
|
||||
# Start the connection to the micro-controller to read data from it.
|
||||
# This also now starts the reader thread to continuously read out data
|
||||
# Small helper function that makes the UI not freeze by offloading
|
||||
def start(self):
|
||||
Clock.schedule_once(lambda _: self._start())
|
||||
|
||||
# Start the connection to the micro-controller to read data from it.
|
||||
# This also starts the reader thread to continuously read out data
|
||||
def _start(self):
|
||||
# Prevent running multiple times
|
||||
self.connection_error_dialog.dismiss()
|
||||
if self._has_connected:
|
||||
return
|
||||
|
||||
# Some UI config
|
||||
self.ids.status.text = "Connecting..."
|
||||
if self._com.connect():
|
||||
print("[ COM ] Connection Acquired")
|
||||
|
||||
# Prevent multiple connections
|
||||
self._has_connected = True
|
||||
self._has_run = True
|
||||
if self._has_run:
|
||||
self._prepare_reader()
|
||||
|
||||
# Start communication
|
||||
self._reader.start()
|
||||
print("[ COM ] Reader has started")
|
||||
|
||||
# Schedule UI updates
|
||||
self._event = Clock.schedule_interval(self._update_screen, 0.5)
|
||||
else:
|
||||
self.ids.status.text = "Connection failed"
|
||||
@@ -179,15 +191,20 @@ class MainScreen(MDScreen):
|
||||
if self._event != None:
|
||||
self._event.cancel()
|
||||
self._reader.stop()
|
||||
|
||||
# Join the thread to end it safely
|
||||
try:
|
||||
self._reader.join()
|
||||
except:
|
||||
pass
|
||||
|
||||
# Go back to Normal Mode on the Controller
|
||||
# This is so you don't accidentally forget!
|
||||
try:
|
||||
self._com.send("NM")
|
||||
except:
|
||||
pass
|
||||
|
||||
self._com.close()
|
||||
if set_msg:
|
||||
self.ids.status.text = "Connection terminated"
|
||||
@@ -202,18 +219,24 @@ class MainScreen(MDScreen):
|
||||
update = synced_queue.get_nowait()
|
||||
except:
|
||||
pass
|
||||
|
||||
if len(update) == 0:
|
||||
# There are no updates to process, don't block and simply try again next time
|
||||
return
|
||||
|
||||
if len(update) == 1:
|
||||
# Sync errors
|
||||
if update[0] == "ERR_HOOK":
|
||||
self.ids.status.text = "Hook failed"
|
||||
self.end(False)
|
||||
|
||||
if len(update) == 2:
|
||||
# Connection successful
|
||||
if update[0] == "HOOK":
|
||||
self.ids.status.text = "Connected to controller"
|
||||
self.ids.port.text = "Port: " + update[1]
|
||||
else:
|
||||
# Update the UI
|
||||
self.ids.sensor1.text = update[0]
|
||||
self.ids.sensor2.text = update[1]
|
||||
self.ids.sensor3.text = update[2]
|
||||
|
||||
@@ -20,15 +20,16 @@ class ProgramScreen(MDScreen):
|
||||
self._instructions = Instructions(com)
|
||||
self._decoder = Decoder()
|
||||
|
||||
# Configure Dialog
|
||||
self.connection_error_dialog = MDDialog(
|
||||
title="Connection",
|
||||
text="Failed to connect. Do you wish to retry?",
|
||||
buttons=[
|
||||
MDFlatButton(
|
||||
text="Cancel",
|
||||
on_release=lambda dt: self.connection_error_dialog.dismiss(),
|
||||
on_release=lambda _: self.connection_error_dialog.dismiss(),
|
||||
),
|
||||
MDFlatButton(text="Retry", on_release=lambda dt: self._load()),
|
||||
MDFlatButton(text="Retry", on_release=lambda _: self.load_config()),
|
||||
],
|
||||
)
|
||||
|
||||
@@ -38,7 +39,7 @@ class ProgramScreen(MDScreen):
|
||||
buttons=[
|
||||
MDFlatButton(
|
||||
text="Ok",
|
||||
on_release=lambda dt: self.missing_fields_error_dialog.dismiss(),
|
||||
on_release=lambda _: self.missing_fields_error_dialog.dismiss(),
|
||||
),
|
||||
],
|
||||
)
|
||||
@@ -49,7 +50,7 @@ class ProgramScreen(MDScreen):
|
||||
buttons=[
|
||||
MDFlatButton(
|
||||
text="Ok",
|
||||
on_release=lambda dt: self.save_error_dialog.dismiss(),
|
||||
on_release=lambda _: self.save_error_dialog.dismiss(),
|
||||
),
|
||||
],
|
||||
)
|
||||
@@ -60,15 +61,16 @@ class ProgramScreen(MDScreen):
|
||||
buttons=[
|
||||
MDFlatButton(
|
||||
text="Ok",
|
||||
on_release=lambda dt: self.save_success_dialog.dismiss(),
|
||||
on_release=lambda _: self.save_success_dialog.dismiss(),
|
||||
),
|
||||
],
|
||||
)
|
||||
|
||||
super().__init__(**kw)
|
||||
|
||||
# Load the config (async to not freeze the UI)
|
||||
def load_config(self):
|
||||
Clock.schedule_once(lambda dt: self._load())
|
||||
Clock.schedule_once(lambda _: self._load())
|
||||
|
||||
# Load the current configuration from the micro-controller
|
||||
def _load(self):
|
||||
@@ -131,8 +133,11 @@ class ProgramScreen(MDScreen):
|
||||
|
||||
return data
|
||||
|
||||
# Transmit the changed data to the micro-controller to reconfigure it
|
||||
def save(self):
|
||||
Clock.schedule_once(lambda _: self._save())
|
||||
|
||||
# Transmit the changed data to the micro-controller to reconfigure it
|
||||
def _save(self):
|
||||
self.ids.status.text = "Saving..."
|
||||
data = self._read_ui()
|
||||
if data == None:
|
||||
@@ -140,14 +145,14 @@ class ProgramScreen(MDScreen):
|
||||
else:
|
||||
try:
|
||||
self._instructions.change_config(data)
|
||||
except Exception as e:
|
||||
except:
|
||||
self.save_error_dialog.open()
|
||||
return
|
||||
self.save_success_dialog.open()
|
||||
self.ids.status.text = "Saved!"
|
||||
Clock.schedule_once(self.reset_update, 5)
|
||||
|
||||
def reset_update(self, dt):
|
||||
def reset_update(self, _):
|
||||
self.ids.status.text = ""
|
||||
|
||||
def validate_float(self, instance):
|
||||
|
||||
Reference in New Issue
Block a user