From 7f6cad6ada8ddd182fb2471cbad4a99e31b11d48 Mon Sep 17 00:00:00 2001 From: Carlos Cabral Date: Thu, 26 Dec 2024 19:30:50 -0300 Subject: [PATCH 1/5] Improving formatting --- carryout_rotor.py | 189 +++++++++++++++++++++++----------------------- 1 file changed, 93 insertions(+), 96 deletions(-) diff --git a/carryout_rotor.py b/carryout_rotor.py index 11a1c55..3081c9a 100644 --- a/carryout_rotor.py +++ b/carryout_rotor.py @@ -1,113 +1,110 @@ -#Python program to control Winegard Carryout as an AZ/EL Rotor from Gpredict -#Version 1.0 -#Gabe Emerson / Saveitforparts 2024, Email: gabe@saveitforparts.com +# Python program to control Winegard Carryout as an AZ/EL Rotor from Gpredict +# Version 1.0 +# Gabe Emerson / Saveitforparts 2024, Email: gabe@saveitforparts.com + +import socket -import serial -import socket import regex as re +import serial -#initialize some variables -current_az = 0.0 +# initialize some variables +current_az = 0.0 current_el = 0.0 index = 0 -#define "carryout" as the serial port device to interface with +# define "carryout" as the serial port device to interface with carryout = serial.Serial( - port='/dev/ttyUSB0', #pass this from command line in future? - baudrate = 57600, - parity=serial.PARITY_NONE, - stopbits=serial.STOPBITS_ONE, - bytesize=serial.EIGHTBITS, - timeout=1) - -print ('Carryout antenna connected on ', carryout.port) - -carryout.write(bytes(b'q\r')) #go back to root menu in case firmware was left in a submenu -carryout.write(bytes(b'\r')) #clear firmware prompt to avoid unknown command errors - - -#listen to local port for rotctld commands -listen_ip = '127.0.0.1' #listen on localhost -listen_port = 4533 #pass this from command line in future? + port="/dev/ttyUSB0", # pass this from command line in future? + baudrate=57600, + parity=serial.PARITY_NONE, + stopbits=serial.STOPBITS_ONE, + bytesize=serial.EIGHTBITS, + timeout=1, +) + +print("Carryout antenna connected on ", carryout.port) + +carryout.write( + bytes(b"q\r") +) # go back to root menu in case firmware was left in a submenu +carryout.write(bytes(b"\r")) # clear firmware prompt to avoid unknown command errors + + +# listen to local port for rotctld commands +listen_ip = "127.0.0.1" # listen on localhost +listen_port = 4533 # pass this from command line in future? client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) client_socket.bind((listen_ip, listen_port)) client_socket.listen(1) -print ('Listening for rotor commands on', listen_ip, ':', listen_port) +print("Listening for rotor commands on", listen_ip, ":", listen_port) conn, addr = client_socket.accept() -print ('Connection from ',addr) +print("Connection from ", addr) -#Would be nice to get initial / resting position from Carryout firmware -#I have not found a way to do this, just live position while motors are running +# Would be nice to get initial / resting position from Carryout firmware +# I have not found a way to do this, just live position while motors are running -#pass rotor commands to Carryout +# pass rotor commands to Carryout while 1: - data = conn.recv(100) #get Gpredict's message - if not data: - break - - cmd = data.decode("utf-8").strip().split(" ") #grab the incoming command - - #print("Received: ",cmd) #debugging, what did Gpredict send? - - if cmd[0] == "p": #Gpredict is requesting current position - response = "{}\n{}\n".format(current_az, current_el) - conn.send(response.encode('utf-8')) - - elif cmd[0] == "P": #Gpredict is sending desired position - target_az = float(cmd[1]) - target_el = float(cmd[2]) - print(' Move antenna to:', target_az, ' ', target_el, end="\r") - - - #tell Carryout to move to target position - carryout.write(bytes(b'target\r')) - command = ('g ' + str(target_az) + ' ' + str(target_el) + '\r').encode('ascii') - carryout.write(command) - - - #read live position updates from Carryout - reply = carryout.read(100).decode().strip() #read dish response - header, *readings = reply.split(" ") #Split into list - [re.sub('[^a-z0-9]+', '', _) for _ in readings] #clean out garbage chars - #print('Carryout replied:', readings) #debugging - - - #massage messy output into az/el - while index < len(readings): - if readings[index] == "el" and (index+2) < len(readings): - current_az = readings[index-3] - current_el = readings[index+2] - current_el = current_el[:4] #strip off excess garbage - current_az = int(current_az)/100 #convert to format Gpredict expects - current_el = int(current_el)/100 #(Add the decimal) - index +=1 #maybe unnecessary - break - else: - index +=1 - continue - - #Tell Gpredict things went correctly - response="RPRT 0\n " #Everything's under control, situation normal - conn.send(response.encode('utf-8')) - - carryout.write(bytes(b'q\r')) #go back to Carryout's root menu - - - elif cmd[0] == "S": #Gpredict says to stop - print('Gpredict disconnected, exiting') #Do we want to do something else with this? - conn.close() - carryout.close() - exit() - else: - print('Exiting') - conn.close() - carryout.close() - exit() - - - - - + data = conn.recv(100) # get Gpredict's message + if not data: + break + + cmd = data.decode("utf-8").strip().split(" ") # grab the incoming command + + # print("Received: ",cmd) #debugging, what did Gpredict send? + + if cmd[0] == "p": # Gpredict is requesting current position + response = "{}\n{}\n".format(current_az, current_el) + conn.send(response.encode("utf-8")) + + elif cmd[0] == "P": # Gpredict is sending desired position + target_az = float(cmd[1]) + target_el = float(cmd[2]) + print(" Move antenna to:", target_az, " ", target_el, end="\r") + + # tell Carryout to move to target position + carryout.write(bytes(b"target\r")) + command = ("g " + str(target_az) + " " + str(target_el) + "\r").encode("ascii") + carryout.write(command) + + # read live position updates from Carryout + reply = carryout.read(100).decode().strip() # read dish response + header, *readings = reply.split(" ") # Split into list + [re.sub("[^a-z0-9]+", "", _) for _ in readings] # clean out garbage chars + # print('Carryout replied:', readings) #debugging + + # massage messy output into az/el + while index < len(readings): + if readings[index] == "el" and (index + 2) < len(readings): + current_az = readings[index - 3] + current_el = readings[index + 2] + current_el = current_el[:4] # strip off excess garbage + current_az = int(current_az) / 100 # convert to format Gpredict expects + current_el = int(current_el) / 100 # (Add the decimal) + index += 1 # maybe unnecessary + break + else: + index += 1 + continue + + # Tell Gpredict things went correctly + response = "RPRT 0\n " # Everything's under control, situation normal + conn.send(response.encode("utf-8")) + + carryout.write(bytes(b"q\r")) # go back to Carryout's root menu + + elif cmd[0] == "S": # Gpredict says to stop + print( + "Gpredict disconnected, exiting" + ) # Do we want to do something else with this? + conn.close() + carryout.close() + exit() + else: + print("Exiting") + conn.close() + carryout.close() + exit() From e840515d45d0cf340ecbc07de0bfecd3eec666db Mon Sep 17 00:00:00 2001 From: Carlos Cabral Date: Thu, 26 Dec 2024 19:31:49 -0300 Subject: [PATCH 2/5] Remove unnecessary bytes call --- carryout_rotor.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/carryout_rotor.py b/carryout_rotor.py index 3081c9a..7180037 100644 --- a/carryout_rotor.py +++ b/carryout_rotor.py @@ -24,10 +24,8 @@ print("Carryout antenna connected on ", carryout.port) -carryout.write( - bytes(b"q\r") -) # go back to root menu in case firmware was left in a submenu -carryout.write(bytes(b"\r")) # clear firmware prompt to avoid unknown command errors +carryout.write(b"q\r") # go back to root menu in case firmware was left in a submenu +carryout.write(b"\r") # clear firmware prompt to avoid unknown command errors # listen to local port for rotctld commands @@ -66,7 +64,7 @@ print(" Move antenna to:", target_az, " ", target_el, end="\r") # tell Carryout to move to target position - carryout.write(bytes(b"target\r")) + carryout.write(b"target\r") command = ("g " + str(target_az) + " " + str(target_el) + "\r").encode("ascii") carryout.write(command) @@ -94,7 +92,7 @@ response = "RPRT 0\n " # Everything's under control, situation normal conn.send(response.encode("utf-8")) - carryout.write(bytes(b"q\r")) # go back to Carryout's root menu + carryout.write(b"q\r") # go back to Carryout's root menu elif cmd[0] == "S": # Gpredict says to stop print( From 0190f011963b58e8c0db69621aead4b14f927981 Mon Sep 17 00:00:00 2001 From: Carlos Cabral Date: Thu, 26 Dec 2024 19:37:49 -0300 Subject: [PATCH 3/5] f-strings are more readable --- carryout_rotor.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/carryout_rotor.py b/carryout_rotor.py index 7180037..c77f6a6 100644 --- a/carryout_rotor.py +++ b/carryout_rotor.py @@ -35,9 +35,9 @@ client_socket.bind((listen_ip, listen_port)) client_socket.listen(1) -print("Listening for rotor commands on", listen_ip, ":", listen_port) +print(f"Listening for rotor commands on {listen_ip} : {listen_port}") conn, addr = client_socket.accept() -print("Connection from ", addr) +print(f"Connection from {addr}") # Would be nice to get initial / resting position from Carryout firmware @@ -52,20 +52,20 @@ cmd = data.decode("utf-8").strip().split(" ") # grab the incoming command - # print("Received: ",cmd) #debugging, what did Gpredict send? + # print(f"Received: {cmd}") #debugging, what did Gpredict send? if cmd[0] == "p": # Gpredict is requesting current position - response = "{}\n{}\n".format(current_az, current_el) + response = f"{current_az}\n{current_el}\n" conn.send(response.encode("utf-8")) elif cmd[0] == "P": # Gpredict is sending desired position target_az = float(cmd[1]) target_el = float(cmd[2]) - print(" Move antenna to:", target_az, " ", target_el, end="\r") + print(f"Move antenna to: {target_az} {target_el}", end="\r") # tell Carryout to move to target position carryout.write(b"target\r") - command = ("g " + str(target_az) + " " + str(target_el) + "\r").encode("ascii") + command = (f"g {target_az} {target_el}\r").encode("ascii") carryout.write(command) # read live position updates from Carryout From 5362fbb0d758633330dbe65447c401d01ef519b6 Mon Sep 17 00:00:00 2001 From: Carlos Cabral Date: Thu, 26 Dec 2024 19:43:08 -0300 Subject: [PATCH 4/5] Use sys.exit() instead of exit (PLR1722) --- carryout_rotor.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/carryout_rotor.py b/carryout_rotor.py index c77f6a6..7275b63 100644 --- a/carryout_rotor.py +++ b/carryout_rotor.py @@ -3,6 +3,7 @@ # Gabe Emerson / Saveitforparts 2024, Email: gabe@saveitforparts.com import socket +import sys import regex as re import serial @@ -95,14 +96,12 @@ carryout.write(b"q\r") # go back to Carryout's root menu elif cmd[0] == "S": # Gpredict says to stop - print( - "Gpredict disconnected, exiting" - ) # Do we want to do something else with this? + print("Gpredict disconnected, exiting") # Do we want to do something else with this? conn.close() carryout.close() - exit() + sys.exit() else: print("Exiting") conn.close() carryout.close() - exit() + sys.exit() From 266571fcf810d5c458e2cf5c791388c82ba8c5cc Mon Sep 17 00:00:00 2001 From: Carlos Cabral Date: Fri, 27 Dec 2024 00:50:54 -0300 Subject: [PATCH 5/5] Add argparse for command-line argument parsing --- carryout_rotor.py | 60 +++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 55 insertions(+), 5 deletions(-) diff --git a/carryout_rotor.py b/carryout_rotor.py index 7275b63..2d28438 100644 --- a/carryout_rotor.py +++ b/carryout_rotor.py @@ -2,12 +2,61 @@ # Version 1.0 # Gabe Emerson / Saveitforparts 2024, Email: gabe@saveitforparts.com +import argparse import socket import sys import regex as re import serial + +def parse_arguments(): + """Parse command-line arguments for configuring the Winegard Carryout controller. + + This function defines and parses the command-line arguments required to configure + the serial communication and TCP/IP settings for interfacing with the Winegard Carryout + antenna and Gpredict. + + Returns: + argparse.Namespace: Parsed command-line arguments containing: + - port (str): Serial port to communicate with the Winegard Carryout. + - baudrate (int): Baudrate for the serial communication. + - listen_ip (str): IP address to listen for Gpredict commands. + - listen_port (int): Port to listen for Gpredict commands. + """ + parser = argparse.ArgumentParser( + description="Control Winegard Carryout as an AZ/EL Rotor from Gpredict.", + ) + parser.add_argument( + "--port", + type=str, + default="/dev/ttyUSB0", + help="Serial port to communicate with the Winegard Carryout.", + ) + parser.add_argument( + "--baudrate", + type=int, + default=57600, + help="Baudrate for the serial communication.", + ) + parser.add_argument( + "--listen_ip", + type=str, + default="127.0.0.1", + help="IP address to listen for Gpredict commands.", + ) + parser.add_argument( + "--listen_port", + type=int, + default=4533, + help="Port to listen for Gpredict commands.", + ) + return parser.parse_args() + + +# Parse command-line arguments +args = parse_arguments() + # initialize some variables current_az = 0.0 current_el = 0.0 @@ -15,8 +64,8 @@ # define "carryout" as the serial port device to interface with carryout = serial.Serial( - port="/dev/ttyUSB0", # pass this from command line in future? - baudrate=57600, + port=args.port, + baudrate=args.baudrate, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE, bytesize=serial.EIGHTBITS, @@ -30,8 +79,8 @@ # listen to local port for rotctld commands -listen_ip = "127.0.0.1" # listen on localhost -listen_port = 4533 # pass this from command line in future? +listen_ip = args.listen_ip # Use the IP address provided via command-line arguments +listen_port = args.listen_port # Use the port provided via command-line arguments client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) client_socket.bind((listen_ip, listen_port)) client_socket.listen(1) @@ -73,7 +122,8 @@ reply = carryout.read(100).decode().strip() # read dish response header, *readings = reply.split(" ") # Split into list [re.sub("[^a-z0-9]+", "", _) for _ in readings] # clean out garbage chars - # print('Carryout replied:', readings) #debugging + + # print(f"Carryout replied: {readings}") # debugging # massage messy output into az/el while index < len(readings):