Skip to content

Commit 25cd8d4

Browse files
joshannepeterbarker
authored andcommitted
modules: add bitmask modifying to param module
Adds ability to toggle, set and clear bitmask fields in parameters
1 parent 02d9f7e commit 25cd8d4

File tree

1 file changed

+111
-2
lines changed

1 file changed

+111
-2
lines changed

MAVProxy/modules/mavproxy_param.py

Lines changed: 111 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,112 @@ def param_watchlist(self, master, args):
383383
for pattern in self.watch_patterns:
384384
self.mpstate.console.writeln("> %s" % (pattern))
385385

386+
def param_bitmask_modify(self, master, args):
387+
'''command for performing bitmask actions on a parameter'''
388+
389+
BITMASK_ACTIONS = ['toggle', 'set', 'clear']
390+
391+
# Ensure we have at least an action and a parameter
392+
if len(args) < 2:
393+
print("Not enough arguments")
394+
print(f"param bitmask <{'/'.join(BITMASK_ACTIONS)}> <parameter> [bit-index]")
395+
return
396+
397+
action = args[0]
398+
if action not in BITMASK_ACTIONS:
399+
print(f"action must be one of: {', '.join(BITMASK_ACTIONS)}")
400+
return
401+
402+
# Grab the parameter argument, and check it exists
403+
param = args[1]
404+
if not param.upper() in self.mav_param:
405+
print(f"Unable to find parameter {param.upper()}")
406+
return
407+
uname = param.upper()
408+
409+
htree = self.param_help.param_help_tree()
410+
if htree is None:
411+
# No help tree is available
412+
print("Download parameters first")
413+
return
414+
415+
# Take the help tree and check if parameter is a bitmask
416+
phelp = htree[uname]
417+
bitmask_values = self.param_help.get_bitmask_from_help(phelp)
418+
if bitmask_values is None:
419+
print(f"Parameter {uname} is not a bitmask")
420+
return
421+
422+
# Find the type of the parameter
423+
ptype = None
424+
if uname in self.param_types:
425+
# Get the type of the parameter
426+
ptype = self.param_types[uname]
427+
428+
# Now grab the value for the parameter
429+
value = int(self.mav_param.get(uname))
430+
if value is None:
431+
print(f"Could not get a value for parameter {uname}")
432+
return
433+
434+
# The next argument is the bit_index - if it exists, handle it
435+
bit_index = None
436+
if len(args) >= 3:
437+
try:
438+
# If the bit index is available lets grab it
439+
arg_bit_index = args[2]
440+
# Try to convert it to int
441+
bit_index = int(arg_bit_index)
442+
except ValueError:
443+
print(f"Invalid bit index: {arg_bit_index}\n")
444+
445+
if bit_index is None:
446+
# No bit index was specified, but the parameter and action was.
447+
# Print the available bitmask information.
448+
print("%s: %s" % (uname, phelp.get('humanName')))
449+
s = "%-16.16s %s" % (uname, value)
450+
print(s)
451+
452+
# Generate the bitmask enabled list
453+
remaining_bits = value
454+
out_v = []
455+
if bitmask_values is not None and len(bitmask_values):
456+
for (n, v) in bitmask_values.items():
457+
if bit_index is None or bit_index == int(n):
458+
out_v.append(f"\t{int(n):3d} [{'x' if value & (1<<int(n)) else ' '}] : {v}")
459+
remaining_bits &= ~(1 << int(n))
460+
461+
# Loop bits 0 to 31, checking if they are remaining, and append
462+
for i in range(32):
463+
if (remaining_bits & (1 << i)) and ((bit_index is None) or (bit_index == i)):
464+
out_v.append(f"\t{i:3d} [{'x' if value & (1 << i) else ' '}] : Unknownbit{i}")
465+
466+
if out_v is not None and len(out_v) > 0:
467+
print("\nBitmask: ")
468+
print("\n".join(out_v))
469+
470+
# Finally, inform user of the error we experienced
471+
if bit_index is None:
472+
print("bit index is not specified")
473+
474+
# We don't have enough information to modify the bitmask, so bail
475+
return
476+
477+
# We have enough information to try perform an action
478+
if action == "toggle":
479+
value = value ^ (1 << bit_index)
480+
elif action == "set":
481+
value = value | (1 << bit_index)
482+
elif action == "clear":
483+
value = value & ~(1 << bit_index)
484+
else:
485+
# We cannot toggle, set or clear
486+
print("Invalid bitmask action")
487+
return
488+
489+
# Update the parameter
490+
self.mav_param.mavset(master, uname, value, retries=3, parm_type=ptype)
491+
386492
def param_revert(self, master, args):
387493
'''handle param revert'''
388494
defaults = self.default_params
@@ -417,7 +523,7 @@ def param_revert(self, master, args):
417523
def handle_command(self, master, mpstate, args):
418524
'''handle parameter commands'''
419525
param_wildcard = "*"
420-
usage="Usage: param <fetch|ftp|save|savechanged|revert|set|show|load|preload|forceload|ftpload|diff|download|check|help|watch|unwatch|watchlist>" # noqa
526+
usage="Usage: param <fetch|ftp|save|savechanged|revert|set|show|load|preload|forceload|ftpload|diff|download|check|help|watch|unwatch|watchlist|bitmask>" # noqa
421527
if len(args) < 1:
422528
print(usage)
423529
return
@@ -494,7 +600,8 @@ def handle_command(self, master, mpstate, args):
494600
# mpstate.module('rally').set_last_change(time.time())
495601
# need to redraw loiter points
496602
mpstate.module('wp').wploader.last_change = time.time()
497-
603+
elif args[0] == "bitmask":
604+
self.param_bitmask_modify(master, args[1:])
498605
elif args[0] == "load":
499606
if len(args) < 2:
500607
print("Usage: param load <filename> [wildcard]")
@@ -664,12 +771,14 @@ def __init__(self, mpstate, **kwargs):
664771
self.pstate = {}
665772
self.check_new_target_system()
666773
self.menu_added_console = False
774+
bitmask_indexes = "|".join(str(x) for x in range(32))
667775
self.add_command(
668776
'param', self.cmd_param, "parameter handling", [
669777
"<download|status>",
670778
"<set|show|fetch|ftp|help|apropos|revert> (PARAMETER)",
671779
"<load|save|savechanged|diff|forceload|ftpload> (FILENAME)",
672780
"<set_xml_filepath> (FILEPATH)",
781+
f"<bitmask> <toggle|set|clear> (PARAMETER) <{bitmask_indexes}>"
673782
],
674783
)
675784
if mp_util.has_wxpython:

0 commit comments

Comments
 (0)