diff --git a/tools/flaskIfc/README.md b/tools/flaskIfc/README.md new file mode 100644 index 0000000000000..4893dc75147c8 --- /dev/null +++ b/tools/flaskIfc/README.md @@ -0,0 +1,46 @@ +This tool provides you an interface to Tsavorite FPGA via a serial console + +The tool consists of following files + +. +├── flaskCommon.py << Common code but currently not used +├── flaskIfc.py << Browser based console interface to TSI device +├── flaskXterm.py << Browser based terminal emulation +├── README.md << Readme file +└── serial_script.py << File with serial interface to console + + +The command to run to run the service on FPGA machine is +``` +flask -A flaskIfc.py --debug run --port 5000 +``` + +This command runs a webserver at port number 500 + +The curl command to connect to this server and communicate is as follows as +an example + +``` +curl "http://localhost:5000/serial?command=cd+%20/usr/bin/tsi/v0.1.1.tsv31_06_06_2025/bin/;./run_platform_test.sh" +``` + +In the above command the command being run is + +``` +cd /usr/bin/tsi/v0.1.1.tsv31_06_06_2025/bin +./run_platform_test.sh +``` + +You can also get full fledged Terminal within a browser by running following + +``` +flask -A flaskXterm.py --debug run --port 5000 +``` + +You can connect to this flaskTerm by doing as follows + +``` +http://127.0.0.1:5000/terminal +``` + + diff --git a/tools/flaskIfc/flaskCommon.py b/tools/flaskIfc/flaskCommon.py new file mode 100644 index 0000000000000..eb93a63fcf395 --- /dev/null +++ b/tools/flaskIfc/flaskCommon.py @@ -0,0 +1,85 @@ + +from flask import Flask +from flask_terminal import terminal_blueprint, configure_logger +from flask import Flask, render_template, request +import serial + + +app = Flask(__name__) +app.logger = configure_logger('flask_terminal') + +app.config['SECRET_KEY'] = 'your_secret_key_here' + + +@app.route('/ping') +def ping(): + app.logger.info("Accessed /ping route") + try: + app.logger.info("Successfully returned 'pong'") + return 'pong', 200 + except Exception as e: + app.logger.error(f"Error in ping route: {e}", exc_info=True) + return "An error occurred", 500 + +#### +## IMPLEMENT SOME SORT OF SECURITY +## Around your application, below is an example +### +def is_authenticated(): + """Check if the user is authenticated based on a token stored in the session.""" + # Example logic for checking if a user is authenticated + return 'user_token' in session and session['user_token'] == 'your_secure_token' + +#@terminal_blueprint.before_request +#def before_request_func(): +# if not is_authenticated(): + # Redirect to login page or return an error +# current_app.logger.info("User not authenticated, redirecting to login.") +# return redirect('/login') # Adjusted to use a direct path + + +# Register the terminal blueprint +#app.register_blueprint(terminal_blueprint, url_prefix='/terminal') + +#if __name__ == '__main__': +# app.run(port=8080) + + + +try: + ser = serial.Serial('/dev/ttyUSB3', 921600) # Replace /dev/ttyUSB3 with your port and baud rate +except serial.SerialException as e: + print(f"Error opening serial port: {e}") + ser = None # Handle case where serial port cannot be opened + +@app.route('/send', methods=['POST']) +def send_data(): + if ser is None: + return "Serial port not available", 500 + data = request.form['data'] # Get data from the form + try: + ser.write(data.encode()) # Convert to bytes and send + return 'Data sent successfully' + except serial.SerialException as e: + return f"Error writing to serial port: {e}", 500 + + +@app.route('/receive') +def receive_data(): + if ser is None: + return "Serial port not available", 500 + try: + if ser.in_waiting > 0: + data = ser.readline().decode().strip() # Read and decode + return data + else: + return "No data available" + except serial.SerialException as e: + return f"Error reading from serial port: {e}", 500 + +# Register the terminal blueprint +#app.register_blueprint(terminal_blueprint, url_prefix='/terminal') + +if __name__ == '__main__': + app.run(port=8080) + diff --git a/tools/flaskIfc/flaskIfc.py b/tools/flaskIfc/flaskIfc.py new file mode 100644 index 0000000000000..61187c91a09d4 --- /dev/null +++ b/tools/flaskIfc/flaskIfc.py @@ -0,0 +1,32 @@ +from flask import Flask, request +import subprocess + +app = Flask(__name__) + +@app.route('/serial', methods=['GET']) +def serial_command(): + # Currently the port is hard coded to /dev/ttyUSB3 but can be parameterized + port = '/dev/ttyUSB3' + #port = request.args.get('port') + + # Currently the baudrate is hard coded to 921600 but can be parameterized + #baudrate = request.args.get('baudrate') + baudrate = '921600' + + + # Parse the command and send it to serial.py + command = request.args.get('command') + + #if not all([port, baudrate, command]): + if not all([command]): + return "Missing parameters", 400 + + try: + result = subprocess.run(['python3', 'serial_script.py', port, baudrate, command], capture_output=True, text=True, check=True) + return result.stdout.strip(), 200 + except subprocess.CalledProcessError as e: + return f"Error executing script: {e.stderr}", 500 + + +if __name__ == '__main__': + app.run(debug=True, port=5000) diff --git a/tools/flaskIfc/flaskXterm.py b/tools/flaskIfc/flaskXterm.py new file mode 100644 index 0000000000000..df7ecf391471d --- /dev/null +++ b/tools/flaskIfc/flaskXterm.py @@ -0,0 +1,43 @@ + +from flask import Flask +from flask_terminal import terminal_blueprint, configure_logger + + +app = Flask(__name__) +app.logger = configure_logger('flask_terminal') + +app.config['SECRET_KEY'] = 'your_secret_key_here' + + +@app.route('/ping') +def ping(): + app.logger.info("Accessed /ping route") + try: + app.logger.info("Successfully returned 'pong'") + return 'pong', 200 + except Exception as e: + app.logger.error(f"Error in ping route: {e}", exc_info=True) + return "An error occurred", 500 + +#### +## IMPLEMENT SOME SORT OF SECURITY +## Around your application, below is an example +### +def is_authenticated(): + """Check if the user is authenticated based on a token stored in the session.""" + # Example logic for checking if a user is authenticated + return 'user_token' in session and session['user_token'] == 'your_secure_token' + +#@terminal_blueprint.before_request +#def before_request_func(): +# if not is_authenticated(): + # Redirect to login page or return an error +# current_app.logger.info("User not authenticated, redirecting to login.") +# return redirect('/login') # Adjusted to use a direct path + + +# Register the terminal blueprint +app.register_blueprint(terminal_blueprint, url_prefix='/terminal') + +if __name__ == '__main__': + app.run(port=8080) diff --git a/tools/flaskIfc/serial_script.py b/tools/flaskIfc/serial_script.py new file mode 100644 index 0000000000000..e61f926d0bf47 --- /dev/null +++ b/tools/flaskIfc/serial_script.py @@ -0,0 +1,44 @@ +import serial +import sys + +def send_serial_command(port, baudrate, command): + try: + # Open the serial port with 1 second timeout + ser = serial.Serial(port, baudrate, timeout=1) + + ser.write(command.encode()) # Encode command to bytes + ser.write('\n'.encode()) # Encode command to bytes + + # Wait to read the serial port + data = '\0' + while True: + try: + line = ser.readline() + if line: # Check if line is not empty + data += (line.decode('utf-8').strip()) # Decode and strip to remove extra chars + else: + break # Exit loop if no data is received + except serial.SerialException as e: + ser.close() + return (f"Error reading from serial port: {e}") + except KeyboardInterrupt: + ser.close() + return ("Program interrupted by user") + ser.close() + return data + + except serial.SerialException as e: + ser.close() + return f"Error: {e}" + +# This script can be run in standalone as well +if __name__ == "__main__": + if len(sys.argv) < 4: + print("Usage: python script.py ") + sys.exit(1) + + port = sys.argv[1] + baudrate = int(sys.argv[2]) + command = sys.argv[3] + response = send_serial_command(port, baudrate, command) + print(response)