How to flush the data in pysimplegui. As I want the response to be displayed immeadiatly as it is received instead of storing it in some kind of buffer and then displaying it. flush = true is not working over here as i am using Multiline element of pysimplegui to display the response , so it is not allowing me to use flush- true in this portion of code:
for ip in ip_list: response = await ping(ip) window.refresh() await asyncio.sleep(2) window['multi_pi_log'].print(f'res -> {response}', flush=True)
Here is my code:
import reimport PySimpleGUI as sgimport paramikoimport asyncioip_addresses = ['192.168.11.1', '192.168.12.1', '192.168.13.1', '192.162.14.1', '192.168.15.1', '192.168.16.1', '192.168.101.1', '192.168.101.2', '192.168.101.3', '192.168.101.4', '192.168.101.5', '192.168.101.6', '192.168.10.35', '192.168.10.36']async def ping(host): """ Function to ping the host and get the result back. param host: It is the ip address of the PI. """ try: result = await asyncio.create_subprocess_shell( f'ping {host} -n 5', stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE ) stdout, stderr = await result.communicate() return stdout.decode() except Exception: return "Error while pinging."def get_average_latency(ping_output): """ Function to extract average latency from ping output. param ping_output: It is output after pinging the IP address. """ match = re.search(r"Average = (\d+)ms", ping_output) if match: avg_latency = match.group(1) return avg_latency return Nonedef reboot_raspberry_pi(ip_address, username, password): """ It is the function used to reboot raspberry PI. param ip_address: The IP address of the raspberry pi. param username: The username of the pi for the ssh connection. param password: The password of the pi. """ try: ssh = paramiko.SSHClient() # SSH connection to the Raspberry Pi ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) ssh.connect(ip_address, username=username, password=password) # Issue the reboot command for rebooting pi(s) ssh.exec_command('sudo reboot') ssh.close() return True except Exception: return Falseasync def reboot_raspberry_pi_async(ip, username, password): """ This function is created to make the reboot_raspberry_pi function async, as we are using this function below in multi_pi_reboot function with async, await syntax, so we cannot use synchronous function with it. param ip: The IP address of the raspberry pi. param username: The username of the pi for the ssh connection. param password: The password of the pi. """ result = await asyncio.to_thread(reboot_raspberry_pi, ip, username, password) return resultasync def check_multiple_pi_status(ip_list, window): """ This function is created to check the status of multiple PI(s). param ip_list: It is the list of IP address stored, which we are passing to this function to check the status of those ip(s). param window: It is the screen of the GUI. """ for ip in ip_list: response = await ping(ip) window.refresh() await asyncio.sleep(2) window['multi_pi_log'].print(f'res -> {response}', flush=True) avg = get_average_latency(response) if avg is not None: window['multi_pi_log'].print(f'Raspberry Pi at {ip} is online.', text_color='green') else: window['multi_pi_log'].print(f'Raspberry Pi at {ip} is offline.', text_color='red')async def multiple_pi_reboot(ip_list, window): """ This function is created to reboot multiple PI(s) together. param ip_list: It is the list of IP address stored, which we are passing to this function to reboot those ip(s). param window: It is the screen of the GUI. """ reboot_success_count = 0 reboot_fail_count = 0 rebooted_ips = [] reboot_tasks = [] reboot_fail_ips = [] selected_ips_message = "\n".join([f'IP-{ip}' for ip in ip_list]) # Ask for confirmation with the list of IP addresses confirm_reboot = sg.popup_yes_no( f'Are you sure you want to reboot the following Raspberry Pi(s)?\n\n{selected_ips_message}', title='Confirm Reboot') for ip in ip_list: response = await ping(ip) avg = get_average_latency(response) if avg is not None: if confirm_reboot == 'Yes': window['multi_pi_log'].print(f'Initiating reboot...\n', text_color='white') window.refresh() await asyncio.sleep(2) reboot_tasks.append(asyncio.create_task(reboot_raspberry_pi_async(ip, 'lucidauto', 'Lucid@390'))) rebooted_ips.append(ip) # Awaiting all reboot tasks outside the for loop await asyncio.gather(*reboot_tasks) if reboot_tasks: window['multi_pi_log'].print(f'Reboot command sent to Raspberry Pi at \n{", ".join(rebooted_ips)}.\n') window.refresh() await asyncio.sleep(2) window['multi_pi_log'].print('Rebooting...', text_color='white') window.refresh() await asyncio.sleep(2) reboot_success_count += len(rebooted_ips) for ip in ip_list: response = await ping(ip) avg = get_average_latency(response) if avg is not None: if ip in rebooted_ips: window['multi_pi_log'].print(f'Raspberry Pi at {ip} has been successfully rebooted.\n') else: window['multi_pi_log'].print(f'Raspberry Pi at {ip} was not rebooted.\n', text_color='red') reboot_fail_count += 1 reboot_fail_ips.append(ip) # adding ip of the pi to the list which was failed to be rebooted. else: window['multi_pi_log'].print(f'Raspberry Pi at {ip} is offline. Cannot reboot.\n', text_color='red') reboot_fail_count += 1 reboot_fail_ips.append(ip) if reboot_success_count > 0: rebooted_ip_message = ', '.join(rebooted_ips) window['multi_pi_log'].print( f'Successfully rebooted {reboot_success_count} Raspberry Pi(s) with IP Addresses: \n' f'{rebooted_ip_message}.\n', text_color='green') if reboot_fail_count > 0: window['multi_pi_log'].print(f'Failed to reboot {reboot_fail_count} Raspberry Pi(s) with Ip:.\n ' f'{", ".join(reboot_fail_ips)}', text_color='red')# -----------------The layout of the GUI------------------sg.theme("DarkBlue")layout_left = [ [sg.Text('Raspberry PI Control Panel', font=('Bold', 24))], [sg.Text('Select IP Addresses', font=('Bold', 14))],]# Creating a checkbox for each IP address and adding it to the layoutfor ip in ip_addresses: layout_left.append([sg.Checkbox(ip, default=False, key=f'ip_{ip}', size=(16, 1), font=('Arial', 12), background_color='black', text_color='white')])# Creating two buttons for Checking status of pi(s) and rebooting themlayout_left.append( [sg.Button('Check Status', font=('Arial', 12), size=(12, 1), key='multi_status', button_color=('White', 'Green'), pad=(5, 5)), sg.Button('Reboot PI(s)', font=('Arial', 12), size=(12, 1), key='multi_reboot', button_color=('White', 'Green'), pad=(5, 5))])layout_right = [ [sg.Text('Other Processes', font=('Bold', 22), pad=(0, 10))], [sg.Text('System Uptime:', size=(12, 1), font=('Bold', 14)), sg.Text("", size=(12, 1), font=('Bold', 14), key='Uptime')], [sg.Text('Memory Usage:', size=(12, 1), font=('Bold', 14)), sg.Text("", size=(12, 1), font=('Bold', 14), key='Usage')], [sg.Text('Storage Space:', size=(12, 1), font=('Bold', 14)), sg.Text("", size=(12, 1), font=('Bold', 14), key='Storage')], [sg.Text('CPU Temperature:', size=(14, 1), font=('Bold', 14)), sg.Text("", size=(12, 1), key='CPU')], [sg.Text("")], [sg.Multiline(size=(70, 20), background_color='Black', font=('Bold', 11), key='multi_pi_log', autoscroll=True)]]layout = [ [ sg.Column(layout_left, size=(420, 600), pad=(0, 0)), sg.VerticalSeparator(), sg.Column(layout_right, size=(1000, 580), pad=(0, 0)) ]]window = sg.Window('Raspberry Pi Control', layout, finalize=True, size=(1000, 600), resizable=True)async def main(): while True: event, values = window.read() if event == sg.WIN_CLOSED: break if event == 'multi_status': # if clicked on check status button then this event will get executed. window['multi_pi_log'].print('') # Clearing the console every time this event is called window['multi_pi_log'].print('Checking...\n', text_color='white') window.refresh() selected_ips = [ip for ip in ip_addresses if values[f'ip_{ip}']] await check_multiple_pi_status(selected_ips, window) if event == 'multi_reboot': # if clicked on reboot pi(s) button then this event is called. window['multi_pi_log'].print('') window['multi_pi_log'].print('Please wait...\n') selected_ips_for_reboot = [ip for ip in ip_addresses if values[f'ip_{ip}']] await multiple_pi_reboot(selected_ips_for_reboot, window)if __name__ == '__main__': asyncio.run(main()) window.close()
In this code I have created the functionality of checking the status of multiple pi(s) and rebooting them.