-
Notifications
You must be signed in to change notification settings - Fork 318
Add sensor-config commands (guidance needed) #903
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1085,6 +1085,11 @@ def setSimpleConfig(modem_preset): | |
| print(f"Waiting {args.wait_to_disconnect} seconds before disconnecting") | ||
| time.sleep(int(args.wait_to_disconnect)) | ||
|
|
||
| if args.sensor_config: | ||
| closeNow = True | ||
| waitForAckNak = True | ||
| interface.getNode(args.dest, False, **getNode_kwargs).sensorConfig(args.sensor_config) | ||
|
|
||
| # if the user didn't ask for serial debugging output, we might want to exit after we've done our operation | ||
| if (not args.seriallog) and closeNow: | ||
| interface.close() # after running command then exit | ||
|
|
@@ -1983,6 +1988,14 @@ def addRemoteAdminArgs(parser: argparse.ArgumentParser) -> argparse.ArgumentPars | |
| metavar="TIMESTAMP", | ||
| ) | ||
|
|
||
| group.add_argument( | ||
| "--sensor-config", | ||
| help="Send a sensor admin command to configure sensor parameters.", | ||
| action="store", | ||
| nargs='+', | ||
| default=None | ||
| ) | ||
|
Comment on lines
+1991
to
+1997
|
||
|
|
||
| return parser | ||
|
|
||
| def initParser(): | ||
|
|
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -977,6 +977,102 @@ def onAckNak(self, p): | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| print(f"Received an ACK.") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.iface._acknowledgment.receivedAck = True | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def sensorConfig(self, commands: List = None): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """Send a sensor configuration command""" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.ensureSessionKey() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
| if not commands: | |
| print("No sensor configuration commands were provided.") | |
| return |
Copilot
AI
Mar 6, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This method prints user-facing status/errors directly. In node.py, other admin actions typically use logger.info()/warning() (e.g. reboot() / shutdown()), which is easier to test and integrates with library consumers. Consider switching these print() calls to logging (and letting the CLI decide what to print) to keep Node usable as a library API.
Copilot
AI
Mar 6, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
send_command is assigned but never read. This is dead code and may trigger linting failures; either remove it or use it to control the “Nothing to request”/sending behavior consistently across all sensor config fields.
Copilot
AI
Mar 6, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Several options read their value via cleanup_commands[cleanup_commands.index(name) + 1] without checking that a following token exists. If a user passes an option as the last argument (e.g. scd4x_config.set_asc with no value), this will raise IndexError and crash the CLI. Please validate that the option has a value (and ideally that the value token isn’t another *_config.* key) before indexing.
| if 'factory_reset' in cleanup_commands: | |
| print ("Performing factory reset on SCD4X") | |
| p.sensor_config.scd4x_config.factory_reset = True | |
| else: | |
| if 'set_asc' in cleanup_commands: | |
| if cleanup_commands[cleanup_commands.index('set_asc')+1] == "true": | |
| p.sensor_config.scd4x_config.set_asc = True | |
| print ("Setting SCD4X ASC mode") | |
| elif cleanup_commands[cleanup_commands.index('set_asc')+1] == "false": | |
| p.sensor_config.scd4x_config.set_asc = False | |
| print ("Setting SCD4X FRC mode") | |
| else: | |
| print( | |
| f'Not valid argument for sensor_config.scd4x_config.set_asc' | |
| ) | |
| if 'set_target_co2_conc' in cleanup_commands: | |
| try: | |
| target_co2_conc = int(cleanup_commands[cleanup_commands.index('set_target_co2_conc')+1]) | |
| except ValueError: | |
| print( | |
| f'Invalid value for target CO2 conc' | |
| ) | |
| return | |
| else: | |
| print (f"Setting SCD4X target CO2 conc to {target_co2_conc}") | |
| p.sensor_config.scd4x_config.set_target_co2_conc = target_co2_conc | |
| send_command = True | |
| if 'set_temperature' in cleanup_commands: | |
| try: | |
| temperature = float(cleanup_commands[cleanup_commands.index('set_temperature')+1]) | |
| except ValueError: | |
| print( | |
| f'Invalid value for reference temperature' | |
| ) | |
| return | |
| else: | |
| print (f"Setting SCD4X Reference temperature to {temperature}") | |
| p.sensor_config.scd4x_config.set_temperature = temperature | |
| send_command = True | |
| if 'set_altitude' in cleanup_commands: | |
| try: | |
| altitude = int(cleanup_commands[cleanup_commands.index('set_altitude')+1]) | |
| except ValueError: | |
| print( | |
| f'Invalid value for reference altitude' | |
| ) | |
| return | |
| else: | |
| print (f"Setting SCD4X Reference altitude to {altitude}") | |
| p.sensor_config.scd4x_config.set_altitude = altitude | |
| if 'set_ambient_pressure' in cleanup_commands: | |
| try: | |
| ambient_pressure = int(cleanup_commands[cleanup_commands.index('set_ambient_pressure')+1]) | |
| except ValueError: | |
| print( | |
| f'Invalid value for reference ambient pressure' | |
| ) | |
| return | |
| else: | |
| print (f"Setting SCD4X Reference ambient pressure to {ambient_pressure}") | |
| def _get_scd4x_option_value(option_name: str) -> Optional[str]: | |
| """ | |
| Safely get the value token that follows an SCD4X option name | |
| in cleanup_commands. Returns None if no valid value is found. | |
| """ | |
| try: | |
| idx = cleanup_commands.index(option_name) | |
| except ValueError: | |
| return None | |
| value_index = idx + 1 | |
| if value_index >= len(cleanup_commands): | |
| print(f"Missing value for sensor_config.scd4x_config.{option_name}") | |
| return None | |
| value_token = cleanup_commands[value_index] | |
| # Treat any other known SCD4X option name as not being a valid value | |
| scd4x_option_names = { | |
| 'factory_reset', | |
| 'set_asc', | |
| 'set_target_co2_conc', | |
| 'set_temperature', | |
| 'set_altitude', | |
| 'set_ambient_pressure', | |
| } | |
| if value_token in scd4x_option_names: | |
| print(f"Missing value for sensor_config.scd4x_config.{option_name}") | |
| return None | |
| return value_token | |
| if 'factory_reset' in cleanup_commands: | |
| print("Performing factory reset on SCD4X") | |
| p.sensor_config.scd4x_config.factory_reset = True | |
| else: | |
| if 'set_asc' in cleanup_commands: | |
| asc_value = _get_scd4x_option_value('set_asc') | |
| if asc_value == "true": | |
| p.sensor_config.scd4x_config.set_asc = True | |
| print("Setting SCD4X ASC mode") | |
| elif asc_value == "false": | |
| p.sensor_config.scd4x_config.set_asc = False | |
| print("Setting SCD4X FRC mode") | |
| elif asc_value is not None: | |
| print( | |
| f'Not valid argument for sensor_config.scd4x_config.set_asc' | |
| ) | |
| if 'set_target_co2_conc' in cleanup_commands: | |
| value = _get_scd4x_option_value('set_target_co2_conc') | |
| if value is None: | |
| return | |
| try: | |
| target_co2_conc = int(value) | |
| except ValueError: | |
| print( | |
| f'Invalid value for target CO2 conc' | |
| ) | |
| return | |
| else: | |
| print(f"Setting SCD4X target CO2 conc to {target_co2_conc}") | |
| p.sensor_config.scd4x_config.set_target_co2_conc = target_co2_conc | |
| send_command = True | |
| if 'set_temperature' in cleanup_commands: | |
| value = _get_scd4x_option_value('set_temperature') | |
| if value is None: | |
| return | |
| try: | |
| temperature = float(value) | |
| except ValueError: | |
| print( | |
| f'Invalid value for reference temperature' | |
| ) | |
| return | |
| else: | |
| print(f"Setting SCD4X Reference temperature to {temperature}") | |
| p.sensor_config.scd4x_config.set_temperature = temperature | |
| send_command = True | |
| if 'set_altitude' in cleanup_commands: | |
| value = _get_scd4x_option_value('set_altitude') | |
| if value is None: | |
| return | |
| try: | |
| altitude = int(value) | |
| except ValueError: | |
| print( | |
| f'Invalid value for reference altitude' | |
| ) | |
| return | |
| else: | |
| print(f"Setting SCD4X Reference altitude to {altitude}") | |
| p.sensor_config.scd4x_config.set_altitude = altitude | |
| if 'set_ambient_pressure' in cleanup_commands: | |
| value = _get_scd4x_option_value('set_ambient_pressure') | |
| if value is None: | |
| return | |
| try: | |
| ambient_pressure = int(value) | |
| except ValueError: | |
| print( | |
| f'Invalid value for reference ambient pressure' | |
| ) | |
| return | |
| else: | |
| print(f"Setting SCD4X Reference ambient pressure to {ambient_pressure}") |
Copilot
AI
Mar 6, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
New parsing/sending behavior in sensorConfig() isn’t covered by unit tests. The repo already has meshtastic/tests/test_node.py exercising other admin methods (e.g. reboot(), shutdown()). Please add tests that validate: (1) valid tokens set the expected protobuf fields, and (2) invalid/missing values are handled without raising (especially the IndexError cases).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
--sensor-configis executed after the global ACK/NAK wait block, but it setswaitForAckNak = Trueonly inside this late block. As a result, remote--sensor-configcommands won’t trigger the “Waiting for an acknowledgment…” path and the interface may close immediately after sending. Please move this handling up with the other remote-admin actions (before the ACK/NAK wait section), or explicitly calliface.waitForAckNak()right aftersensorConfig()when--destis remote.