Try Live
Add Docs
Rankings
Pricing
Enterprise
Docs
Install
Install
Docs
Pricing
Enterprise
More...
More...
Try Live
Rankings
Add Docs
Meshtastic C#
https://github.com/meshtastic/c-sharp
Admin
Meshtastic C# is a cross-platform .NET 8 command-line interface for interacting with Meshtastic mesh
...
Tokens:
7,568
Snippets:
51
Trust Score:
9.8
Update:
1 month ago
Context
Skills
Chat
Benchmark
78.5
Suggestions
Latest
Show doc for...
Code
Info
Show Results
Context Summary (auto-generated)
Raw
Copy
Link
# Meshtastic C# Meshtastic C# is a cross-platform .NET 8/.NET 9 library and command-line interface for communicating with Meshtastic mesh radio devices. It provides a comprehensive API for device discovery, connection management via serial, TCP, and Bluetooth, sending and receiving messages, configuring device settings, and managing mesh network operations. The library uses Protocol Buffers for message serialization and supports both programmatic API access and a feature-rich CLI tool. The project consists of two main components: the `Meshtastic` core library that handles device connections, message factories, and protocol handling, and `Meshtastic.Cli` that provides a complete command-line interface for device management. Key features include device auto-discovery across USB ports, multi-connection type support (Serial, TCP, Bluetooth), real-time live dashboard monitoring, MQTT proxy functionality, configuration import/export, and comprehensive settings management for both device configuration and module settings. ## Installation ### Install via NuGet (CLI Tool) ```bash # Install the CLI as a global dotnet tool dotnet tool install --global Meshtastic.Cli # Update to the latest version dotnet tool update Meshtastic.Cli -g ``` ### Install via NuGet (Library) ```bash # Add the library to your .NET project dotnet add package Meshtastic ``` ### Build from Source ```bash # Clone the repository git clone https://github.com/meshtastic/c-sharp.git cd c-sharp # Build all projects dotnet build # Run the CLI directly dotnet run --project ./Meshtastic.Cli/Meshtastic.Cli.csproj -- --help ``` ## Serial Connection The `SerialConnection` class provides communication with Meshtastic devices over USB serial ports. It handles packet framing, DTR handshaking, and async read/write operations with configurable baud rate (default 115200). ```csharp using Meshtastic.Connections; using Meshtastic.Data; using Meshtastic.Data.MessageFactories; using Meshtastic.Protobufs; using Microsoft.Extensions.Logging; // Create a logger using var loggerFactory = LoggerFactory.Create(builder => builder.AddConsole()); var logger = loggerFactory.CreateLogger<SerialConnection>(); // List available serial ports (filters out debug/Bluetooth ports) string[] availablePorts = SerialConnection.ListPorts(); Console.WriteLine($"Available ports: {string.Join(", ", availablePorts)}"); // Create serial connection on first available port var connection = new SerialConnection(logger, availablePorts[0]); // Request device configuration var toRadioFactory = new ToRadioMessageFactory(); var wantConfig = toRadioFactory.CreateWantConfigMessage(); // Write to radio and wait for config complete DeviceStateContainer container = await connection.WriteToRadio(wantConfig, async (fromRadio, state) => { // Return true when config is complete to stop reading if (fromRadio.PayloadVariantCase == FromRadio.PayloadVariantOneofCase.ConfigCompleteId) { Console.WriteLine($"Config complete! Node ID: {state.MyNodeInfo.MyNodeNum}"); Console.WriteLine($"Firmware: {state.Metadata.FirmwareVersion}"); Console.WriteLine($"Nodes discovered: {state.Nodes.Count}"); return true; } return false; }); // Access device state Console.WriteLine($"Device Region: {container.LocalConfig.Lora.Region}"); Console.WriteLine($"Channels: {container.Channels.Count}"); // Disconnect when done connection.Disconnect(); ``` ## TCP Connection The `TcpConnection` class enables network-based communication with Meshtastic devices over TCP/IP. It connects to devices on the default port 4403 and supports the same operations as serial connections. ```csharp using Meshtastic.Connections; using Meshtastic.Data; using Meshtastic.Data.MessageFactories; using Meshtastic.Protobufs; using Microsoft.Extensions.Logging; using var loggerFactory = LoggerFactory.Create(builder => builder.AddConsole()); var logger = loggerFactory.CreateLogger<TcpConnection>(); // Connect to device by IP address (default port 4403) using var connection = new TcpConnection(logger, "192.168.1.100"); // Or specify custom port // using var connection = new TcpConnection(logger, "192.168.1.100", port: 4403); var toRadioFactory = new ToRadioMessageFactory(); var wantConfig = toRadioFactory.CreateWantConfigMessage(); DeviceStateContainer container = await connection.WriteToRadio(wantConfig, async (fromRadio, state) => { if (fromRadio.PayloadVariantCase == FromRadio.PayloadVariantOneofCase.ConfigCompleteId) { Console.WriteLine($"Connected to: {state.GetDeviceNodeInfo()?.User?.LongName}"); Console.WriteLine($"Hardware: {state.Metadata.HwModel}"); return true; } return false; }); // TCP connection implements IDisposable for automatic cleanup ``` ## Device Discovery The `DeviceDiscovery` class provides automatic detection of connected Meshtastic USB devices on Linux and macOS. It matches known vendor IDs (Heltec, RAK, Seeed, etc.) and returns available serial port paths. ```csharp using Meshtastic.Discovery; using Microsoft.Extensions.Logging; using var loggerFactory = LoggerFactory.Create(builder => builder.AddConsole()); var logger = loggerFactory.CreateLogger<DeviceDiscovery>(); var discovery = new DeviceDiscovery(logger); // Discover all connected Meshtastic USB devices IEnumerable<MeshtasticDevice> devices = discovery.DiscoverUsbDevices(); foreach (var device in devices) { Console.WriteLine($"Device: {device.Name}"); Console.WriteLine($" Serial Port: {device.SerialPort}"); Console.WriteLine($" Vendor ID: {device.VendorId}"); Console.WriteLine($" Product ID: {device.ProductId}"); Console.WriteLine($" Hardware Model: {device.HwModel}"); Console.WriteLine($" Connection Type: {device.ConnectionType}"); } // Supported vendor IDs include: // - 239A (Nordic NRF52 devices) // - 10C4 (Silicon Labs CP210x - Heltec V3) // - 1A86 (CH340/CH341) // - 0403 (FTDI) // - 2E8A (Raspberry Pi Pico) // - 2886 (Seeed Studio) ``` ## Text Message Factory The `TextMessageFactory` creates properly formatted mesh packets for sending text messages to individual nodes or broadcasting to all nodes on a channel. ```csharp using Meshtastic.Connections; using Meshtastic.Data; using Meshtastic.Data.MessageFactories; using Meshtastic.Protobufs; using Microsoft.Extensions.Logging; using var loggerFactory = LoggerFactory.Create(builder => builder.AddConsole()); var logger = loggerFactory.CreateLogger<SerialConnection>(); var connection = new SerialConnection(logger, "/dev/ttyUSB0"); var toRadioFactory = new ToRadioMessageFactory(); // Get device config first var container = await connection.WriteToRadio(toRadioFactory.CreateWantConfigMessage(), async (fromRadio, state) => fromRadio.PayloadVariantCase == FromRadio.PayloadVariantOneofCase.ConfigCompleteId); // Create text message factory (null destination = broadcast to all) var textFactory = new TextMessageFactory(container, dest: null); // Create broadcast message on primary channel (0) MeshPacket broadcastPacket = textFactory.CreateTextMessagePacket("Hello mesh!", channel: 0); // Create direct message to specific node uint targetNodeNum = 0x12345678; var directFactory = new TextMessageFactory(container, dest: targetNodeNum); MeshPacket directPacket = directFactory.CreateTextMessagePacket("Hello specific node!"); // Send the message and wait for acknowledgment await connection.WriteToRadio(toRadioFactory.CreateMeshPacketMessage(broadcastPacket), async (fromRadio, state) => { var routing = fromRadio.GetPayload<Routing>(); if (routing != null && fromRadio.Packet.Priority == MeshPacket.Types.Priority.Ack) { if (routing.ErrorReason == Routing.Types.Error.None) Console.WriteLine("Message acknowledged!"); else Console.WriteLine($"Delivery failed: {routing.ErrorReason}"); return true; } return false; }); connection.Disconnect(); ``` ## Admin Message Factory The `AdminMessageFactory` creates administrative commands for device configuration, including settings changes, channel management, reboots, and factory resets. ```csharp using Meshtastic.Connections; using Meshtastic.Data; using Meshtastic.Data.MessageFactories; using Meshtastic.Protobufs; using Microsoft.Extensions.Logging; using static Meshtastic.Protobufs.Config.Types; using var loggerFactory = LoggerFactory.Create(builder => builder.AddConsole()); var logger = loggerFactory.CreateLogger<SerialConnection>(); var connection = new SerialConnection(logger, "/dev/ttyUSB0"); var toRadioFactory = new ToRadioMessageFactory(); // Get device config var container = await connection.WriteToRadio(toRadioFactory.CreateWantConfigMessage(), async (fromRadio, state) => fromRadio.PayloadVariantCase == FromRadio.PayloadVariantOneofCase.ConfigCompleteId); // Create admin factory for local device (null dest = this device) var adminFactory = new AdminMessageFactory(container, dest: null); // Begin edit transaction (required before making config changes) var beginEdit = adminFactory.CreateBeginEditSettingsMessage(); await connection.WriteToRadio(toRadioFactory.CreateMeshPacketMessage(beginEdit), async (fromRadio, state) => true); // Modify device configuration var deviceConfig = container.LocalConfig.Device; deviceConfig.Role = Config.Types.DeviceConfig.Types.Role.Client; var setConfig = adminFactory.CreateSetConfigMessage(deviceConfig); await connection.WriteToRadio(toRadioFactory.CreateMeshPacketMessage(setConfig), async (fromRadio, state) => true); // Commit changes var commitEdit = adminFactory.CreateCommitEditSettingsMessage(); await connection.WriteToRadio(toRadioFactory.CreateMeshPacketMessage(commitEdit), async (fromRadio, state) => true); // Other admin operations: // Reboot device in 5 seconds var rebootPacket = adminFactory.CreateRebootMessage(seconds: 5, isOta: false); // Factory reset var resetPacket = adminFactory.CreateFactoryResetMessage(); // Reset node database var nodeDbReset = adminFactory.CreateNodeDbResetMessage(); // Remove specific node from database var removeNode = adminFactory.CreateRemoveByNodenumMessage(nodeNum: 0x12345678); // Set fixed position var fixedPos = adminFactory.CreateFixedPositionMessage(new Position { LatitudeI = (int)(37.7749 * 1e7), LongitudeI = (int)(-122.4194 * 1e7), Altitude = 10 }); // Get device metadata var getMetadata = adminFactory.CreateGetMetadataMessage(); connection.Disconnect(); ``` ## Waypoint Message Factory The `WaypointMessageFactory` creates mesh packets for sharing geographic waypoints across the mesh network. Waypoints can include names, descriptions, and icons. ```csharp using Meshtastic.Connections; using Meshtastic.Data; using Meshtastic.Data.MessageFactories; using Meshtastic.Protobufs; using Microsoft.Extensions.Logging; using var loggerFactory = LoggerFactory.Create(builder => builder.AddConsole()); var logger = loggerFactory.CreateLogger<SerialConnection>(); var connection = new SerialConnection(logger, "/dev/ttyUSB0"); var toRadioFactory = new ToRadioMessageFactory(); var container = await connection.WriteToRadio(toRadioFactory.CreateWantConfigMessage(), async (fromRadio, state) => fromRadio.PayloadVariantCase == FromRadio.PayloadVariantOneofCase.ConfigCompleteId); // Create waypoint factory (null dest = broadcast) var waypointFactory = new WaypointMessageFactory(container, dest: null); // Define waypoint location var waypoint = new Waypoint { Id = (uint)Random.Shared.Next(), Name = "Camp Site", Description = "Meet here at noon", LatitudeI = (int)(37.7749 * 1e7), // San Francisco latitude LongitudeI = (int)(-122.4194 * 1e7), // San Francisco longitude Icon = 128205, // Pin emoji codepoint Expire = (uint)DateTimeOffset.UtcNow.AddHours(24).ToUnixTimeSeconds() }; // Create and send waypoint packet MeshPacket waypointPacket = waypointFactory.CreateWaypointPacket(waypoint, channel: 0); await connection.WriteToRadio(toRadioFactory.CreateMeshPacketMessage(waypointPacket), async (fromRadio, state) => { var routing = fromRadio.GetPayload<Routing>(); if (routing != null) { Console.WriteLine(routing.ErrorReason == Routing.Types.Error.None ? "Waypoint sent successfully!" : $"Failed: {routing.ErrorReason}"); return true; } return false; }); connection.Disconnect(); ``` ## Trace Route Message Factory The `TraceRouteMessageFactory` creates route discovery packets to trace the path between nodes in the mesh network, useful for debugging connectivity and understanding network topology. ```csharp using Meshtastic.Connections; using Meshtastic.Data; using Meshtastic.Data.MessageFactories; using Meshtastic.Protobufs; using Meshtastic.Extensions; using Microsoft.Extensions.Logging; using var loggerFactory = LoggerFactory.Create(builder => builder.AddConsole()); var logger = loggerFactory.CreateLogger<SerialConnection>(); var connection = new SerialConnection(logger, "/dev/ttyUSB0"); var toRadioFactory = new ToRadioMessageFactory(); var container = await connection.WriteToRadio(toRadioFactory.CreateWantConfigMessage(), async (fromRadio, state) => fromRadio.PayloadVariantCase == FromRadio.PayloadVariantOneofCase.ConfigCompleteId); // Create trace route to specific destination node uint destinationNode = 0x12345678; var traceRouteFactory = new TraceRouteMessageFactory(container, dest: destinationNode); MeshPacket tracePacket = traceRouteFactory.CreateRouteDiscoveryPacket(channel: 0); uint requestId = tracePacket.Id; Console.WriteLine($"Tracing route to node {destinationNode:X}..."); await connection.WriteToRadio(toRadioFactory.CreateMeshPacketMessage(tracePacket), async (fromRadio, state) => { // Check if this is the response to our trace request if (fromRadio.Packet?.Decoded?.RequestId == requestId && fromRadio.Packet?.Decoded?.Portnum == PortNum.TracerouteApp) { var routeDiscovery = fromRadio.GetPayload<RouteDiscovery>(); if (routeDiscovery != null) { Console.WriteLine("Route discovered:"); Console.WriteLine($" Hops: {routeDiscovery.Route.Count}"); foreach (var hop in routeDiscovery.Route) { string nodeName = state.GetNodeDisplayName(hop); Console.WriteLine($" -> {nodeName} ({hop:X})"); } } return true; } return false; }); connection.Disconnect(); ``` ## Telemetry Message Factory The `TelemetryMessageFactory` creates telemetry request packets for retrieving device metrics (battery, voltage, uptime) from other nodes in the mesh. ```csharp using Meshtastic.Connections; using Meshtastic.Data; using Meshtastic.Data.MessageFactories; using Meshtastic.Protobufs; using Meshtastic.Extensions; using Microsoft.Extensions.Logging; using var loggerFactory = LoggerFactory.Create(builder => builder.AddConsole()); var logger = loggerFactory.CreateLogger<SerialConnection>(); var connection = new SerialConnection(logger, "/dev/ttyUSB0"); var toRadioFactory = new ToRadioMessageFactory(); var container = await connection.WriteToRadio(toRadioFactory.CreateWantConfigMessage(), async (fromRadio, state) => fromRadio.PayloadVariantCase == FromRadio.PayloadVariantOneofCase.ConfigCompleteId); // Request telemetry from a specific node uint targetNode = 0x12345678; var telemetryFactory = new TelemetryMessageFactory(container, dest: targetNode); MeshPacket telemetryRequest = telemetryFactory.CreateTelemetryPacket(channel: 0); Console.WriteLine($"Requesting telemetry from {container.GetNodeDisplayName(targetNode)}..."); await connection.WriteToRadio(toRadioFactory.CreateMeshPacketMessage(telemetryRequest), async (fromRadio, state) => { var telemetry = fromRadio.GetPayload<Telemetry>(); if (telemetry?.DeviceMetrics != null && fromRadio.Packet?.From == targetNode) { var metrics = telemetry.DeviceMetrics; Console.WriteLine("Device Telemetry:"); Console.WriteLine($" Battery: {metrics.BatteryLevel}%"); Console.WriteLine($" Voltage: {metrics.Voltage}V"); Console.WriteLine($" Channel Utilization: {metrics.ChannelUtilization}%"); Console.WriteLine($" Air Util TX: {metrics.AirUtilTx}%"); Console.WriteLine($" Uptime: {metrics.UptimeSeconds} seconds"); return true; } return false; }); connection.Disconnect(); ``` ## Device State Container The `DeviceStateContainer` maintains the complete state of a connected device including configuration, channels, node database, and message logs. It provides helper methods for accessing commonly needed information. ```csharp using Meshtastic.Connections; using Meshtastic.Data; using Meshtastic.Data.MessageFactories; using Meshtastic.Protobufs; using Microsoft.Extensions.Logging; using var loggerFactory = LoggerFactory.Create(builder => builder.AddConsole()); var logger = loggerFactory.CreateLogger<SerialConnection>(); var connection = new SerialConnection(logger, "/dev/ttyUSB0"); var toRadioFactory = new ToRadioMessageFactory(); DeviceStateContainer container = await connection.WriteToRadio(toRadioFactory.CreateWantConfigMessage(), async (fromRadio, state) => fromRadio.PayloadVariantCase == FromRadio.PayloadVariantOneofCase.ConfigCompleteId); // Access device info Console.WriteLine($"My Node Number: {container.MyNodeInfo.MyNodeNum}"); Console.WriteLine($"Has GPS: {container.MyNodeInfo.HasGps}"); // Get this device's node info NodeInfo? myNode = container.GetDeviceNodeInfo(); Console.WriteLine($"Long Name: {myNode?.User?.LongName}"); Console.WriteLine($"Short Name: {myNode?.User?.ShortName}"); // Access device configuration Console.WriteLine($"Region: {container.LocalConfig.Lora.Region}"); Console.WriteLine($"Modem Preset: {container.LocalConfig.Lora.ModemPreset}"); Console.WriteLine($"Hop Limit: {container.GetHopLimitOrDefault()}"); // Access module configuration Console.WriteLine($"MQTT Enabled: {container.LocalModuleConfig.Mqtt.Enabled}"); Console.WriteLine($"Telemetry Interval: {container.LocalModuleConfig.Telemetry.DeviceUpdateInterval}s"); // List all channels foreach (var channel in container.Channels) { Console.WriteLine($"Channel {channel.Index}: {channel.Settings.Name} ({channel.Role})"); } // Get admin channel index (for remote administration) uint adminChannel = container.GetAdminChannelIndex(); // List all known nodes foreach (var node in container.Nodes) { string displayName = container.GetNodeDisplayName(node.Num); Console.WriteLine($"Node: {displayName}"); Console.WriteLine($" Last Heard: {node.LastHeard}"); Console.WriteLine($" SNR: {node.Snr}"); } // Generate shareable channel URL string channelUrl = container.GetChannelUrl(); Console.WriteLine($"Channel URL: {channelUrl}"); // Generate URL for specific channels only string partialUrl = container.GetChannelUrl(selection: new[] { 0, 1 }); // Access device metadata Console.WriteLine($"Firmware: {container.Metadata.FirmwareVersion}"); Console.WriteLine($"Hardware Model: {container.Metadata.HwModel}"); connection.Disconnect(); ``` ## FromRadio Extensions The `FromRadioExtensions` class provides strongly-typed payload extraction from incoming radio messages, automatically parsing Protocol Buffer payloads based on port number. ```csharp using Meshtastic.Connections; using Meshtastic.Data; using Meshtastic.Data.MessageFactories; using Meshtastic.Extensions; using Meshtastic.Protobufs; using Microsoft.Extensions.Logging; using var loggerFactory = LoggerFactory.Create(builder => builder.AddConsole()); var logger = loggerFactory.CreateLogger<SerialConnection>(); var connection = new SerialConnection(logger, "/dev/ttyUSB0"); var toRadioFactory = new ToRadioMessageFactory(); var container = await connection.WriteToRadio(toRadioFactory.CreateWantConfigMessage(), async (fromRadio, state) => fromRadio.PayloadVariantCase == FromRadio.PayloadVariantOneofCase.ConfigCompleteId); // Monitor incoming messages and extract typed payloads await connection.ReadFromRadio(async (fromRadio, state) => { if (fromRadio == null) return false; // Extract text messages string? textMessage = fromRadio.GetPayload<string>(); if (textMessage != null) { uint sender = fromRadio.Packet.From; Console.WriteLine($"Text from {state.GetNodeDisplayName(sender)}: {textMessage}"); } // Extract position updates Position? position = fromRadio.GetPayload<Position>(); if (position != null) { double lat = position.LatitudeI * 1e-7; double lon = position.LongitudeI * 1e-7; Console.WriteLine($"Position update: {lat}, {lon} Alt: {position.Altitude}m"); } // Extract telemetry data Telemetry? telemetry = fromRadio.GetPayload<Telemetry>(); if (telemetry?.DeviceMetrics != null) { Console.WriteLine($"Telemetry - Battery: {telemetry.DeviceMetrics.BatteryLevel}%"); } // Extract node info updates NodeInfo? nodeInfo = fromRadio.GetPayload<NodeInfo>(); if (nodeInfo != null) { Console.WriteLine($"Node update: {nodeInfo.User?.LongName}"); } // Extract routing/acknowledgment info Routing? routing = fromRadio.GetPayload<Routing>(); if (routing != null) { Console.WriteLine($"Routing result: {routing.ErrorReason}"); } // Extract admin message responses AdminMessage? admin = fromRadio.GetPayload<AdminMessage>(); if (admin != null) { Console.WriteLine($"Admin response received"); } // Extract waypoints Waypoint? waypoint = fromRadio.GetPayload<Waypoint>(); if (waypoint != null) { Console.WriteLine($"Waypoint: {waypoint.Name} at {waypoint.LatitudeI * 1e-7}, {waypoint.LongitudeI * 1e-7}"); } return false; // Continue listening }, readTimeoutMs: 60000); connection.Disconnect(); ``` ## Packet Encryption The `PacketEncryption` class provides AES-CTR encryption and decryption for mesh packets using the BouncyCastle cryptography library. ```csharp using Meshtastic.Crypto; // Default Meshtastic PSK (pre-shared key) byte[] defaultPsk = new byte[] { 0xd4, 0xf1, 0xbb, 0x3a, 0x20, 0x29, 0x07, 0x59, 0xf0, 0xbc, 0xff, 0xab, 0xcf, 0x4e, 0x69, 0x01 }; // Or use a custom 16/32 byte key byte[] customKey = new byte[32]; // 256-bit key Random.Shared.NextBytes(customKey); // Nonce should be 16 bytes, typically derived from packet ID and sender byte[] nonce = new byte[16]; // Typically constructed from: packetId (4 bytes) + fromNode (4 bytes) + padding // Decrypt an encrypted packet payload byte[] encryptedPayload = new byte[] { /* ... encrypted data ... */ }; byte[] decryptedPayload = PacketEncryption.TransformPacket(encryptedPayload, nonce, defaultPsk); // The same function encrypts (AES-CTR is symmetric) byte[] plainText = System.Text.Encoding.UTF8.GetBytes("Hello Mesh!"); byte[] encrypted = PacketEncryption.TransformPacket(plainText, nonce, defaultPsk); ``` ## CLI Commands ### List Available Ports ```bash # List all available serial ports for Meshtastic devices meshtastic-cli list ``` ### Get Device Info ```bash # Get comprehensive device information via serial meshtastic-cli info --port /dev/ttyUSB0 # Get device info via TCP meshtastic-cli info --host 192.168.1.100 # Output as JSON meshtastic-cli info --port /dev/ttyUSB0 --output Json ``` ### Send Text Messages ```bash # Broadcast message to all nodes on primary channel meshtastic-cli text "Hello everyone!" --port /dev/ttyUSB0 # Send direct message to specific node meshtastic-cli text "Hello!" --port /dev/ttyUSB0 --dest 0x12345678 # Interactively select destination from node list meshtastic-cli text "Hello!" --port /dev/ttyUSB0 --select-dest ``` ### Get and Set Configuration ```bash # Get specific setting values meshtastic-cli get --setting Lora.Region --setting Device.Role --port /dev/ttyUSB0 # Set configuration values meshtastic-cli set --setting Lora.Region=US --port /dev/ttyUSB0 meshtastic-cli set --setting Device.Role=Client --port /dev/ttyUSB0 meshtastic-cli set --setting Bluetooth.Enabled=true --port /dev/ttyUSB0 # Set multiple settings at once meshtastic-cli set --setting Lora.Region=EU_868 --setting Device.Role=Router --port /dev/ttyUSB0 ``` ### Channel Management ```bash # Add a new channel with random PSK meshtastic-cli channel Add --index 1 --name "Private" --psk random --port /dev/ttyUSB0 # Add channel with specific PSK (hashed) meshtastic-cli channel Add --index 1 --name "Secure" --psk "mysecretpassword" --port /dev/ttyUSB0 # Enable/disable channels meshtastic-cli channel Enable --index 1 --port /dev/ttyUSB0 meshtastic-cli channel Disable --index 2 --port /dev/ttyUSB0 # Get/set channel URL for sharing meshtastic-cli url Get --port /dev/ttyUSB0 meshtastic-cli url Set "https://meshtastic.org/e/#..." --port /dev/ttyUSB0 ``` ### Device Operations ```bash # Reboot device (default 5 second delay) meshtastic-cli reboot --port /dev/ttyUSB0 # Reboot with custom delay meshtastic-cli reboot 10 --port /dev/ttyUSB0 # Factory reset device configuration meshtastic-cli factory-reset --port /dev/ttyUSB0 # Reset node database meshtastic-cli reset-nodedb --port /dev/ttyUSB0 # Remove specific node from database meshtastic-cli remove-node 0x12345678 --port /dev/ttyUSB0 # Get device metadata meshtastic-cli metadata --port /dev/ttyUSB0 ``` ### Position and Waypoints ```bash # Set fixed position meshtastic-cli fixed-position 37.7749 -122.4194 10 --port /dev/ttyUSB0 # Send waypoint to mesh meshtastic-cli waypoint 37.7749 -122.4194 --port /dev/ttyUSB0 ``` ### Network Diagnostics ```bash # Trace route to destination node meshtastic-cli trace-route --dest 0x12345678 --port /dev/ttyUSB0 # Request telemetry from specific node meshtastic-cli request-telemetry --dest 0x12345678 --port /dev/ttyUSB0 ``` ### Monitoring and Live Dashboard ```bash # Serial monitor mode (raw device output) meshtastic-cli monitor --port /dev/ttyUSB0 # Live dashboard with nodes, messages, and traffic meshtastic-cli live --port /dev/ttyUSB0 ``` ### Profile Export/Import ```bash # Export device profile to YAML file meshtastic-cli export --port /dev/ttyUSB0 # Creates export.yml with selected configuration # Import profile from YAML file meshtastic-cli import profile.yml --port /dev/ttyUSB0 ``` ### MQTT Proxy ```bash # Start MQTT proxy (forwards messages between device and MQTT broker) meshtastic-cli mqtt-proxy --port /dev/ttyUSB0 ``` ### Firmware Update ```bash # Update firmware (serial connected NRF52 devices) meshtastic-cli update --port /dev/ttyUSB0 # Enter DFU mode for manual update meshtastic-cli dfu --port /dev/ttyUSB0 ``` ### Canned Messages ```bash # Get current canned messages meshtastic-cli canned-messages Get --port /dev/ttyUSB0 # Set canned messages (pipe-separated) meshtastic-cli canned-messages Set "OK|Help|On my way" --port /dev/ttyUSB0 ``` ### Logging Levels ```bash # Set logging verbosity meshtastic-cli info --port /dev/ttyUSB0 --log Debug meshtastic-cli info --port /dev/ttyUSB0 --log Trace meshtastic-cli info --port /dev/ttyUSB0 --log Warning ``` ## Summary Meshtastic C# provides a complete solution for integrating Meshtastic mesh radio devices into .NET applications. The library supports multiple connection types (Serial, TCP, and planned Bluetooth support), handles all Protocol Buffer message serialization automatically, and provides high-level abstractions through message factories for common operations like sending text, managing channels, and configuring device settings. The event-driven architecture with async/await patterns makes it easy to build responsive applications that react to incoming mesh traffic. The CLI tool built on this library demonstrates practical usage patterns and provides a full-featured command-line interface for device management without writing code. Key integration patterns include: connecting via `SerialConnection` or `TcpConnection`, requesting device state with `ToRadioMessageFactory.CreateWantConfigMessage()`, accessing configuration through `DeviceStateContainer`, creating messages with typed factories (`TextMessageFactory`, `AdminMessageFactory`, etc.), and processing responses using `FromRadioExtensions.GetPayload<T>()` for type-safe payload extraction. The modular design allows developers to use just the core library for programmatic control or leverage the CLI for scripting and automation.