Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions src/devices/led_mock.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
"""
Mock LED device for the Tank Controller.
"""


class LED:
"""Mock LED that tracks an ON/OFF state."""

def __init__(self):
"""Initialize the LED as off."""
self.is_on = False

def on(self):
"""Turn the LED on."""
self.is_on = True

def off(self):
"""Turn the LED off."""
self.is_on = False

def toggle(self):
"""Toggle the LED between on and off."""
self.is_on = not self.is_on
1 change: 1 addition & 0 deletions src/devices/library.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
from src.devices.digital_mock import DigitalInOut
from src.devices.heater_mock import Heater
from src.devices.keypad_mock import Keypad
from src.devices.led_mock import LED
from src.devices.liquid_crystal_mock import LiquidCrystal
from src.devices.max31865_mock import MAX31865
from src.devices.serial_mock import Serial
Expand Down
83 changes: 77 additions & 6 deletions src/gui.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,31 @@ def __init__(self, titrator):

# Initialize the GUI Frame
self.root = tk.Tk()
self.root.geometry("280x200")
self.root.geometry("560x200")
self.root.title("Tank Controller")
self.root.configure(background="black")

# Split window into left and right sections
self.root.columnconfigure(0, weight=1)
self.root.columnconfigure(1, weight=1)
self.root.rowconfigure(0, weight=1)

# ---------------------------------------------------------
# LEFT SIDE - LCD AND KEYPAD
# ---------------------------------------------------------

left_frame = tk.Frame(self.root, bg="lightgray")
left_frame.grid(row=0, column=0, sticky=STICKY)

left_frame.columnconfigure(0, weight=1)
left_frame.rowconfigure(0, weight=1)
left_frame.rowconfigure(1, weight=1)

# Initialize the Labels
label_frame = tk.Frame(self.root)
label_frame = tk.Frame(left_frame)
label_frame.config(bg=BG)

label_frame.columnconfigure(0, weight=1)
label_frame.rowconfigure(0, weight=1)
label_frame.rowconfigure(1, weight=1)
label_frame.rowconfigure(2, weight=1)
Expand Down Expand Up @@ -95,7 +111,7 @@ def __init__(self, titrator):
label_frame.grid(row=0, column=0, sticky=STICKY)

# Initialize the Buttons
buttonframe = tk.Frame(self.root)
buttonframe = tk.Frame(left_frame)
buttonframe.columnconfigure(0, weight=1)
buttonframe.columnconfigure(1, weight=1)
buttonframe.columnconfigure(2, weight=1)
Expand Down Expand Up @@ -215,7 +231,50 @@ def __init__(self, titrator):

buttonframe.grid(row=1, column=0, sticky=STICKY)

self.thread = threading.Thread(target=self.update_lcd, daemon=True)
# ---------------------------------------------------------
# RIGHT SIDE - BOARD LED
# ---------------------------------------------------------

right_frame = tk.Frame(self.root, bg="darkgray")
right_frame.grid(row=0, column=1, sticky=STICKY)

right_frame.columnconfigure(0, weight=1)
right_frame.columnconfigure(1, weight=1)
right_frame.rowconfigure(0, weight=1)

self.led_canvas = tk.Canvas(
right_frame,
width=80,
height=80,
bg="darkgray",
highlightthickness=0,
)
self.led_canvas.grid(row=0, column=0, padx=5, pady=10, sticky=tk.NE)

self.led_circle = self.led_canvas.create_oval(
4,
4,
30,
30,
fill="red",
outline="black",
width=3,
)

self.led_label = tk.Label(
right_frame,
text="Board LED",
font=("Arial", 12),
bg="darkgray",
fg="black",
)
self.led_label.grid(row=0, column=1, padx=2, pady=10, sticky=tk.NW)

# Start GUI update thread
self.thread = threading.Thread(
target=self.update_gui,
daemon=True,
)
self.thread.start()

