1use rs_teststand::{
16 ConflictHandler, Engine, GetSeqFileOptions, PropValType, PropertyObject, SequenceFile,
17};
18
19const INSERT_IF_MISSING: i32 = 1;
21
22fn set_string(
24 container: &PropertyObject,
25 name: &str,
26 value: &str,
27) -> Result<(), rs_teststand::Error> {
28 if !container.exists(name, 0)? {
29 container.new_sub_property(name, PropValType::String, false, "", INSERT_IF_MISSING)?;
30 }
31 container.set_val_string(name, 0, value)
32}
33
34fn temporary_variable_lifecycle(container: &PropertyObject) -> Result<(), rs_teststand::Error> {
39 let name = "TempScratch";
40 let clone_name = "TempScratchCopy";
41 for stale in [name, clone_name] {
42 if container.exists(stale, 0)? {
43 container.delete_sub_property(stale, 0)?;
44 }
45 }
46
47 container.new_sub_property(name, PropValType::String, false, "", INSERT_IF_MISSING)?;
48 container.set_val_string(name, 0, "scratch")?;
49 println!(
50 " created {name} (String) = '{}'",
51 container.get_val_string(name, 0)?
52 );
53
54 container.delete_sub_property(name, 0)?;
55 container.new_sub_property(name, PropValType::Number, false, "", INSERT_IF_MISSING)?;
56 container.set_val_number(name, 0, 42.0)?;
57 println!(
58 " retyped {name} -> Number = {}",
59 container.get_val_number(name, 0)?
60 );
61
62 let copy = container.clone_property(name, 0)?;
64 container.set_property_object(clone_name, INSERT_IF_MISSING, ©)?;
65 println!(
66 " cloned {name} -> {clone_name} = {}",
67 container.get_val_number(clone_name, 0)?
68 );
69
70 container.delete_sub_property(clone_name, 0)?;
71 container.delete_sub_property(name, 0)?;
72 println!(
73 " removed both: {name} exists={}, {clone_name} exists={}",
74 container.exists(name, 0)?,
75 container.exists(clone_name, 0)?
76 );
77 Ok(())
78}
79
80fn open_sequence_file(engine: &Engine) -> Result<Option<SequenceFile>, rs_teststand::Error> {
85 let Some(path) = std::env::args().nth(1) else {
86 return Ok(None);
87 };
88 let file = engine.get_sequence_file_ex(
89 &path,
90 GetSeqFileOptions::DO_NOT_RUN_LOAD_CALLBACK,
91 ConflictHandler::Error,
92 )?;
93 Ok(Some(file))
94}
95
96fn show_station_globals(engine: &Engine) -> Result<(), rs_teststand::Error> {
101 let station_globals = engine.globals()?;
103 if !station_globals.exists("StationInfo", 0)? {
104 station_globals.new_sub_property(
105 "StationInfo",
106 PropValType::Container,
107 false,
108 "",
109 INSERT_IF_MISSING,
110 )?;
111 }
112 let station_info = station_globals.get_property_object("StationInfo", 0)?;
113
114 set_string(&station_info, "StationName", "STATION_01")?;
117 station_info.set_val_number("CalibrationIntervalDays", INSERT_IF_MISSING, 90.0)?;
118 station_info.set_val_bool("FixtureInstalled", INSERT_IF_MISSING, true)?;
119
120 station_info.set_val_integer64("UnitsTestedTotal", INSERT_IF_MISSING, 9_007_199_254_740_993)?;
124
125 if !station_info.exists("LastCalibration", 0)? {
127 station_info.new_sub_property(
128 "LastCalibration",
129 PropValType::Container,
130 false,
131 "",
132 INSERT_IF_MISSING,
133 )?;
134 }
135 let calibration = station_info.get_property_object("LastCalibration", 0)?;
136 set_string(&calibration, "Technician", "R. Alvarez")?;
137 set_string(&calibration, "Date", "2026-06-14")?;
138
139 println!("StationGlobals.StationInfo:");
140 println!(
141 " StationName = '{}'",
142 station_info.get_val_string("StationName", 0)?
143 );
144 println!(
145 " CalibrationIntervalDays = {}",
146 station_info.get_val_number("CalibrationIntervalDays", 0)?
147 );
148 println!(
149 " FixtureInstalled = {}",
150 station_info.get_val_bool("FixtureInstalled", 0)?
151 );
152 println!(
153 " UnitsTestedTotal = {}",
154 station_info.get_val_integer64("UnitsTestedTotal", 0)?
155 );
156 println!(
157 " LastCalibration.Technician = '{}' on {}",
158 calibration.get_val_string("Technician", 0)?,
159 calibration.get_val_string("Date", 0)?
160 );
161
162 println!(
165 " walked, {} field(s):",
166 station_info.get_num_sub_properties("")?
167 );
168 for index in 0..station_info.get_num_sub_properties("")? {
169 println!(
170 " {}",
171 station_info.get_nth_sub_property_name("", index, 0)?
172 );
173 }
174
175 engine.commit_globals_to_disk(false)?;
181 println!(" committed to disk");
182
183 Ok(())
184}
185
186fn main() -> Result<(), rs_teststand::Error> {
187 let engine = Engine::new()?;
188
189 show_station_globals(&engine)?;
190
191 if let Some(sequence_file) = open_sequence_file(&engine)? {
193 let file_globals = sequence_file.file_globals_default_values()?;
196 set_string(&file_globals, "BatchID", "BATCH-2026-Q2-001")?;
197 println!(
198 "FileGlobals.BatchID = '{}'",
199 file_globals.get_val_string("BatchID", 0)?
200 );
201
202 let main_sequence = sequence_file.get_sequence_by_name("MainSequence")?;
203
204 let locals = main_sequence.locals()?;
206 set_string(&locals, "OperatorName", "Alice")?;
207 println!(
208 "MainSequence.Locals.OperatorName = '{}'",
209 locals.get_val_string("OperatorName", 0)?
210 );
211
212 let parameters = main_sequence.parameters()?;
214 set_string(¶meters, "DUTSerial", "SN-000000")?;
215 println!(
216 "MainSequence.Parameters.DUTSerial = '{}'",
217 parameters.get_val_string("DUTSerial", 0)?
218 );
219
220 println!("\nTemporary variable lifecycle (Locals.TempScratch):");
221 temporary_variable_lifecycle(&locals)?;
222
223 engine.release_sequence_file_ex(sequence_file, 0)?;
225 } else {
226 println!("\n(pass a .seq path to also demonstrate locals, parameters and file globals)");
227 println!("\nTemporary variable lifecycle (StationGlobals.TempScratch):");
228 temporary_variable_lifecycle(&engine.globals()?)?;
229 }
230
231 engine.commit_globals_to_disk(false)?;
232 println!("\nStation globals committed to disk.");
233 Ok(())
234}