1+ #! /usr/bin/python3
2+
3+ ##------------------------------------------------------------------------------------------------\
4+ # tinySA_python (tsapython)
5+ # './tests/test_example_workflow.py'
6+ # UNOFFICIAL Python API based on the tinySA official documentation at https://www.tinysa.org/wiki/
7+ #
8+ # Full workflow test. This was originally "hello_world.py" in the examples, but has been modified
9+ # to include feedback in a 'test' format. This is a more realistic format than the tests.
10+ # HARDWARE IS REQUIRED
11+ #
12+ # Run with: python tests/test_example_workflow.py
13+ #
14+ #
15+ # Author(s): Lauren Linkous
16+ # Last update: August 17, 2025
17+ ##--------------------------------------------------------------------------------------------------\
18+
19+
20+ import matplotlib .pyplot as plt
21+
22+
23+ def run_complete_example ():
24+ """Run the complete tinySA example workflow."""
25+
26+
27+ print ("=" * 50 )
28+ print ("RUNNING COMPLETE EXAMPLE WORKFLOW" )
29+ print ("=" * 50 )
30+
31+ try :
32+ from tsapython import tinySA
33+
34+ # Create a new tinySA object
35+ tsa = tinySA ()
36+
37+ # Set the return message preferences
38+ tsa .set_verbose (True )# detailed messages
39+ tsa .set_error_byte_return (True )# get explicit b'ERROR' if error thrown
40+
41+ # Attempt to autoconnect
42+ print ("Attempting to connect to device..." )
43+ found_bool ,connected_bool = tsa .autoconnect ()
44+
45+ # If port found and connected, then complete task(s) and disconnect
46+ if connected_bool :
47+ print ("PASS! Device connected" )
48+
49+ # Print the device ID
50+ msg = tsa .get_device_id ()
51+ print (f"Device ID:{ msg } " )
52+
53+ # Get the device info
54+ msg = tsa .info ()
55+ print (f"Device Info:{ msg } " )
56+
57+ # Collect some data!
58+ start_freq = 100e6 # 100 MHz
59+ stop_freq = 500e6 # 500 MHz
60+ n_pts = 101 # take 101 pts
61+
62+ print (f"Collecting data from{ start_freq / 1e6 :.1f} MHz to{ stop_freq / 1e6 :.1f} MHz ({ n_pts } points)..." )
63+
64+ # Pause the device so we can play with a single trace data
65+ tsa .pause ()
66+
67+ # Get the Frequency vals the measurements happen at
68+ outmask_select = 1 # 1 for step in hz, 2 for step in pts
69+ freq_vals = tsa .hop (start_freq ,stop_freq ,n_pts ,outmask_select )
70+ print (f"PASS! Frequency data collected:{ len (freq_vals .decode ('utf-8' ).split ())} points" )
71+
72+ # Get the dBm measurements for the freq
73+ outmask_select = 2 # 1 for step in hz, 2 for step in pts
74+ dbm_vals = tsa .hop (start_freq ,stop_freq ,n_pts ,outmask_select )
75+ print (f"PASS! Power data collected:{ len (dbm_vals .decode ('utf-8' ).split ())} points" )
76+
77+ # Disconnect because we've taken the data and don't need the device anymore
78+ tsa .disconnect ()
79+ print ("PASS! Device disconnected" )
80+
81+ # PLOTTING EXAMPLE
82+ print ("Creating plot..." )
83+ try :
84+ # Python version of conversion, without data checking or sanitizing
85+ x_val = [float (x )for x in freq_vals .decode ('utf-8' ).split ()]
86+ y_val = [float (x )for x in dbm_vals .decode ('utf-8' ).split ()]
87+
88+ # Create plot
89+ plt .figure (figsize = (12 ,8 ))
90+ plt .plot (x_val ,y_val ,'b-' ,linewidth = 1.5 ,alpha = 0.8 )
91+ plt .xlabel ("Frequency (Hz)" ,fontsize = 12 )
92+ plt .ylabel ("Measured Data (dBm)" ,fontsize = 12 )
93+ plt .title ("tinySA Hop() Plot - Complete Example" ,fontsize = 14 ,fontweight = 'bold' )
94+ plt .grid (True ,alpha = 0.3 )
95+
96+ # Format x-axis to show frequencies in a readable format
97+ plt .ticklabel_format (style = 'scientific' ,axis = 'x' ,scilimits = (0 ,0 ))
98+
99+ # Save the plot
100+ plot_filename = "example_sweep_plot.png"
101+ plt .savefig (plot_filename ,dpi = 150 ,bbox_inches = 'tight' )
102+ print (f"PASS! Plot saved as:{ plot_filename } " )
103+
104+ # Show the plot
105+ plt .show ()
106+
107+ print ("DONE! Complete example workflow finished successfully!" )
108+ return True
109+
110+ except Exception as plot_error :
111+ print (f"ERROR: Plotting failed:{ plot_error } " )
112+ return False
113+
114+ else :
115+ print ("ERROR: could not connect to port" )
116+ print ("Make sure your tinySA device is connected and try again." )
117+ return False
118+
119+ except Exception as e :
120+ print (f"ERROR: Example workflow failed:{ e } " )
121+ return False
122+
123+
124+ if __name__ == "__main__" :
125+ # this will run hardware tests when the file is executed directly.
126+ # this call does not happen anywhere in the core library, so it needs to be deliberate
127+
128+ # Hardware MUST be connected
129+
130+
131+ success = run_complete_example ()
132+ if success :
133+ print ("\n Example completed successfully!" )
134+ else :
135+ print ("\n WARNING: Example had issues - check device connection" )