self.root.mainloop()
Expand All @@ -226,12 +285,13 @@ def button_press(self, key):
"""
self.titrator.keypad.set_key(key)

def update_lcd(self):
def update_gui(self):
"""
The function to update the GUI LCD
The function to update the GUI LCD and LED
"""
while True:
time.sleep(0.001)

self.line_1.config(
text=self.titrator.lcd.get_line(1),
anchor=self.titrator.lcd.get_style(1),
Expand All @@ -248,3 +308,14 @@ def update_lcd(self):
text=self.titrator.lcd.get_line(4),
anchor=self.titrator.lcd.get_style(4),
)

if self.titrator.led.is_on:
self.led_canvas.itemconfig(
self.led_circle,
fill="yellow",
)
else:
self.led_canvas.itemconfig(
self.led_circle,
fill="black",
)
4 changes: 4 additions & 0 deletions src/titrator.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from src.devices.date_time import DateTime
from src.devices.eeprom import EEPROM
from src.devices.library import (
LED,
Heater,
Keypad,
LiquidCrystal,
Expand Down Expand Up @@ -64,6 +65,9 @@ def __init__(self):
# Initialize LCD
self.lcd = LiquidCrystal()

# Initialize LED
self.led = LED()

# Initialize Keypad
self.keypad = Keypad()

Expand Down
3 changes: 3 additions & 0 deletions src/ui_state/main_menu.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from src.ui_state.set_menu.set_kd import SetKD
from src.ui_state.set_menu.set_ki import SetKI
from src.ui_state.set_menu.set_kp import SetKP
from src.ui_state.set_menu.set_led import SetLED
from src.ui_state.set_menu.set_ph_calibration import PHCalibration
from src.ui_state.set_menu.set_ph_calibration_clear import ResetPHCalibration
from src.ui_state.set_menu.set_ph_sine_wave import SetPHSineWave
Expand Down Expand Up @@ -77,6 +78,7 @@ def __init__(self, titrator):
"Set chill/heat",
"Set Google mins",
"Set KD",
"Set LED",
"Set KI",
"Set KP",
"Set pH target",
Expand Down Expand Up @@ -114,6 +116,7 @@ def __init__(self, titrator):
SetChillOrHeat, # Set chill/heat
SetGoogleSheetInterval, # Set Google mins
SetKD, # Set KD
SetLED, # Set LED
SetKI, # Set KI
SetKP, # Set KP
SetPHTarget, # Set pH target
Expand Down
51 changes: 51 additions & 0 deletions src/ui_state/set_menu/set_led.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
"""
The file to hold the Set LED class
"""

from src.devices.library import Keypad
from src.ui_state.ui_state import UIState


class SetLED(UIState):
"""
This is a class for the SetLED state of the Tank Controller
"""

def __init__(self, titrator, previous_state=None):
super().__init__(titrator)
self.previous_state = previous_state

def loop(self):
"""
The main loop for the SetLED state
"""
self.titrator.lcd.print("LED 1:on; 9:off", line=1)

if self.titrator.led.is_on:
self.titrator.lcd.print("Currently on", line=2)
else:
self.titrator.lcd.print("Currently off", line=2)

def handle_key(self, key):
"""
Handle key presses to control the LED.
"""
if key == Keypad.KEY_1:
self.titrator.led.on()
self.titrator.lcd.print("LED on", line=2)
self.return_to_main_menu(ms_delay=3000)

if key == Keypad.KEY_9:
self.titrator.led.off()
self.titrator.lcd.print("LED off", line=2)
self.return_to_main_menu(ms_delay=3000)

if key == Keypad.KEY_A:
if self.titrator.led.is_on:
self.titrator.lcd.print("LED on", line=2)
else:
self.titrator.lcd.print("LED off", line=2)
self.return_to_main_menu(ms_delay=3000)

if key == Keypad.KEY_D:
self._set_next_state(self.previous_state, True)
50 changes: 50 additions & 0 deletions tests/devices/led_mock_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
"""
The file to test the Mock LED class.
"""

from src.devices.led_mock import LED


def test_led_starts_off():
"""
LED should be off when initialized.
"""
led = LED()

assert led.is_on is False


def test_led_turns_on():
"""
LED should turn on when on() is called.
"""
led = LED()

led.on()

assert led.is_on is True


def test_led_turns_off():
"""
LED should turn off when off() is called.
"""
led = LED()
led.on()

led.off()

assert led.is_on is False


def test_led_toggle():
"""
LED should switch between on and off when toggle() is called.
"""
led = LED()

led.toggle()
assert led.is_on is True

led.toggle()
assert led.is_on is False
28 changes: 28 additions & 0 deletions tests/ui_state/set_menu/set_led_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
"""
The file to test the SetLED class
"""

from src.devices.library import Keypad
from src.titrator import Titrator
from src.ui_state.set_menu.set_led import SetLED


def test_led_on():
"""Test turning the LED on."""
titrator = Titrator()
state = SetLED(titrator)

state.handle_key(Keypad.KEY_1)

assert titrator.led.is_on is True


def test_led_off():
"""Test turning the LED off."""
titrator = Titrator()
state = SetLED(titrator)

titrator.led.on()
state.handle_key(Keypad.KEY_9)

assert titrator.led.is_on is False