From 2b430351a33262a1551c187088fef3ded9c3f8a3 Mon Sep 17 00:00:00 2001 From: Rubal Singh Date: Thu, 11 Jan 2024 23:09:38 +0530 Subject: [PATCH 1/2] add SpeedTest --- scripts/speedtest/README.md | 24 +++++ scripts/speedtest/images/download_logo.png | Bin 0 -> 15197 bytes scripts/speedtest/images/ping_logo.png | Bin 0 -> 15079 bytes scripts/speedtest/images/upload_logo.png | Bin 0 -> 7031 bytes scripts/speedtest/main.py | 99 +++++++++++++++++++++ 5 files changed, 123 insertions(+) create mode 100644 scripts/speedtest/README.md create mode 100644 scripts/speedtest/images/download_logo.png create mode 100644 scripts/speedtest/images/ping_logo.png create mode 100644 scripts/speedtest/images/upload_logo.png create mode 100644 scripts/speedtest/main.py diff --git a/scripts/speedtest/README.md b/scripts/speedtest/README.md new file mode 100644 index 0000000..7cda65d --- /dev/null +++ b/scripts/speedtest/README.md @@ -0,0 +1,24 @@ +# SpeedTest 101 + +## Overview +SpeedTest101 is a simple Python application that uses the speedtest-cli library to measure internet speed. The graphical user interface (GUI) is built using the Tkinter library for a user-friendly experience. + +## Features +- Measure Download Speed in Mbps +- Measure Upload Speed in Mbps +- Measure Ping in milliseconds +- GUI with logos for visual representation + +## Usage +- Install dependency. + ``` bash + pip install speedtest-cli + +- Navigate to repo. + ``` bash + cd scripts/speedtest + +- Run the project. + ``` bash + python main.py + \ No newline at end of file diff --git a/scripts/speedtest/images/download_logo.png b/scripts/speedtest/images/download_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..d6637ff8b7cb3077af853966667137feab96c545 GIT binary patch literal 15197 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 B-%kJl literal 0 HcmV?d00001 diff --git a/scripts/speedtest/images/upload_logo.png b/scripts/speedtest/images/upload_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..98b5a13176b5a8d65f7f013a513defed8b777d6c GIT binary patch literal 7031 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 AwEzGB literal 0 HcmV?d00001 diff --git a/scripts/speedtest/main.py b/scripts/speedtest/main.py new file mode 100644 index 0000000..53509cd --- /dev/null +++ b/scripts/speedtest/main.py @@ -0,0 +1,99 @@ +''' +SpeedTest using speedtest-cli, used tkinter for GUI +''' +import tkinter as tk +from tkinter import Tk +from tkinter import ttk +import speedtest +from decimal import Decimal +from PIL import Image, ImageTk + +root = Tk() +root.title('SpeedTest 101') +root.geometry("300x500") +root.configure(bg="#9F9998") +root.resizable(False, False) + +''' +check_speed() function will get trigerred after clicking SpeedTest Button +1. intiliaze an object of speedtest.SpeedTest() +2. Calculate downlaoding speed in Mbps +3. Calculate upload speed in Mbps +4. Calculate ping in ms +5. return it to respected labels +''' + +def check_speed(): + + check_speed_button.config(state=tk.DISABLED) + quit_button.config(state=tk.DISABLED) + + st = speedtest.Speedtest() + + check_speed_button.config(state=tk.NORMAL) + quit_button.config(state=tk.NORMAL) + + check_speed_button.config(state=tk.NORMAL) + quit_button.config(state=tk.NORMAL) + + download_speed = Decimal(st.download()) / Decimal('1024') / Decimal('1024') + download_speed = download_speed.quantize(Decimal('0.00')) + + upload_speed = Decimal(st.upload()) / Decimal('1024') / Decimal('1024') + upload_speed = upload_speed.quantize(Decimal('0.00')) + + ping = st.results.ping + + download_label.config(text=f"Downoad Speed: {download_speed} Mbps") + upload_label.config(text=f"Upload Speed: {upload_speed} Mbps") + ping_label.config(text=f"Ping: {ping} ms") + + +''' +This function will resize the downlod logo, upload logo and ping logo to fit rows. +''' +def resize_image(image_path, width, height): + img = Image.open(image_path) + img = img.resize((width, height), Image.LANCZOS) + return ImageTk.PhotoImage(img) + + +download_logo = resize_image('images/download_logo.png', 50, 50) +upload_logo = resize_image('images/upload_logo.png', 50, 50) +ping_logo = resize_image('images/ping_logo.png', 50, 50) + + +download_logo_label = tk.Label(root, image=download_logo) +download_logo_label.grid(row=0, column=0, padx=10, pady=10) +download_label = tk.Label(root, text="Click SpeedTest....") +download_label.grid(row=0, column=1, padx=10, pady=10) + +tk.Label(root, text="", bg="#9F9998").grid(row=1) #add space of 1 row btw two sections + +upload_logo_label = tk.Label(root, image=upload_logo) +upload_logo_label.grid(row=2, column=0, padx=10, pady=10) +upload_label = tk.Label(root, text="Click SpeedTest....") +upload_label.grid(row=2, column=1, padx=10, pady=10) + +tk.Label(root, text="", bg="#9F9998").grid(row=3) #add space of 1 row btw two sections + +ping_logo_label = tk.Label(root, image=ping_logo) +ping_logo_label.grid(row=4, column=0, padx=10, pady=10) +ping_label = tk.Label(root, text="Click SpeedTest....") +ping_label.grid(row=4, column=1, padx=10, pady=10) + +#add space of 2 rows btw two sections +tk.Label(root, text="", bg="#9F9998").grid(row=5) +tk.Label(root, text="", bg="#9F9998").grid(row=6) + + +check_speed_button = ttk.Button(root, text='SpeedTest', command=check_speed) #this button will trigger check_speed() function initialzing speedTest +check_speed_button.grid(row=8, column=1, padx=7, pady=5, sticky='w') + +tk.Label(root, text="", bg="#9F9998").grid(row=9) #add space of 1 row btw two sections + +quit_button = ttk.Button(root, text="Quit", command=root.destroy) #quit button +quit_button.grid(row=10, column=1, padx=7, pady=5, sticky='w') + + +root.mainloop() From 5a2cf4391dc047e557eef121516c4c82eee4a7b3 Mon Sep 17 00:00:00 2001 From: Rubal Singh Date: Fri, 12 Jan 2024 00:59:32 +0530 Subject: [PATCH 2/2] update SpeedTest #51 --- scripts/speedtest/main.py | 124 +++++++++++++++++++++++++------------- 1 file changed, 82 insertions(+), 42 deletions(-) diff --git a/scripts/speedtest/main.py b/scripts/speedtest/main.py index 53509cd..85b28b4 100644 --- a/scripts/speedtest/main.py +++ b/scripts/speedtest/main.py @@ -22,40 +22,75 @@ 4. Calculate ping in ms 5. return it to respected labels ''' - def check_speed(): + try: - check_speed_button.config(state=tk.DISABLED) - quit_button.config(state=tk.DISABLED) + st = speedtest.Speedtest() - st = speedtest.Speedtest() + check_speed_button.config(state=tk.NORMAL) - check_speed_button.config(state=tk.NORMAL) - quit_button.config(state=tk.NORMAL) + download_speed = Decimal(st.download()) / Decimal('1024') / Decimal('1024') + download_speed = download_speed.quantize(Decimal('0.00')) - check_speed_button.config(state=tk.NORMAL) - quit_button.config(state=tk.NORMAL) + upload_speed = Decimal(st.upload()) / Decimal('1024') / Decimal('1024') + upload_speed = upload_speed.quantize(Decimal('0.00')) - download_speed = Decimal(st.download()) / Decimal('1024') / Decimal('1024') - download_speed = download_speed.quantize(Decimal('0.00')) + ping = st.results.ping - upload_speed = Decimal(st.upload()) / Decimal('1024') / Decimal('1024') - upload_speed = upload_speed.quantize(Decimal('0.00')) + download_label.config(text=f"Downoad Speed: {download_speed} Mbps") + upload_label.config(text=f"Upload Speed: {upload_speed} Mbps") + ping_label.config(text=f"Ping: {ping} ms") - ping = st.results.ping - download_label.config(text=f"Downoad Speed: {download_speed} Mbps") - upload_label.config(text=f"Upload Speed: {upload_speed} Mbps") - ping_label.config(text=f"Ping: {ping} ms") + except Exception as error_speedtest: + download_label.config(text=f"Downoad Speed: Failed") + upload_label.config(text=f"Upload Speed: Failed") + ping_label.config(text=f"Ping: Failed") + print(f"Error occured, {error_speedtest}") ''' -This function will resize the downlod logo, upload logo and ping logo to fit rows. +The function intiate_check_speed() +1. Disables the SpeedTest and Quit button. +2. Introduces a delay of 500 milliseconds, so we can actually see the status- + converging from 'Click SpeedTest....'-> 'In Progress...' -> 'Speed: x mbps' +3. Call check_speed function. +''' +def intiate_check_speed(): + try: + check_speed_button.config(state=tk.DISABLED) + + # Provide feedback to the user that the speed test is in progress + download_label.config(text="Downoad Speed: In Progress...") + upload_label.config(text="Upload Speed: In Progress...") + ping_label.config(text="Ping: In Progress...") + + # Delay before starting the speed test (e.g., 500 milliseconds) + root.after(500, check_speed) + + except Exception as error_speedtest: + download_label.config(text="Downoad Speed: Failed") + upload_label.config(text="Upload Speed: Failed") + ping_label.config(text="Ping: Failed") + + print(f"Error occurred, {error_speedtest}") + +''' +This function will resize the logos to given width and height. + +returns either: +1. resized image as PhotoImage or +2. -1 (Error Handling purpose) ''' def resize_image(image_path, width, height): - img = Image.open(image_path) - img = img.resize((width, height), Image.LANCZOS) - return ImageTk.PhotoImage(img) + try: + img = Image.open(image_path) + img = img.resize((width, height), Image.LANCZOS) + return ImageTk.PhotoImage(img) + except Exception as error_image_path: + print(f"Error loading image, {error_image_path}") + return -1 + download_logo = resize_image('images/download_logo.png', 50, 50) @@ -63,37 +98,42 @@ def resize_image(image_path, width, height): ping_logo = resize_image('images/ping_logo.png', 50, 50) -download_logo_label = tk.Label(root, image=download_logo) -download_logo_label.grid(row=0, column=0, padx=10, pady=10) -download_label = tk.Label(root, text="Click SpeedTest....") -download_label.grid(row=0, column=1, padx=10, pady=10) +if download_logo==-1 or upload_logo==-1 or ping_logo==-1: #If failed to load image from specified path, exit tkinter + print('Error loading Logos') + root.destroy() + +else: + download_logo_label = tk.Label(root, image=download_logo) + download_logo_label.grid(row=0, column=0, padx=10, pady=10) + download_label = tk.Label(root, text="Click SpeedTest....") + download_label.grid(row=0, column=1, padx=10, pady=10) -tk.Label(root, text="", bg="#9F9998").grid(row=1) #add space of 1 row btw two sections + tk.Label(root, text="", bg="#9F9998").grid(row=1) #add space of 1 row btw two sections -upload_logo_label = tk.Label(root, image=upload_logo) -upload_logo_label.grid(row=2, column=0, padx=10, pady=10) -upload_label = tk.Label(root, text="Click SpeedTest....") -upload_label.grid(row=2, column=1, padx=10, pady=10) + upload_logo_label = tk.Label(root, image=upload_logo) + upload_logo_label.grid(row=2, column=0, padx=10, pady=10) + upload_label = tk.Label(root, text="Click SpeedTest....") + upload_label.grid(row=2, column=1, padx=10, pady=10) -tk.Label(root, text="", bg="#9F9998").grid(row=3) #add space of 1 row btw two sections + tk.Label(root, text="", bg="#9F9998").grid(row=3) #add space of 1 row btw two sections -ping_logo_label = tk.Label(root, image=ping_logo) -ping_logo_label.grid(row=4, column=0, padx=10, pady=10) -ping_label = tk.Label(root, text="Click SpeedTest....") -ping_label.grid(row=4, column=1, padx=10, pady=10) + ping_logo_label = tk.Label(root, image=ping_logo) + ping_logo_label.grid(row=4, column=0, padx=10, pady=10) + ping_label = tk.Label(root, text="Click SpeedTest....") + ping_label.grid(row=4, column=1, padx=10, pady=10) -#add space of 2 rows btw two sections -tk.Label(root, text="", bg="#9F9998").grid(row=5) -tk.Label(root, text="", bg="#9F9998").grid(row=6) + #add space of 2 rows btw two sections + tk.Label(root, text="", bg="#9F9998").grid(row=5) + tk.Label(root, text="", bg="#9F9998").grid(row=6) -check_speed_button = ttk.Button(root, text='SpeedTest', command=check_speed) #this button will trigger check_speed() function initialzing speedTest -check_speed_button.grid(row=8, column=1, padx=7, pady=5, sticky='w') + check_speed_button = ttk.Button(root, text='SpeedTest', command=intiate_check_speed) #this button will trigger check_speed() function initialzing speedTest + check_speed_button.grid(row=8, column=1, padx=7, pady=5, sticky='w') -tk.Label(root, text="", bg="#9F9998").grid(row=9) #add space of 1 row btw two sections + tk.Label(root, text="", bg="#9F9998").grid(row=9) #add space of 1 row btw two sections -quit_button = ttk.Button(root, text="Quit", command=root.destroy) #quit button -quit_button.grid(row=10, column=1, padx=7, pady=5, sticky='w') + quit_button = ttk.Button(root, text="Quit", command=root.destroy) #quit button + quit_button.grid(row=10, column=1, padx=7, pady=5, sticky='w') root.mainloop()