Skip to content

Commit f8990e5

Browse files
committed
Optional Client_Side Text Message Logging
1 parent be36666 commit f8990e5

3 files changed

Lines changed: 552 additions & 1 deletion

File tree

‎meshtastic/__main__.py‎

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@
6666
from meshtastic.protobuf import admin_pb2, channel_pb2, clientonly_pb2, config_pb2, portnums_pb2, mesh_pb2
6767
from meshtastic.version import get_active_version
6868

69+
from meshtastic.message_store import MessageSettings, MessageStore, MessageLog, print_messages
70+
6971
logger = logging.getLogger(__name__)
7072

7173
# Map dotted preference paths to the protobuf enum that defines their flags.
@@ -600,6 +602,14 @@ def onConnected(interface):
600602
onResponse=interface.getNode(args.dest, False, **getNode_kwargs).onAckNak,
601603
portNum=portnums_pb2.PortNum.PRIVATE_APP if args.private else portnums_pb2.PortNum.TEXT_MESSAGE_APP
602604
)
605+
606+
#Save Outbound Messages -- if save enabled
607+
if mt_config.message_store:
608+
mt_config.message_store.log_sent(
609+
args.sendtext,
610+
destination_id=args.dest,
611+
channel=channelIndex,
612+
)
603613
else:
604614
meshtastic.util.our_exit(
605615
f"Warning: {channelIndex} is not a valid channel. Channel must not be DISABLED."
@@ -1642,6 +1652,18 @@ def common():
16421652
mt_config.logfile = logfile
16431653

16441654
subscribe()
1655+
1656+
# (after the early arg checks, before any interface is constructed)
1657+
# Enable? StoreMessages? Call to get bool --> True (Save)
1658+
message_store = None
1659+
if handleMessageStoreArgs(args):
1660+
message_store = MessageStore(MessageLog())
1661+
mt_config.message_store = message_store # so onConnected can reach it
1662+
1663+
#Display Messages
1664+
if handleShowMessagesArgs(args):
1665+
return
1666+
16451667
if args.ble_scan:
16461668
logger.debug("BLE scan starting")
16471669
for x in BLEInterface.scan():
@@ -1806,6 +1828,70 @@ def common():
18061828
# don't call exit, background threads might be running still
18071829
# sys.exit(0)
18081830

1831+
def handleMessageStoreArgs(args) -> bool:
1832+
"""Resolve whether message logging is enabled for this run.
1833+
1834+
Reads --messages, updates the saved setting for on/off, and returns
1835+
the effective logging state. Does not attach hooks or exit.
1836+
"""
1837+
1838+
args = mt_config.args
1839+
mode = args.messages
1840+
1841+
store = MessageSettings()
1842+
1843+
# No flag: use the saved setting (defaults to off if missing/corrupt)
1844+
if mode is None:
1845+
return store.is_enabled()
1846+
1847+
if mode == "on":
1848+
store.set_enabled(True) # persist
1849+
return True
1850+
1851+
if mode == "off":
1852+
store.set_enabled(False) # persist
1853+
return False
1854+
1855+
if mode == "live":
1856+
# Log for this run only; saved setting is untouched
1857+
return True
1858+
1859+
if mode == "status":
1860+
saved = store.is_enabled()
1861+
print(f"Message logging is {'ON' if saved else 'OFF'}")
1862+
return saved
1863+
1864+
return False # unreachable with argparse choices, but safe
1865+
1866+
def handleShowMessagesArgs(args) -> bool:
1867+
"""Handle --show-messages. Returns True if it did, so the caller can stop
1868+
before any store is created or any connection is attempted."""
1869+
1870+
args = mt_config.args
1871+
parser = mt_config.parser
1872+
1873+
mode = getattr(args, "show_messages", None)
1874+
#
1875+
if mode is None:
1876+
return False
1877+
1878+
# Local-only command: refuse anything else that was actually set.
1879+
# Compare each arg to its parser default so unset flags don't count.
1880+
allowed = {"show_messages", "dest"} #Exclude dest -- which is set @BRDCST_ADDR
1881+
others = [
1882+
"--" + name.replace("_", "-")
1883+
for name, value in vars(args).items()
1884+
if name not in allowed and value != parser.get_default(name)
1885+
]
1886+
if others:
1887+
meshtastic.util.our_exit(
1888+
"Error: --show-messages can't be combined with: " + ", ".join(sorted(others)), 1
1889+
)
1890+
1891+
if mode == "all":
1892+
print_messages()
1893+
return True
1894+
18091895

18101896
def addConnectionArgs(parser: argparse.ArgumentParser) -> argparse.ArgumentParser:
18111897
"""Add connection specification arguments"""
@@ -2396,6 +2482,43 @@ def addRemoteAdminArgs(parser: argparse.ArgumentParser) -> argparse.ArgumentPars
23962482

23972483
return parser
23982484

2485+
2486+
def addMessageArgs(parser: argparse.ArgumentParser) -> argparse.ArgumentParser:
2487+
"""Add message logging / history arguments."""
2488+
group = parser.add_argument_group(
2489+
"Messages",
2490+
"Persistent text-message logging (client-side JSONL). "
2491+
)
2492+
2493+
group.add_argument(
2494+
"--messages",
2495+
nargs="?",
2496+
const="status",
2497+
default=None,
2498+
choices=["on", "off", "status", "live"],
2499+
metavar="on|off|status|live",
2500+
help=(
2501+
"on/off: enable or disable message logging (saved) (default off). "
2502+
"status: show whether logging is on/off. "
2503+
"live: log messages for this run only, without changing the saved "
2504+
"setting. Combine with --listen or other commands."
2505+
)
2506+
)
2507+
2508+
group.add_argument(
2509+
"--show-messages",
2510+
nargs="?",
2511+
const="all",
2512+
default=None,
2513+
choices=["all"],
2514+
help=(
2515+
"Print stored messages. Currently supports: all."
2516+
)
2517+
)
2518+
2519+
return parser
2520+
2521+
23992522
def initParser():
24002523
"""Initialize the command line argument parsing."""
24012524
parser = mt_config.parser
@@ -2436,6 +2559,9 @@ def initParser():
24362559
parser = addRemoteActionArgs(parser)
24372560
parser = addRemoteAdminArgs(parser)
24382561

2562+
#Arguments for Message Parsing
2563+
parser = addMessageArgs(parser)
2564+
24392565
# All the rest of the arguments
24402566
group = parser.add_argument_group("Miscellaneous arguments")
24412567

0 commit comments

Comments
 (0)