#[non_exhaustive]pub enum AdapterKeyName {
NoneAdapter,
LabView,
LabViewStdPrototype,
LabViewNxg,
Cvi,
CviStdPrototype,
DllFlex,
Sequence,
Automation,
DotNet,
Python,
HtBasic,
}Expand description
A code-module adapter, by the key the engine knows it under
(AdapterKeyNames).
The key is what Engine::new_step and
Step::adapter_key_name exchange, and it
is a string rather than a number, so this exists to keep those strings in
one checked place instead of spread across call sites.
use rs_teststand::AdapterKeyName;
assert_eq!(AdapterKeyName::LabView.as_str(), "G Flexible VI Adapter");
assert_eq!(
AdapterKeyName::from_key("Sequence Adapter"),
Some(AdapterKeyName::Sequence)
);A key names an adapter the engine recognizes, not one the station can
necessarily run: calling a LabVIEW step needs LabVIEW present. Building a
step with the key succeeds either way; only running it does not.
Two keys are obsolete, and the documentation says so outright: the
standard-prototype Self::LabViewStdPrototype and Self::CviStdPrototype are to be
replaced by Self::LabView and Self::Cvi. They are kept here
because engines back to 2016 accept them and old sequence files contain
them, but a step built with one reports back its replacement, so a
comparison of “asked for” against “got” differs for exactly those two, by
design rather than by accident. Self::is_obsolete and
Self::replacement make that checkable instead of folklore.
Variants (Non-exhaustive)§
This enum is marked as non-exhaustive
NoneAdapter
No code module, the step type does its own work
(NoneAdapterKeyName).
LabView
The LabVIEW adapter (FlexLVAdapterKeyName, value
“G Flexible VI Adapter”). This is what the editor calls the LabVIEW
Adapter today, and the one to reach for.
LabViewStdPrototype
The superseded standard-prototype LabVIEW adapter. Obsolete, the
documentation directs callers to Self::LabView, and the engine
substitutes it. The type library carries this one key under two names,
LVAdapterKeyName and GAdapterKeyName, so the crate names it once.
LabViewNxg
LabVIEW NXG (LabVIEWNXGAdapterKeyName), its own key for the
discontinued second-generation product, not a spelling of the above.
Cvi
A C/CVI function with any prototype (FlexCVIAdapterKeyName).
CviStdPrototype
A C/CVI function with the standard prototype. Obsolete, the
documentation directs callers to Self::Cvi
(StdCVIAdapterKeyName).
DllFlex
A DLL function with any prototype (FlexCAdapterKeyName).
Sequence
Another sequence (SequenceAdapterKeyName).
Automation
An ActiveX automation server (AutomationAdapterKeyName).
DotNet
A .NET assembly member (DotNetAdapterKeyname).
Python
A Python module (PythonAdapterKeyName).
HtBasic
HTBasic (HTBasicAdapterKeyName).
Implementations§
Source§impl AdapterKeyName
impl AdapterKeyName
Sourcepub const fn as_str(self) -> &'static str
pub const fn as_str(self) -> &'static str
The key the engine expects.
Examples found in repository?
36fn add_pass_fail(
37 engine: &Engine,
38 sequence: &Sequence,
39 name: &str,
40 source: &str,
41) -> Result<(), Error> {
42 let step = engine.new_step(AdapterKeyName::NoneAdapter.as_str(), "PassFailTest")?;
43 step.set_name(name)?;
44 step.as_property_object()?
45 .set_val_string("DataSource", insert_if_missing(), source)?;
46 sequence.insert_step(
47 &step,
48 sequence.get_num_steps(StepGroup::Main)?,
49 StepGroup::Main,
50 )
51}
52
53/// Adds a numeric limit test with a fixed measurement.
54fn add_numeric(
55 engine: &Engine,
56 sequence: &Sequence,
57 name: &str,
58 source: &str,
59 low: f64,
60 high: f64,
61) -> Result<(), Error> {
62 let step = engine.new_step(AdapterKeyName::NoneAdapter.as_str(), "NumericLimitTest")?;
63 step.set_name(name)?;
64 let properties = step.as_property_object()?;
65 properties.set_val_string("DataSource", insert_if_missing(), source)?;
66 properties.set_val_number("Limits.Low", insert_if_missing(), low)?;
67 properties.set_val_number("Limits.High", insert_if_missing(), high)?;
68 sequence.insert_step(
69 &step,
70 sequence.get_num_steps(StepGroup::Main)?,
71 StepGroup::Main,
72 )
73}
74
75/// Adds a statement step that records nothing, to show the gap it leaves.
76fn add_unrecorded_filler(engine: &Engine, sequence: &Sequence, name: &str) -> Result<(), Error> {
77 let step = engine.new_step(AdapterKeyName::NoneAdapter.as_str(), "Statement")?;
78 step.set_name(name)?;
79 step.set_result_recording_option(ResultRecordingOption::Disabled)?;
80 sequence.insert_step(
81 &step,
82 sequence.get_num_steps(StepGroup::Main)?,
83 StepGroup::Main,
84 )
85}More examples
51fn build_prototype(engine: &Engine) -> Result<Step, Error> {
52 // The maintained LabVIEW adapter. The standard-prototype key still exists
53 // but the documentation marks it obsolete in favour of this one.
54 let step = engine.new_step(AdapterKeyName::LabView.as_str(), "Action")?;
55 step.set_name("Measure (VI)")?;
56 step.set_run_mode(RunMode::Normal)?;
57 step.as_property_object()?.set_val_string(
58 VI_PATH,
59 PropertyOptions::INSERT_IF_MISSING.bits(),
60 r"example.lvlibp\measure.vi",
61 )?;
62 Ok(step)
63}44fn add_action(engine: &Engine, sequence: &Sequence, name: &str) -> Result<(), Error> {
45 // The None adapter is what actually means "no code module"; an empty key
46 // would let the step type pick, and a step on a real adapter fails at run
47 // time with "module has not yet been specified".
48 let step = engine.new_step(AdapterKeyName::NoneAdapter.as_str(), "Action")?;
49 step.set_name(name)?;
50 step.set_record_result(true)?;
51 sequence.insert_step(
52 &step,
53 sequence.get_num_steps(StepGroup::Main)?,
54 StepGroup::Main,
55 )
56}62fn add_numeric_limit_test(
63 engine: &Engine,
64 sequence: &Sequence,
65 name: &str,
66 data_source: &str,
67 low: f64,
68 high: f64,
69) -> Result<(), Error> {
70 let step = engine.new_step(AdapterKeyName::NoneAdapter.as_str(), "NumericLimitTest")?;
71 step.set_name(name)?;
72 step.set_record_result(true)?;
73
74 let properties = step.as_property_object()?;
75 properties.set_val_string("DataSource", insert_if_missing(), data_source)?;
76 properties.set_val_number("Limits.Low", insert_if_missing(), low)?;
77 properties.set_val_number("Limits.High", insert_if_missing(), high)?;
78
79 sequence.insert_step(
80 &step,
81 sequence.get_num_steps(StepGroup::Main)?,
82 StepGroup::Main,
83 )
84}37fn vi_call_step(
38 engine: &Engine,
39 name: &str,
40 vi_path: &str,
41 project_path: &str,
42 run_mode: RunMode,
43) -> Result<Step, Error> {
44 let step = engine.new_step(AdapterKeyName::LabView.as_str(), "Action")?;
45 step.set_name(name)?;
46 step.set_run_mode(run_mode)?;
47 // Recorded explicitly rather than left to the default, so the step shows up
48 // in the result list a report is built from.
49 step.set_result_recording_option(ResultRecordingOption::Enabled)?;
50
51 let properties = step.as_property_object()?;
52 properties.set_val_string(VI_PATH, insert_if_missing(), vi_path)?;
53 if !project_path.is_empty() {
54 properties.set_val_string(PROJECT_PATH, insert_if_missing(), project_path)?;
55 }
56 Ok(step)
57}
58
59/// The index of a step within a group, by name.
60///
61/// `None` when no step of that name is in the group, which a caller should
62/// treat as "append at the end" rather than as a failure: a sequence is free
63/// not to contain the step someone expected.
64fn index_of(sequence: &Sequence, name: &str, group: StepGroup) -> Result<Option<i32>, Error> {
65 for index in 0..sequence.get_num_steps(group)? {
66 if sequence.get_step(index, group)?.name()? == name {
67 return Ok(Some(index));
68 }
69 }
70 Ok(None)
71}
72
73fn main() -> Result<(), Box<dyn std::error::Error>> {
74 let engine = Engine::new()?;
75
76 // A file to insert into. Built here so the example depends on nothing that
77 // has to exist on the station first.
78 let sequence_file = engine.new_sequence_file()?;
79 let subsequence = engine.new_sequence()?;
80 subsequence.set_name("CustomSubsequence")?;
81 let existing = engine.new_step(AdapterKeyName::NoneAdapter.as_str(), "Action")?;
82 existing.set_name(TARGET_STEP)?;
83 subsequence.insert_step(&existing, 0, StepGroup::Main)?;
84 sequence_file.insert_sequence(&subsequence)?;
85
86 // Where to insert: in front of the target, or at the end if it is absent.
87 let insert_at = if let Some(index) = index_of(&subsequence, TARGET_STEP, StepGroup::Main)? {
88 println!("Found {TARGET_STEP} at index {index}; inserting in front of it.");
89 index
90 } else {
91 let end = subsequence.get_num_steps(StepGroup::Main)?;
92 println!("{TARGET_STEP} not found; appending at index {end}.");
93 end
94 };
95
96 for (offset, (name, vi, project, mode)) in [
97 (
98 "Measure Voltage (VI)",
99 r"instruments.lvlibp\measure_voltage.vi",
100 "",
101 RunMode::Normal,
102 ),
103 (
104 "Measure Current (VI)",
105 r"instruments.lvlibp\measure_current.vi",
106 r"instruments.lvproj",
107 RunMode::Skip,
108 ),
109 ]
110 .into_iter()
111 .enumerate()
112 {
113 let step = vi_call_step(&engine, name, vi, project, mode)?;
114 let at = insert_at + i32::try_from(offset).unwrap_or(0);
115 subsequence.insert_step(&step, at, StepGroup::Main)?;
116 }
117
118 println!(
119 "\n{} now holds {} step(s):",
120 subsequence.name()?,
121 subsequence.get_num_steps(StepGroup::Main)?
122 );
123 for index in 0..subsequence.get_num_steps(StepGroup::Main)? {
124 let step = subsequence.get_step(index, StepGroup::Main)?;
125 let properties = step.as_property_object()?;
126 let vi = properties
127 .get_val_string(VI_PATH, none())
128 .unwrap_or_else(|_| "<no VI>".to_owned());
129 println!(
130 " [{index}] {} - {:?}, run mode {:?}, records {:?}",
131 step.name()?,
132 step.adapter_key_name()?,
133 step.run_mode()?,
134 step.result_recording_option()?
135 );
136 if vi != "<no VI>" {
137 println!(" calls {vi}");
138 }
139 }
140
141 let path = std::env::temp_dir().join("rs_teststand_step_insert.seq");
142 let path = path.to_string_lossy().into_owned();
143 sequence_file.save(&path)?;
144 println!("\nSaved to {path}");
145 Ok(())
146}Sourcepub fn from_key(key: &str) -> Option<Self>
pub fn from_key(key: &str) -> Option<Self>
Recognizes a key read back from a step.
None means the key is not one this build names, a newer engine’s
adapter, or a step that has none, which is information, not an error.
Sourcepub const fn is_obsolete(self) -> bool
pub const fn is_obsolete(self) -> bool
Whether the documentation marks this key obsolete.
An obsolete key still works, engines back to 2016 accept it, and old
sequence files are full of them, but a step built with one reports
replacement back instead.
Sourcepub const fn replacement(self) -> Option<Self>
pub const fn replacement(self) -> Option<Self>
The key the documentation directs callers to instead, if any.
Trait Implementations§
Source§impl Clone for AdapterKeyName
impl Clone for AdapterKeyName
Source§fn clone(&self) -> AdapterKeyName
fn clone(&self) -> AdapterKeyName
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more