File size: 12,263 Bytes
a04cd9f c417206 a04cd9f c417206 a04cd9f c417206 a04cd9f |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 |
import gradio as gr
import time
import threading
# Morse code dictionary
MORSE_CODE_DICT = {
'A': '.-', 'B': '-...', 'C': '-.-.', 'D': '-..', 'E': '.', 'F': '..-.',
'G': '--.', 'H': '....', 'I': '..', 'J': '.---', 'K': '-.-', 'L': '.-..',
'M': '--', 'N': '-.', 'O': '---', 'P': '.--.', 'Q': '--.-', 'R': '.-.',
'S': '...', 'T': '-', 'U': '..-', 'V': '...-', 'W': '.--', 'X': '-..-',
'Y': '-.--', 'Z': '--..', '1': '.----', '2': '..---', '3': '...--',
'4': '....-', '5': '.....', '6': '-....', '7': '--...', '8': '---..',
'9': '----.', '0': '-----', ', ': '--..--', '.': '.-.-.-', '?': '..--..',
'/': '-..-.', '-': '-....-', '(': '-.--.', ')': '-.--.-'
}
dot_duration = 0.2 # seconds
dash_duration = dot_duration * 3
space_duration = dot_duration * 7
letter_space_duration = dot_duration * 3
led_html = """
<div style="width: 50px; height: 50px; border-radius: 50%; background-color: {color};"></div>
"""
def morse_to_text(morse_code):
morse_code = morse_code.replace("/", " / ") # Add space for word separator
words = morse_code.split(" / ")
text = ""
for word in words:
letters = word.split() #Splits into individual Morse codes
for letter in letters:
try:
found = False
for key, value in MORSE_CODE_DICT.items():
if value == letter:
text += key
found = True
break
if not found:
raise ValueError(f"Invalid Morse code: {letter}")
except ValueError as e:
raise e
text += " "
return text.strip()
def display_led(morse_code, callback):
"""Simulates the LED display and updates the Gradio LED component."""
try:
for symbol in morse_code:
if symbol == '.':
callback(led_html.format(color="yellow"))
time.sleep(dot_duration)
callback(led_html.format(color="gray"))
time.sleep(dot_duration)
elif symbol == '-':
callback(led_html.format(color="yellow"))
time.sleep(dash_duration)
callback(led_html.format(color="gray"))
time.sleep(dot_duration)
elif symbol == ' ':
time.sleep(letter_space_duration)
elif symbol == '/':
time.sleep(space_duration)
except Exception as e:
return f"Error during LED display: {e}" # Return error message
return led_html.format(color="gray") # Ensure led is turned off after the process
def decode_morse(morse_code):
try:
decoded_text = morse_to_text(morse_code.upper())
except ValueError as e:
return str(e), led_html.format(color="gray") # Return error message
# Use a GradioState to keep track of the LED display
def update_led(led_status):
return led_status
# Call the display_led function in a separate thread to keep the UI responsive
threading.Thread(target=display_led, args=(morse_code, update_led)).start()
return decoded_text, led_html.format(color="gray")
# Gradio Interface
with gr.Blocks() as iface:
morse_input = gr.Textbox(label="Morse Code Input", placeholder="Enter Morse Code Here")
decoded_output = gr.Textbox(label="Decoded Text")
led_display = gr.HTML(led_html.format(color="gray"), label="LED Output") # Initialize with gray
morse_input.change(fn=decode_morse,
inputs=morse_input,
outputs=[decoded_output, led_display])
# To run it locally
iface.launch()
# To run it on Hugging Face Spaces
"""
import tkinter as tk
from tkinter import ttk
import time
import threading
# Morse code dictionary
MORSE_CODE_DICT = {
'A': '.-', 'B': '-...', 'C': '-.-.', 'D': '-..', 'E': '.', 'F': '..-.',
'G': '--.', 'H': '....', 'I': '..', 'J': '.---', 'K': '-.-', 'L': '.-..',
'M': '--', 'N': '-.', 'O': '---', 'P': '.--.', 'Q': '--.-', 'R': '.-.',
'S': '...', 'T': '-', 'U': '..-', 'V': '...-', 'W': '.--', 'X': '-..-',
'Y': '-.--', 'Z': '--..', '1': '.----', '2': '..---', '3': '...--',
'4': '....-', '5': '.....', '6': '-....', '7': '--...', '8': '---..',
'9': '----.', '0': '-----', ', ': '--..--', '.': '.-.-.-', '?': '..--..',
'/': '-..-.', '-': '-....-', '(': '-.--.', ')': '-.--.-'
}
class MorseDecoderApp:
def __init__(self, root):
self.root = root
self.root.title("Morse Code Decoder")
self.root.geometry("600x400") # Set initial window size
self.dot_duration = 200 # milliseconds
self.dash_duration = self.dot_duration * 3
self.space_duration = self.dot_duration * 7 # Between words
self.letter_space_duration = self.dot_duration * 3 # Between letters
# Input Frame
self.input_frame = ttk.Frame(root, padding=(10, 10, 10, 10))
self.input_frame.pack(fill=tk.BOTH, expand=True)
self.input_label = ttk.Label(self.input_frame, text="Morse Code Input:")
self.input_label.grid(row=0, column=0, sticky=tk.W)
self.morse_input = tk.Text(self.input_frame, height=5, width=50)
self.morse_input.grid(row=1, column=0, columnspan=2, sticky=tk.EW)
self.decode_button = ttk.Button(self.input_frame, text="Decode", command=self.decode_morse)
self.decode_button.grid(row=2, column=0, columnspan=2, pady=5)
# Output Frame
self.output_frame = ttk.Frame(root, padding=(10, 0, 10, 10)) # Less top padding
self.output_frame.pack(fill=tk.BOTH, expand=True)
self.output_label = ttk.Label(self.output_frame, text="Decoded Text:")
self.output_label.grid(row=0, column=0, sticky=tk.W)
self.decoded_text = tk.Text(self.output_frame, height=5, width=50, state=tk.DISABLED) # Start disabled
self.decoded_text.grid(row=1, column=0, columnspan=2, sticky=tk.EW)
# LED Light Simulation (Basic)
self.led_frame = ttk.Frame(root, padding=(10, 0, 10, 10)) # Less top padding
self.led_frame.pack(fill=tk.BOTH, expand=True)
self.led_label = ttk.Label(self.led_frame, text="LED Output:")
self.led_label.grid(row=0, column=0, sticky=tk.W)
self.led = tk.Canvas(self.led_frame, width=50, height=50, bg="white", highlightthickness=0) # highlightthickness=0 removes border
self.led.grid(row=1, column=0, columnspan=2, pady=5) # pady for spacing
self.led_circle = self.led.create_oval(10, 10, 40, 40, fill="gray", outline="") # outline="" removes the default black outline
#Status bar at the bottom
self.status_bar = ttk.Label(root, text="Ready", relief=tk.SUNKEN, anchor=tk.W)
self.status_bar.pack(side=tk.BOTTOM, fill=tk.X)
# Configure grid weights for resizing
self.input_frame.columnconfigure(0, weight=1)
self.input_frame.columnconfigure(1, weight=1)
self.input_frame.rowconfigure(1, weight=1) # Morse Text area expands vertically
self.output_frame.columnconfigure(0, weight=1)
self.output_frame.columnconfigure(1, weight=1)
self.output_frame.rowconfigure(1, weight=1) # Decoded text area expands vertically
self.led_frame.columnconfigure(0, weight=1)
self.led_frame.columnconfigure(1, weight=1)
def decode_morse(self):
morse_code = self.morse_input.get("1.0", tk.END).strip().upper() # Get text, remove whitespace, and convert to uppercase
if not morse_code:
self.status_bar.config(text="Error: Please enter Morse code.")
return
try:
decoded_text = self.morse_to_text(morse_code)
self.status_bar.config(text="Decoding...") #Update Status bar
self.display_led(morse_code)
except ValueError as e:
self.decoded_text.config(state=tk.NORMAL)
self.decoded_text.delete("1.0", tk.END)
self.decoded_text.insert("1.0", str(e)) #Display error in output text area
self.decoded_text.config(state=tk.DISABLED)
self.status_bar.config(text=f"Error: {str(e)}") # Show error in status bar
except Exception as e: # Catch any other unexpected errors
self.decoded_text.config(state=tk.NORMAL)
self.decoded_text.delete("1.0", tk.END)
self.decoded_text.insert("1.0", "An unexpected error occurred.")
self.decoded_text.config(state=tk.DISABLED)
self.status_bar.config(text="An unexpected error occurred.")
def morse_to_text(self, morse_code):
# Basic morse to text conversion (doesn't handle invalid codes well)
morse_code = morse_code.replace("/", " / ") # Add space for word separator
words = morse_code.split(" / ")
text = ""
for word in words:
letters = word.split() #Splits into individual Morse codes
for letter in letters:
try:
# Reverse lookup from the dictionary (inefficient for large dictionaries, but simple)
found = False
for key, value in MORSE_CODE_DICT.items():
if value == letter:
text += key
found = True
break # Stop search once a match is found
if not found:
raise ValueError(f"Invalid Morse code: {letter}") # Custom Error
except ValueError as e:
raise e # Re-raise the exception to be caught outside
text += " "
return text.strip() # Remove trailing space
def display_led(self, morse_code):
#Displays the Morse code using the LED simulation. Runs in a separate thread to avoid freezing the GUI.
self.decode_button.config(state=tk.DISABLED) # Disable button during processing
self.morse_input.config(state=tk.DISABLED) # Disable input field during processing
def led_thread():
try:
for symbol in morse_code:
if symbol == '.':
self.turn_on_led()
time.sleep(self.dot_duration / 1000)
self.turn_off_led()
time.sleep(self.dot_duration / 1000) # Intra-character space
elif symbol == '-':
self.turn_on_led()
time.sleep(self.dash_duration / 1000)
self.turn_off_led()
time.sleep(self.dot_duration / 1000) # Intra-character space
elif symbol == ' ': # Space between letters
time.sleep(self.letter_space_duration / 1000) # Longer pause between letters
elif symbol == '/':
time.sleep(self.space_duration/1000)
self.root.update() # Update the GUI
decoded_text = self.morse_to_text(morse_code) #Decode here, after animation is complete
self.decoded_text.config(state=tk.NORMAL)
self.decoded_text.delete("1.0", tk.END)
self.decoded_text.insert("1.0", decoded_text)
self.decoded_text.config(state=tk.DISABLED)
self.status_bar.config(text="Decoding complete.") #Update Status bar
except Exception as e:
self.status_bar.config(text=f"Error during LED display: {e}") #Status bar
print(f"Error during LED display: {e}")
finally: # Make sure to re-enable button/text, even if there's an error
self.decode_button.config(state=tk.NORMAL)
self.morse_input.config(state=tk.NORMAL)
thread = threading.Thread(target=led_thread)
thread.start()
def turn_on_led(self):
self.led.itemconfig(self.led_circle, fill="yellow") # Simulate LED turning on
self.root.update()
def turn_off_led(self):
self.led.itemconfig(self.led_circle, fill="gray") # Simulate LED turning off
self.root.update()
if __name__ == "__main__":
root = tk.Tk()
app = MorseDecoderApp(root)
root.mainloop()
""" |