betaflight-configurator
betaflight-configurator copied to clipboard
Allow Preset Options to be conditional on Betaflight variables
Is your feature request related to a problem? Please describe
There is currently no way for one preset to affect another, or for an optional portion of a preset to affect a later portion.
Communicating Between Presets
Several presets require that the same information be entered in their configuration. This is error prone and complicates setup. For instance some presets setup a different configuration if DShot is enabled or not. If the user supplies the wrong information about the state of DShot on the drone then the preset will not be applied properly.
Likewise, if a preset includes another preset it's complicated to pass parameters from the first preset to the second. (I believe that there is a way to do this, but haven't figured out the syntax yet :-). If the first preset sets a variable it's very easy for the included preset to read it. This allows the included preset to be used as an include or on its own.
Communication Within A Preset
A single preset can also specify multiple options, but there is no (easy) way to combine these options. For example if I have a preset that optionally sets up a Crossfire receiver and that also optionally sets up failsafe options, I only want to set the Crossfire RSSI channel to hold on failsafe if I'm also setting up failsafe, since it's a failsafe option that is affected by my receiver type.
Describe the solution you'd like
Define a new 'OPTION' type: #$ VARIABLE_OPTION BEGIN: <variableName> <operator> <value>. Instead of creating a checkbox for the user to select, the option would be evaluated by comparing the value of an existing variable to the preset.
For example, the following will setup a GPS OSD if the GPS feature has been enabled elsewhere in this preset, in another preset, or manually by the user.
#$ VARIABLE_OPTION BEGIN: feature CONTAINS GPS
set osd_gps_speed_pos = 2105
# ... more variables
#$ VARIABLE_OPTION END
This will turn on per cell voltage reporting if the radio protocol is Crossfire since Crossfire telemetry doesn't have an option to report the cell voltage the way FrSky does.
#$ VARIABLE_OPTION BEGIN: serialrx_provider == CRSF
set report_cell_voltage = ON
#$ VARIABLE_OPTION END
Operators may include:
- == Checks to see if the variable has the specified value. Implementation of all other operators is optional, but this one would be required for almost all functionality.
- != Checks to see if the variable does not have the specified value.
- > Checks to see if a numeric variable is greater than a value.
- < Checks to see if a numeric variable is less than a value.
- CONTAINS Checks to see if the variable contains a substring. (This is mainly useful for testing for enabled features).
- !CONTAINS The opposite of CONTAINS
Challenges
The biggest risk I see with this is that presets would need to be applied in order. For example, I have a personal preset that just does all of the setup I normally do on a quad, like enabling DSHOT, etc. If a tune preset was run after this preset it would pick up the DSHOT setting, but if it were run before it would not.
Presets could have an order enforced based on their category, or a dependency system could be run to detect presets that were testing variables that were modified by other presets and warn if things were set out of order. But both of those have limitations.
A simpler solution would be to show all of the variable options to the user just like the regular options, but make the variable value the default. This would make the user aware of the dependency, and allow them to override the variable preset when needed. It would get more complicated with includes and when the same variable is checked multiple times.
Describe alternatives you've considered
Initially I thought of defining local or global variables.
Local variables are defined for the duration of executing the preset (or all selected presets). The preset could set a local value when a user OPTION was detected, and then check the local later to allow multiple user OPTIONS to be combined.
Global variables would be like local variables, but they would be saved at the end of applying the preset, so that they could be queried in the future. This would allow one preset to communicate with another, as well as give the preset a place to store its name and options for future reference. The real downside of this approach is that storage for these extra variables would be required and would not be limited, so they could grow indefinitely. I can't imagine this being easy to implement. It would also require defining a new namespace for these variables to allow different presets to communicate.
Using the existing CLI variables is essentially treating them as globals, but no new variables need to be implemented, the namespace is already well defined, and it solves more problems since it can handle setup done outside of the preset system.
Another limited solution would be to store the state of all user options and allow them all to be queried later on in other option blocks. This still doesn't solve as many problems as using the existing variables.
Another option would be to not implement conditionals as a preset option, but build it into the regular CLI syntax. That would enable it to be used in any CLI script. This would result in a simpler syntax which would be slightly more flexible, but may be more difficult to implement since it would have to be implemented in the CLI parser as opposed to the preset parser.
Other information
No response
I believe I've figured out how the current preset system handles options passed to included scripts (but I may be missing some details). In short, include files apply with all options deselected, unless you specify 'dummy' options in the preset that is including the child. The dummy option has the same definition as the option in the included preset, but it doesn't implement anything. Multiple included presets may reference the same 'dummy' option.
In a sense, this mechanism is similar to the local variables I considered above. It does solve some of the problems that this proposal does, but not all (I can now make a single preset that includes all of the presets that I use when setting up a quad now that I understand this mechanism). The dummy option system still has the following limitations:
- There is a namespace issue, since the preset options are not rigidly defined. It may be that you want to include a tune preset and a filter preset. If there was an option name that was used by the tune and the filter there is no way to specify that option for one include but not the other. This is also an issue when using the Betaflight parameters as conditional options, but at least there the meaning of each parameter is rigidly defined so there's no danger of a name collision.
- There's no way to hide an option. For example, my default setup preset 'assumes' that RPM filtering is enabled. When I import my tune preset, I need to specify that I want the RPM filtering version of it. This creates a selectable option in my 'umbrella' preset, but I don't want this option to be visible since it should always be selected. If the tune preset didn't have an option but just checked to see if DSHOT were enabled then there would be no need for a 'hidden' value. (Or course another way to solve this issue would be to have an option property that would set the option to be read only.)
- There's no way have a preset behave conditionally based on a value configured by the user without using a preset, or by a preset applied in an earlier configuration session. (For instance enabling DSHOT). Allowing a preset to check these values could simplify the existing presets as well as reducing their number.
- The option names don't have a short identifier (they're essentially UI labels), which makes them very easy to mistype. If a 'dummy' option doesn't exactly match the option name in an included preset then things will not behave as intended, and it can be difficult to realize this.
In light of my better understanding of 'dummy options' I can see that this request is less compelling, but it still does simplify the configuration process in some useful ways by using the existing well defined variables as opposed to the options that are at the mercy of preset authors. The decision on whether or not this is an interesting idea to pursue depends on how the preset system is shaped in the future. I can see several possible directions for presets, and I think this would be more useful in some than others.