# Examples Practical code examples for common MeshCS use cases. ## Basic Chat Application A simple console chat application: ```csharp using MeshCS; Console.WriteLine("MeshCS Chat"); Console.WriteLine("==========="); // Connect to device var radio = await MeshRadio.ConnectFirstAsync(verbose: true); if (radio == null) { Console.WriteLine("No device found!"); return; } Console.WriteLine($"Connected as: {radio.Self?.Name}"); Console.WriteLine(); // Subscribe to messages radio.DirectMessageReceived += (msg) => { var sender = msg.IsV3 && !string.IsNullOrEmpty(msg.SenderName) ? msg.SenderName : msg.SenderPrefixHex[..8]; Console.WriteLine($"\n[{sender}]: {msg.Text}"); Console.Write("> "); }; radio.ChannelMessageReceived += (msg) => { var sender = msg.IsV3 && !string.IsNullOrEmpty(msg.SenderName) ? msg.SenderName : "???"; Console.WriteLine($"\n[CH{msg.ChannelIndex}|{sender}]: {msg.Text}"); Console.Write("> "); }; // Get contacts var contacts = await radio.GetContactsAsync(); Console.WriteLine($"Contacts: {contacts.Count}"); foreach (var c in contacts) { Console.WriteLine($" {c.Name} ({c.PublicKeyPrefix})"); } Console.WriteLine(); // Chat loop Console.WriteLine("Commands: /list, /ch , /quit"); Console.WriteLine("Or type a message to send to first contact"); Console.WriteLine(); while (true) { Console.Write("> "); var input = Console.ReadLine(); if (string.IsNullOrWhiteSpace(input)) continue; if (input == "/quit") break; if (input == "/list") { contacts = await radio.GetContactsAsync(); foreach (var c in contacts) Console.WriteLine($" {c.Name} ({c.PublicKeyPrefix})"); continue; } if (input.StartsWith("/ch ")) { var parts = input[4..].Split(' ', 2); if (parts.Length == 2 && byte.TryParse(parts[0], out var ch)) { await radio.SendChannelMessageAsync(ch, parts[1]); Console.WriteLine($"Sent to channel {ch}"); } continue; } // Send to first contact if (contacts.Count > 0) { await radio.SendMessageAsync(contacts[0].PublicKey[..6], input); Console.WriteLine("Sent!"); } else { Console.WriteLine("No contacts to send to"); } } radio.Dispose(); ``` ## BBS Server A simple BBS server that responds to commands: ```csharp using MeshCS; Console.WriteLine("MeshCS BBS Server"); var radio = await MeshRadio.ConnectFirstAsync(verbose: true); if (radio == null) return; var helpText = @" Commands: HELP - Show this help INFO - Server info TIME - Current time PING - Test connection "; radio.ChannelMessageReceived += async (msg) => { var text = msg.Text.Trim().ToUpperInvariant(); string? response = null; switch (text) { case "HELP": response = helpText; break; case "INFO": response = $"MeshCS BBS v1.0\nNode: {radio.Self?.Name}"; break; case "TIME": response = DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss UTC"); break; case "PING": response = "PONG"; break; } if (response != null) { await radio.SendChannelMessageAsync(msg.ChannelIndex, response); } }; Console.WriteLine("Listening... Press Enter to exit."); Console.ReadLine(); ``` ## Device Monitor Monitor device status and mesh activity: ```csharp using MeshCS; var radio = await MeshRadio.ConnectFirstAsync(verbose: true); if (radio == null) return; // Get initial info var device = await radio.DeviceQueryAsync(); var battery = await radio.GetBatteryAsync(); Console.WriteLine($"Device: {device?.Model}"); Console.WriteLine($"Firmware: {device?.FirmwareVersion}"); Console.WriteLine($"Battery: {battery?.Percentage}%"); Console.WriteLine(); var seenNodes = new Dictionary(); radio.AdvertReceived += (advert) => { var key = advert.PublicKeyHex[..12]; seenNodes[key] = (advert.Name, DateTime.UtcNow); Console.WriteLine($"[{DateTime.Now:HH:mm:ss}] AD: {advert.Name,-16} " + $"Hops:{advert.PathLen} SNR:{advert.Snr,3}dB"); }; radio.DirectMessageReceived += (msg) => { Console.WriteLine($"[{DateTime.Now:HH:mm:ss}] DM: {msg.SenderPrefixHex} " + $"Hops:{msg.PathLen} SNR:{msg.Snr,3}dB"); }; radio.ChannelMessageReceived += (msg) => { Console.WriteLine($"[{DateTime.Now:HH:mm:ss}] CH{msg.ChannelIndex}: " + $"Hops:{msg.PathLen} SNR:{msg.Snr,3}dB"); }; // Status update loop var cts = new CancellationTokenSource(); Console.CancelKeyPress += (s, e) => { e.Cancel = true; cts.Cancel(); }; while (!cts.IsCancellationRequested) { await Task.Delay(60000, cts.Token); battery = await radio.GetBatteryAsync(); Console.WriteLine($"[{DateTime.Now:HH:mm:ss}] Battery: {battery?.Percentage}% " + $"Nodes seen: {seenNodes.Count}"); } ``` ## Port Scanner Find all MeshCore devices on the system: ```csharp using MeshCS; Console.WriteLine("Scanning for MeshCore devices...\n"); var results = await MeshRadio.ScanAllPortsAsync( timeoutMs: 3000, verbose: true ); Console.WriteLine("\n=== Results ==="); foreach (var result in results) { if (result.Found) { Console.WriteLine($"✓ {result.PortName}: {result.Self?.Name}"); Console.WriteLine($" Key: {result.Self?.PublicKeyPrefix}..."); } else if (result.Error != null) { Console.WriteLine($"✗ {result.PortName}: {result.Error}"); } else { Console.WriteLine($"- {result.PortName}: No response"); } } var found = results.Where(r => r.Found).ToList(); Console.WriteLine($"\nFound {found.Count} device(s)"); ``` ## Channel Configuration Configure and monitor channels: ```csharp using MeshCS; var radio = await MeshRadio.ConnectFirstAsync(); if (radio == null) return; // Read all channel configurations Console.WriteLine("Current Channels:"); for (byte i = 0; i < 8; i++) { var ch = await radio.GetChannelAsync(i); if (ch != null && !string.IsNullOrEmpty(ch.Name)) { Console.WriteLine($" [{i}] {ch.Name}"); Console.WriteLine($" Secret: {ch.SecretHex[..8]}..."); Console.WriteLine($" Forward: {ch.ForwardEnabled}"); } } // Configure a new channel Console.WriteLine("\nConfiguring channel 1..."); var secret = new byte[16]; Random.Shared.NextBytes(secret); await radio.SetChannelAsync(1, "MyChannel", secret); // Verify var newCh = await radio.GetChannelAsync(1); Console.WriteLine($"Channel 1 is now: {newCh?.Name}"); ``` ## Message Logger Log all messages to a file: ```csharp using MeshCS; var radio = await MeshRadio.ConnectFirstAsync(); if (radio == null) return; using var logFile = new StreamWriter("mesh_log.txt", append: true); void Log(string message) { var line = $"[{DateTime.UtcNow:O}] {message}"; Console.WriteLine(line); logFile.WriteLine(line); logFile.Flush(); } Log($"Started logging for {radio.Self?.Name}"); radio.DirectMessageReceived += (msg) => { Log($"DM from {msg.SenderPrefixHex}: {msg.Text}"); }; radio.ChannelMessageReceived += (msg) => { Log($"CH{msg.ChannelIndex}: {msg.Text}"); }; radio.AdvertReceived += (advert) => { Log($"AD: {advert.Name} at {advert.PathLen} hops"); }; radio.ErrorOccurred += (error) => { Log($"ERROR: {error}"); }; Console.WriteLine("Logging... Press Enter to stop."); Console.ReadLine(); Log("Logging stopped"); ``` ## Low-Level Packet Access For advanced use cases, access packets directly: ```csharp using MeshCS; // Build a custom packet var packet = PacketBuilder.SendMsg( recipientPubKeyPrefix: new byte[] { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 }, text: "Hello!", textType: TextType.Plain, timestamp: (uint)DateTimeOffset.UtcNow.ToUnixTimeSeconds() ); Console.WriteLine($"Packet: {BitConverter.ToString(packet)}"); // Parse a response manually var response = new byte[] { 0x05, /* ... SelfInfo data ... */ }; var selfInfo = PacketParser.ParseSelfInfo(response); if (selfInfo != null) { Console.WriteLine($"Parsed: {selfInfo.Name}"); } // Use debug events to monitor all traffic var radio = await MeshRadio.ConnectFirstAsync(); radio.PacketSent += (pkt) => { Console.WriteLine($"TX: {BitConverter.ToString(pkt)}"); }; radio.PacketReceived += (pkt) => { var code = pkt[0]; var isPush = (code & 0x80) != 0; Console.WriteLine($"RX: 0x{code:X2} ({(isPush ? "PUSH" : "RSP")}) " + $"{pkt.Length} bytes"); }; ``` ## Contact Management Full contact management example: ```csharp using MeshCS; var radio = await MeshRadio.ConnectFirstAsync(); if (radio == null) return; // List all contacts var contacts = await radio.GetContactsAsync(); Console.WriteLine($"Total contacts: {contacts.Count}"); foreach (var contact in contacts) { var lastSeen = DateTimeOffset.FromUnixTimeSeconds(contact.LastSeen); var ago = DateTime.UtcNow - lastSeen.UtcDateTime; Console.WriteLine($"\n{contact.Name}"); Console.WriteLine($" Key: {contact.PublicKeyPrefix}"); Console.WriteLine($" Type: {contact.Type}"); Console.WriteLine($" Hops: {contact.PathLen}"); Console.WriteLine($" Last seen: {ago.TotalMinutes:F0} minutes ago"); } // Add a contact from a public key (hex string) var pubKeyHex = "0102030405060708091011121314151617181920212223242526272829303132"; var pubKey = Convert.FromHexString(pubKeyHex); await radio.AddContactAsync(pubKey, "NewContact", ContactType.Chat); Console.WriteLine("Contact added!"); // Remove a contact var toRemove = contacts.FirstOrDefault(c => c.Name == "OldContact"); if (toRemove != null) { await radio.RemoveContactAsync(toRemove.PublicKey[..6]); Console.WriteLine("Contact removed!"); } ```