From 92fcc4a6e7ba24d25630030caaea237e61891b59 Mon Sep 17 00:00:00 2001 From: Janis Hutz Date: Wed, 5 Mar 2025 14:07:58 +0100 Subject: [PATCH] App launching, some porting work complete --- .../BiogasControllerAppLogo.png | Bin 0 -> 36750 bytes biogascontrollerapp/biogascontrollerapp.py | 52 +++++++++ biogascontrollerapp/config.ini | 19 ++++ biogascontrollerapp/gui/PopupManager.py | 3 + biogascontrollerapp/gui/credits.kv | 0 biogascontrollerapp/gui/credits/credits.kv | 27 +++++ biogascontrollerapp/gui/credits/credits.py | 8 ++ biogascontrollerapp/gui/home.kv | 0 biogascontrollerapp/gui/home/home.kv | 46 ++++++++ biogascontrollerapp/gui/home/home.py | 17 +++ biogascontrollerapp/gui/popups.kv | 0 biogascontrollerapp/gui/popups/popups.kv | 105 ++++++++++++++++++ biogascontrollerapp/gui/popups/popups.py | 16 +++ .../gui/{ => program}/program.kv | 0 biogascontrollerapp/gui/program/program.py | 16 +++ biogascontrollerapp/gui/settings.kv | 0 biogascontrollerapp/gui/settings/settings.kv | 37 ++++++ biogascontrollerapp/gui/settings/settings.py | 10 ++ biogascontrollerapp/lib/com.py | 38 +++++-- biogascontrollerapp/lib/instructions.py | 51 ++++++++- 20 files changed, 428 insertions(+), 17 deletions(-) create mode 100644 biogascontrollerapp/BiogasControllerAppLogo.png create mode 100644 biogascontrollerapp/config.ini create mode 100644 biogascontrollerapp/gui/PopupManager.py delete mode 100644 biogascontrollerapp/gui/credits.kv create mode 100644 biogascontrollerapp/gui/credits/credits.kv create mode 100644 biogascontrollerapp/gui/credits/credits.py delete mode 100644 biogascontrollerapp/gui/home.kv create mode 100644 biogascontrollerapp/gui/home/home.kv create mode 100644 biogascontrollerapp/gui/home/home.py delete mode 100644 biogascontrollerapp/gui/popups.kv create mode 100644 biogascontrollerapp/gui/popups/popups.kv create mode 100644 biogascontrollerapp/gui/popups/popups.py rename biogascontrollerapp/gui/{ => program}/program.kv (100%) create mode 100644 biogascontrollerapp/gui/program/program.py delete mode 100644 biogascontrollerapp/gui/settings.kv create mode 100644 biogascontrollerapp/gui/settings/settings.kv create mode 100644 biogascontrollerapp/gui/settings/settings.py diff --git a/biogascontrollerapp/BiogasControllerAppLogo.png b/biogascontrollerapp/BiogasControllerAppLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..2bd6e939c33637bbea4af96808833d8e93af07a3 GIT binary patch literal 36750 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 DR*=M! literal 0 HcmV?d00001 diff --git a/biogascontrollerapp/biogascontrollerapp.py b/biogascontrollerapp/biogascontrollerapp.py index e69de29..eec58f6 100644 --- a/biogascontrollerapp/biogascontrollerapp.py +++ b/biogascontrollerapp/biogascontrollerapp.py @@ -0,0 +1,52 @@ +import os +import configparser +from typing import override + +config = configparser.ConfigParser() +config.read('./config.ini') + +# Load config and disable kivy log if necessary +if config['Dev Settings']['verbose'] == "True": + pass +else: + os.environ["KIVY_NO_CONSOLELOG"] = "1" + + +# Load kivy modules +from kivy.core.window import Window, Config +from kivy.uix.screenmanager import ScreenManager +from kivy.app import App + +# Load other libraries +import threading + +# Store the current app version +app_version = f"{config['Info']['version']}{config['Info']['subVersion']}" + +#---------# +# Screens # +#---------# + +from gui.home.home import HomeScreen +from gui.credits.credits import CreditsScreen +from gui.settings.settings import SettingsScreen + +#----------------# +# Screen Manager # +#----------------# +class BiogasControllerApp(App): + def __init__(self, **kwargs): + super().__init__(**kwargs) + self.screen_manager = ScreenManager() + + @override + def build(self): + self.icon = './BiogasControllerAppLogo.png' + self.title = 'BiogasControllerApp-' + app_version + self.screen_manager.add_widget(HomeScreen(name='home')) + self.screen_manager.add_widget(CreditsScreen(name='credits')) + self.screen_manager.add_widget(SettingsScreen(name='settings')) + return self.screen_manager + +if __name__ == "__main__": + BiogasControllerApp().run() diff --git a/biogascontrollerapp/config.ini b/biogascontrollerapp/config.ini new file mode 100644 index 0000000..467137c --- /dev/null +++ b/biogascontrollerapp/config.ini @@ -0,0 +1,19 @@ +[Port Settings] +specificport = None + +[UI Config] +sizeh = 600 +sizew = 800 + +[Dev Settings] +verbose = True +log_level = DEBUG +disableconnectioncheck = False + +[License] +show = 1 + +[Info] +version = V2.3.0 +subversion = + diff --git a/biogascontrollerapp/gui/PopupManager.py b/biogascontrollerapp/gui/PopupManager.py new file mode 100644 index 0000000..adc546c --- /dev/null +++ b/biogascontrollerapp/gui/PopupManager.py @@ -0,0 +1,3 @@ +from gui.popups import * + + diff --git a/biogascontrollerapp/gui/credits.kv b/biogascontrollerapp/gui/credits.kv deleted file mode 100644 index e69de29..0000000 diff --git a/biogascontrollerapp/gui/credits/credits.kv b/biogascontrollerapp/gui/credits/credits.kv new file mode 100644 index 0000000..5f879ad --- /dev/null +++ b/biogascontrollerapp/gui/credits/credits.kv @@ -0,0 +1,27 @@ +: + name: "credits" + canvas.before: + Color: + rgba: (50,50,50,0.2) + Rectangle: + size: self.size + pos: self.pos + FloatLayout: + Button: + text: "back" + size_hint: 0.4, 0.2 + pos_hint: {"x":0.3, "y":0.1} + on_release: + app.root.current = "settings" + root.manager.transition.direction = "right" + GridLayout: + cols:1 + pos_hint:{"x":0.05, "y":0.35} + size_hint: 0.9, 0.5 + Label: + text: "This is a rework of the BiogasControllerApp V1, that was originally programmed by S. Reichmuth." + Label: + text: "Written by: Janis Hutz\nDesigned by: Janis Hutz\nDesign language: Kivy" + Label: + text: "This software is free Software licensed under the GPL V3 (GNU General Public License) and as such comes with absolutely no warranty. In return, you can use, modify, distribute or use any of the code of this software in your own project, if you reuse the same license. For more infos, you can find a copy of this license in the project folder." + text_size: self.width, None diff --git a/biogascontrollerapp/gui/credits/credits.py b/biogascontrollerapp/gui/credits/credits.py new file mode 100644 index 0000000..4906c62 --- /dev/null +++ b/biogascontrollerapp/gui/credits/credits.py @@ -0,0 +1,8 @@ +from kivy.uix.screenmanager import Screen +from kivy.lang import Builder + + +class CreditsScreen(Screen): + pass + +Builder.load_file('./gui/credits/credits.kv') diff --git a/biogascontrollerapp/gui/home.kv b/biogascontrollerapp/gui/home.kv deleted file mode 100644 index e69de29..0000000 diff --git a/biogascontrollerapp/gui/home/home.kv b/biogascontrollerapp/gui/home/home.kv new file mode 100644 index 0000000..40a78cb --- /dev/null +++ b/biogascontrollerapp/gui/home/home.kv @@ -0,0 +1,46 @@ +: + name: "home" + canvas.before: + Color: + rgba: (50,50,50,0.2) + Rectangle: + size: self.size + pos: self.pos + GridLayout: + cols:1 + Label: + text: "BiogasanlageControllerApp" + font_size: 50 + color: (0, 113, 0, 1) + bold:True + italic:True + FloatLayout: + GridLayout: + cols: 2 + size_hint: 0.8, 0.8 + pos_hint: {"x": 0.1, "y": 0.1} + Button: + text: "Start" + background_color: (255, 0, 0, 0.6) + font_size: 30 + on_release: + root.start() + Button: + text: "Quit" + background_color: (255, 0, 0, 0.6) + font_size: 30 + on_release: + root.quit() + Label: + text: "App version" + id: app_version + font_size: 13 + pos_hint: {"y": -0.45, "x":0.05} + Button: + text: "Settings" + font_size: 13 + size_hint: 0.07, 0.06 + pos_hint: {"x":0.01, "y":0.01} + background_color: (50, 0, 0, 0.2) + on_release: + root.to_settings() diff --git a/biogascontrollerapp/gui/home/home.py b/biogascontrollerapp/gui/home/home.py new file mode 100644 index 0000000..4273484 --- /dev/null +++ b/biogascontrollerapp/gui/home/home.py @@ -0,0 +1,17 @@ +from kivy.uix.screenmanager import Screen +from kivy.lang import Builder + + +class HomeScreen(Screen): + def start(self): + pass + + def quit(self): + pass + + def to_settings(self): + self.manager.current = 'settings' + self.manager.transition.direction = 'down' + + +Builder.load_file('./gui/home/home.kv') diff --git a/biogascontrollerapp/gui/popups.kv b/biogascontrollerapp/gui/popups.kv deleted file mode 100644 index e69de29..0000000 diff --git a/biogascontrollerapp/gui/popups/popups.kv b/biogascontrollerapp/gui/popups/popups.kv new file mode 100644 index 0000000..6c6f922 --- /dev/null +++ b/biogascontrollerapp/gui/popups/popups.kv @@ -0,0 +1,105 @@ +: + title: "INFORMATION" + size_hint: 0.7, 0.5 + auto_dismiss: True + GridLayout: + cols: 1 + Label: + id: msg + text_size: self.width, None + GridLayout: + cols: 1 + Button: + text: "Ok" + on_release: + root.dismiss() + +: + title: "BiogasControllerApp" + font_size: 50 + size_hint: 0.5, 0.4 + auto_dismiss: False + GridLayout: + cols:1 + Label: + text: "Are you sure you want to leave?" + font_size: 20 + GridLayout: + cols:2 + Button: + text: "Yes" + font_size: 15 + on_release: + root.quit() + app.stop() + Button: + text: "No" + font_size: 15 + on_press: + root.dismiss() + +: + title: "WARNING!" + font_size: 50 + size_hint: 0.5, 0.4 + auto_dismiss: False + GridLayout: + cols:1 + Label: + id: msg + text: "Message" + font_size: 20 + GridLayout: + cols:2 + Button: + id: btn1 + text: "Details" + on_release: + root.action() + Button: + text:"Ok" + on_release: + root.dismiss() + +: + title: "Details" + font_size: 50 + size_hint: 0.7, 0.6 + auto_dismiss: False + GridLayout: + cols:1 + Label: + id: msg_title + text: "Message title" + font_size: 20 + Label: + id: msg_body + text: "Message body" + font_size: 14 + Button: + text:"Ok" + on_release: + root.dismiss() + +: + title: "DETAILS" + font_size: 50 + size_hint: 1, 0.7 + auto_dismiss: False + GridLayout: + Label: + cols:1 + id: msg_title + text: "title" + font_size: 20 + Label: + id: msg_body + text: "Message" + font_size: 13 + Label: + text: msg_extra + font_size: 13 + Button: + text:"Ok" + on_release: + root.dismiss() diff --git a/biogascontrollerapp/gui/popups/popups.py b/biogascontrollerapp/gui/popups/popups.py new file mode 100644 index 0000000..5971a70 --- /dev/null +++ b/biogascontrollerapp/gui/popups/popups.py @@ -0,0 +1,16 @@ +from kivy.uix.screenmanager import Screen +from kivy.lang import Builder + + +class HomeScreen(Screen): + def start(self): + pass + + def quit(self): + pass + + def to_settings(self): + pass + + +Builder.load_file('./gui/home/home.kv') diff --git a/biogascontrollerapp/gui/program.kv b/biogascontrollerapp/gui/program/program.kv similarity index 100% rename from biogascontrollerapp/gui/program.kv rename to biogascontrollerapp/gui/program/program.kv diff --git a/biogascontrollerapp/gui/program/program.py b/biogascontrollerapp/gui/program/program.py new file mode 100644 index 0000000..5971a70 --- /dev/null +++ b/biogascontrollerapp/gui/program/program.py @@ -0,0 +1,16 @@ +from kivy.uix.screenmanager import Screen +from kivy.lang import Builder + + +class HomeScreen(Screen): + def start(self): + pass + + def quit(self): + pass + + def to_settings(self): + pass + + +Builder.load_file('./gui/home/home.kv') diff --git a/biogascontrollerapp/gui/settings.kv b/biogascontrollerapp/gui/settings.kv deleted file mode 100644 index e69de29..0000000 diff --git a/biogascontrollerapp/gui/settings/settings.kv b/biogascontrollerapp/gui/settings/settings.kv new file mode 100644 index 0000000..b1354a7 --- /dev/null +++ b/biogascontrollerapp/gui/settings/settings.kv @@ -0,0 +1,37 @@ +: + name: "settings" + canvas.before: + Color: + rgba: (50,50,50,0.2) + Rectangle: + size: self.size + pos: self.pos + GridLayout: + cols: 1 + Label: + text: "Settings" + font_size: 40 + color: (0, 113, 0, 1) + bold: True + FloatLayout: + GridLayout: + pos_hint: {"x":0.05, "y":0.05} + size_hint: 0.9, 0.9 + cols: 3 + Button: + text: "Back" + background_color: (255,0,0,0.6) + on_release: + app.root.current = "home" + root.manager.transition.direction = "up" + Button: + text: "Report a\nBug" + background_color: (255,0,0,0.6) + on_release: + root.report_issue() + Button: + text: "Credits" + background_color: (255,0,0,0.6) + on_release: + app.root.current = "credits" + root.manager.transition.direction = "left" diff --git a/biogascontrollerapp/gui/settings/settings.py b/biogascontrollerapp/gui/settings/settings.py new file mode 100644 index 0000000..0251b1c --- /dev/null +++ b/biogascontrollerapp/gui/settings/settings.py @@ -0,0 +1,10 @@ +from kivy.uix.screenmanager import Screen +from kivy.lang import Builder +import webbrowser + + +class SettingsScreen(Screen): + def report_issue(self): + webbrowser.open('https://github.com/janishutz/BiogasControllerApp/issues', new=2) + +Builder.load_file('./gui/settings/settings.kv') diff --git a/biogascontrollerapp/lib/com.py b/biogascontrollerapp/lib/com.py index f884688..279e80d 100644 --- a/biogascontrollerapp/lib/com.py +++ b/biogascontrollerapp/lib/com.py @@ -9,11 +9,22 @@ class Com: self._serial: Optional[serial.Serial] = None self._filters = filters if filters != None else [ 'USB-Serial Controller', 'Prolific USB-Serial Controller' ] self._port_override = '' + self._baudrate = 19200 def set_port_override(self, override: str) -> None: """Set the port override, to disable port search""" self._port_override = override + def _connection_check(self) -> bool: + if self._serial == None: + return self._open() + if self._serial != None: + if not self._serial.is_open: + self._serial.open() + return True + else: + return False + def get_comport(self) -> str: """Find the comport the microcontroller has attached to""" if self._port_override != '': @@ -34,20 +45,24 @@ class Com: return '' - def connect(self, baud_rate: int, port_override: Optional[str] = None) -> bool: - """Try to find a comport and connect to the microcontroller. Returns the success as a boolean""" + def _open(self) -> bool: comport = self.get_comport() # Comport search returns empty string if search unsuccessful if comport == '': try: - self._serial = serial.Serial(comport, baud_rate, timeout=5) + self._serial = serial.Serial(comport, self._baudrate, timeout=5) except: return False return True else: return False + def connect(self, baud_rate: int) -> bool: + """Try to find a comport and connect to the microcontroller. Returns the success as a boolean""" + self._baudrate = baud_rate + return self._connection_check() + def close(self) -> None: """Close the serial connection, if possible""" if self._serial != None: @@ -58,23 +73,24 @@ class Com: def receive(self, byte_count: int) -> bytes: """Recieve bytes from microcontroller over serial. Returns bytes. Might want to decode using functions from lib.tools""" - if self._serial == None: - self.connect(19200) + self._connection_check() if self._serial != None: return self._serial.read(byte_count) else: - raise Exception('ERR_CONNECTION') + raise Exception('ERR_CONNECTING') def send(self, msg: str) -> None: - """Send a string over serial connection.""" - if self._serial == None: - self.connect(19200) + """Send a string over serial connection. Will open a connection if none is available""" + self._connection_check() if self._serial != None: self._serial.write(msg.encode()) + else: + raise Exception('ERR_CONNECTING') def send_float(self, msg: float) -> None: """Send a float number over serial connection""" - if self._serial == None: - self.connect(19200) + self._connection_check() if self._serial != None: self._serial.write(bytearray(struct.pack('>f', msg))[0:3]) + else: + raise Exception('ERR_CONNECTING') diff --git a/biogascontrollerapp/lib/instructions.py b/biogascontrollerapp/lib/instructions.py index 182bde2..0db6b8a 100644 --- a/biogascontrollerapp/lib/instructions.py +++ b/biogascontrollerapp/lib/instructions.py @@ -1,22 +1,61 @@ -from typing import Optional import lib.com import lib.decoder +import time # TODO: Load filters (for comport search) com = lib.com.Com() decoder = lib.decoder.Decoder() class Instructions: - def __init__(self) -> None: - pass + def set_port_override(self, override: str) -> None: + com.set_port_override(override) def _hook(self, instruction: str, sequence: list[str]) -> bool: + # Send instruction to microcontroller to start hooking process + com.send(instruction) + + # Record start time to respond to timeout + start = time.time() + + # Check for timeout + pointer = 0 + sequence_max = len(sequence) - 1 + while time.time() - start < 5: + if ( decoder.decode_ascii( com.receive(1) ) ) == sequence[pointer]: + pointer += 1 + else: + pointer = 0 + + if pointer == sequence_max: + return True + return False - def change_temperature(self, new_temps: list[float]) -> None: - pass + def _change_data(self, instruction: str, readback: list[str], data: list[float], readback_length: int) -> None: + # Hook to stream + if self._hook(instruction, readback): + while len(data) > 0: + if com.receive(readback_length) != '': + com.send_float(data.pop(0)) + else: + com.close() + raise Exception('Failed to transmit data. No response from controller') + com.close() + else: + com.close() + raise ConnectionError('Failed to hook to controller data stream. No fitting response received') def change_config(self, new_config: list[float]) -> None: - pass + self._change_data('PR', ['\n', 'P', 'R', '\n'], new_config, 3) + def change_temperature(self, temperatures: list[float]) -> None: + self._change_data('PT', ['\n', 'P', 'T', '\n'], temperatures, 3) + + def enable_fastmode(self) -> None: + com.send('FM') + com.close() + + def disable_fastmode(self) -> None: + com.send('NM') + com.close()