-
-
Notifications
You must be signed in to change notification settings - Fork 1
Examples
Max Litruv Boonzaayer edited this page Feb 15, 2026
·
3 revisions
Practical code examples for common MeshCS use cases.
A simple console chat application:
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 <n> <msg>, /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();A simple BBS server that responds to commands:
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();Monitor device status and mesh activity:
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<string, (string Name, DateTime LastSeen)>();
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}");
}Find all MeshCore devices on the system:
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)");Configure and monitor channels:
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}");Log all messages to a file:
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");For advanced use cases, access packets directly:
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");
};Full contact management example:
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!");
}MeshCS © 2026 Litruv | MIT License
MeshCS Documentation
Classes
Models
Enums
Links