Getting Started
Installation
# PSEM (ANSI C12.18/C12.19) — serial or TCP meters
dotnet add package SharpMeter.Client
# DLMS/COSEM (IEC 62056) — smart meters
dotnet add package SharpMeter.Dlms
# Testing with built-in emulator
dotnet add package SharpMeter.Emulator
Requirements
- .NET 9.0 or .NET 10.0
- For serial communication: a USB-to-optical probe (e.g., ANSI Type 2 optical port)
- For TCP: network access to the meter or collector
First PSEM Connection
using SharpMeter.Client;
using SharpMeter.Transport;
using Microsoft.Extensions.Logging.Abstractions;
// 1. Create a serial transport
var options = new TransportOptions
{
PortName = "COM3",
BaudRate = 9600
};
await using var transport = new SerialTransport(options, NullLogger<SerialTransport>.Instance);
// 2. Create the PSEM client
await using var client = new PsemClient(transport, NullLogger<PsemClient>.Instance);
// 3. Connect (identify → negotiate → logon → security)
byte[] password = new byte[20]; // your meter password
var result = await client.ConnectAsync(
userId: 2,
userName: "SharpMeter",
password: password);
if (result.IsSuccess)
{
// 4. Read a table
var table = await client.ReadTableAsync(tableId: 1);
if (table.IsSuccess)
Console.WriteLine($"Read {table.Value.Length} bytes from {table.Value.DisplayName}");
// 5. Disconnect gracefully
await client.DisconnectAsync();
}
else
{
Console.WriteLine($"Connection failed: {result.Error}");
}
First DLMS Connection
using SharpMeter.Dlms;
using SharpMeter.Dlms.Enums;
using SharpMeter.Transport;
using Microsoft.Extensions.Logging.Abstractions;
// 1. Create a TCP transport
var options = new TransportOptions { Host = "192.168.1.100", Port = 4059 };
await using var transport = new TcpTransport(options, NullLogger<TcpTransport>.Instance);
// 2. Create the DLMS client
var dlmsOptions = new DlmsClientOptions
{
Authentication = AuthenticationMechanism.LowLevelSecurity,
Password = "password"u8.ToArray()
};
await using var client = new DlmsClient(transport, dlmsOptions, NullLogger<DlmsClient>.Instance);
// 3. Connect (SNRM → AARQ)
await client.ConnectAsync();
// 4. Read active energy import
var result = await client.GetAttributeAsync(
classId: 3,
obisCode: ObisCode.ActiveEnergyImportTotal,
attributeIndex: 2);
if (result.IsSuccess)
Console.WriteLine($"Energy: {result.Value.Length} bytes");
// 5. Disconnect
await client.DisconnectAsync();
Using the Emulator
No hardware? Use the built-in emulator for development and testing:
using SharpMeter.Client;
using SharpMeter.Emulator;
using Microsoft.Extensions.Logging.Abstractions;
var config = new EmulatorConfiguration
{
Manufacturer = "TEST",
SerialNumber = "TESTMETER0000001"
};
var emulator = new MeterEmulator(config, NullLogger<MeterEmulator>.Instance);
await using var transport = new EmulatorTransport(emulator, NullLogger<EmulatorTransport>.Instance);
await using var client = new PsemClient(transport, NullLogger<PsemClient>.Instance);
// Use exactly like a real meter
await client.ConnectAsync(password: null);
var table = await client.ReadTableAsync(1);
await client.DisconnectAsync();
Last updated: 2026-04-08