Skip to content
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

A lot of fixes around setting / retrieving base64 encoded values #701

Merged
merged 7 commits into from
Oct 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 37 additions & 39 deletions meshtastic/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,13 +87,22 @@ def checkChannel(interface: MeshInterface, channelIndex: int) -> bool:

def getPref(node, comp_name):
"""Get a channel or preferences value"""
def _printSetting(config_type, uni_name, pref_value, repeated):
"""Pretty print the setting"""
if repeated:
pref_value = [meshtastic.util.toStr(v) for v in pref_value]
else:
pref_value = meshtastic.util.toStr(pref_value)
print(f"{str(config_type.name)}.{uni_name}: {str(pref_value)}")
logging.debug(f"{str(config_type.name)}.{uni_name}: {str(pref_value)}")

name = splitCompoundName(comp_name)
wholeField = name[0] == name[1] # We want the whole field

camel_name = meshtastic.util.snake_to_camel(name[1])
# Note: protobufs has the keys in snake_case, so snake internally
snake_name = meshtastic.util.camel_to_snake(name[1])
uni_name = camel_name if mt_config.camel_case else snake_name
logging.debug(f"snake_name:{snake_name} camel_name:{camel_name}")
logging.debug(f"use camel:{mt_config.camel_case}")

Expand All @@ -112,14 +121,9 @@ def getPref(node, comp_name):
break

if not found:
if mt_config.camel_case:
print(
f"{localConfig.__class__.__name__} and {moduleConfig.__class__.__name__} do not have an attribute {snake_name}."
)
else:
print(
f"{localConfig.__class__.__name__} and {moduleConfig.__class__.__name__} do not have attribute {snake_name}."
)
print(
f"{localConfig.__class__.__name__} and {moduleConfig.__class__.__name__} do not have attribute {uni_name}."
)
print("Choices are...")
printConfig(localConfig)
printConfig(moduleConfig)
Expand All @@ -131,19 +135,12 @@ def getPref(node, comp_name):
config_values = getattr(config, config_type.name)
if not wholeField:
pref_value = getattr(config_values, pref.name)
if mt_config.camel_case:
print(f"{str(config_type.name)}.{camel_name}: {str(pref_value)}")
logging.debug(
f"{str(config_type.name)}.{camel_name}: {str(pref_value)}"
)
else:
print(f"{str(config_type.name)}.{snake_name}: {str(pref_value)}")
logging.debug(
f"{str(config_type.name)}.{snake_name}: {str(pref_value)}"
)
repeated = pref.label == pref.LABEL_REPEATED
_printSetting(config_type, uni_name, pref_value, repeated)
else:
print(f"{str(config_type.name)}:\n{str(config_values)}")
logging.debug(f"{str(config_type.name)}: {str(config_values)}")
for field in config_values.ListFields():
repeated = field[0].label == field[0].LABEL_REPEATED
_printSetting(config_type, field[0].name, field[1], repeated)
else:
# Always show whole field for remote node
node.requestConfig(config_type)
Expand All @@ -168,18 +165,19 @@ def traverseConfig(config_root, config, interface_config):
if isinstance(config[pref], dict):
traverseConfig(pref_name, config[pref], interface_config)
else:
setPref(interface_config, pref_name, str(config[pref]))
setPref(interface_config, pref_name, config[pref])

return True


def setPref(config, comp_name, valStr) -> bool:
def setPref(config, comp_name, raw_val) -> bool:
"""Set a channel or preferences value"""

name = splitCompoundName(comp_name)

snake_name = meshtastic.util.camel_to_snake(name[-1])
camel_name = meshtastic.util.snake_to_camel(name[-1])
uni_name = camel_name if mt_config.camel_case else snake_name
logging.debug(f"snake_name:{snake_name}")
logging.debug(f"camel_name:{camel_name}")

Expand All @@ -201,10 +199,13 @@ def setPref(config, comp_name, valStr) -> bool:
if (not pref) or (not config_type):
return False

val = meshtastic.util.fromStr(valStr)
logging.debug(f"valStr:{valStr} val:{val}")
if isinstance(raw_val, str):
val = meshtastic.util.fromStr(raw_val)
else:
val = raw_val
logging.debug(f"valStr:{raw_val} val:{val}")

if snake_name == "wifi_psk" and len(valStr) < 8:
if snake_name == "wifi_psk" and len(str(raw_val)) < 8:
print(f"Warning: network.wifi_psk must be 8 or more characters.")
return False

Expand All @@ -216,14 +217,9 @@ def setPref(config, comp_name, valStr) -> bool:
if e:
val = e.number
else:
if mt_config.camel_case:
print(
f"{name[0]}.{camel_name} does not have an enum called {val}, so you can not set it."
)
else:
print(
f"{name[0]}.{snake_name} does not have an enum called {val}, so you can not set it."
)
print(
f"{name[0]}.{uni_name} does not have an enum called {val}, so you can not set it."
)
print(f"Choices in sorted order are:")
names = []
for f in enumType.values:
Expand All @@ -244,24 +240,26 @@ def setPref(config, comp_name, valStr) -> bool:
except TypeError:
# The setter didn't like our arg type guess try again as a string
config_values = getattr(config_part, config_type.name)
setattr(config_values, pref.name, valStr)
setattr(config_values, pref.name, str(val))
elif type(val) == list:
new_vals = [meshtastic.util.fromStr(x) for x in val]
config_values = getattr(config, config_type.name)
getattr(config_values, pref.name)[:] = new_vals
else:
config_values = getattr(config, config_type.name)
if val == 0:
# clear values
print(f"Clearing {pref.name} list")
del getattr(config_values, pref.name)[:]
else:
print(f"Adding '{val}' to the {pref.name} list")
print(f"Adding '{raw_val}' to the {pref.name} list")
cur_vals = [x for x in getattr(config_values, pref.name) if x not in [0, "", b""]]
cur_vals.append(val)
getattr(config_values, pref.name)[:] = cur_vals
return True

prefix = f"{'.'.join(name[0:-1])}." if config_type.message_type is not None else ""
if mt_config.camel_case:
print(f"Set {prefix}{camel_name} to {valStr}")
else:
print(f"Set {prefix}{snake_name} to {valStr}")
print(f"Set {prefix}{uni_name} to {raw_val}")

return True

Expand Down
7 changes: 7 additions & 0 deletions meshtastic/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,13 @@ def fromStr(valstr):
return val


def toStr(raw_value):
"""Convert a value to a string that can be used in a config file"""
if isinstance(raw_value, bytes):
return "base64:" + base64.b64encode(raw_value).decode("utf-8")
return str(raw_value)


def pskToString(psk: bytes):
"""Given an array of PSK bytes, decode them into a human readable (but privacy protecting) string"""
if len(psk) == 0:
Expand Down
Loading