Files
Print_server/Inspectron.Epson
EugeneTes fd19cd9358 fix: propagate SPRT discovery bind/broadcast failures instead of swallowing them
SprtDiscoveryService caught SocketException on the UDP 9100 bind and the
broadcast send and returned an empty list either way. That defeated the
CompositeDiscoveryService fix that rethrows only when every child discovery
service fails: on a real network fault the composite would see one child
throw (ENPC) and one child silently succeed empty (SPRT), conclude discovery
worked and found nothing, and let PrinterDiscoveryBackgroundTask expire and
deregister live Epson printers after the retention window - discarding their
queued jobs.

Move the policy decision to the composite, which already has it right: the
child now reports bind/broadcast failure honestly by rethrowing, and
CompositeDiscoveryService absorbs a single child's failure while still
rethrowing when every child fails. The per-datagram receive-loop catch is
unchanged - a single bad receive still shouldn't abort the pass.

Rewrote SprtDiscoveryServiceTests' bind-failure test to assert the throw, and
added an end-to-end CompositeDiscoveryServiceTests case with a real
SprtDiscoveryService failing to bind alongside a stub that succeeds, proving
the composite still degrades gracefully rather than losing the pass. Updated
the POS895 design doc to match the new contract.

Claude-Session: https://claude.ai/code/session_01E6N3P4nSZLtp4BC2LXVref
2026-09-03 13:01:58 +02:00
..
2026-01-13 09:06:47 +01:00
2026-02-18 13:18:19 +01:00
2026-01-13 09:06:47 +01:00
2026-01-13 09:06:47 +01:00
2026-01-13 09:06:47 +01:00
2026-04-02 09:37:18 +02:00
2026-01-13 09:06:47 +01:00
2026-02-05 11:39:06 +01:00
2026-01-13 09:06:47 +01:00
2026-01-13 09:06:47 +01:00
2026-04-03 08:38:32 +02:00
2026-01-13 09:06:47 +01:00
2026-01-13 09:06:47 +01:00
2026-02-04 14:20:08 +01:00
2026-01-26 14:29:37 +01:00
2026-01-26 14:29:37 +01:00
2026-01-13 09:06:47 +01:00
2026-01-13 09:06:47 +01:00

Inspectron.Epson - Epson TM-m30III Printer SDK

A comprehensive C# SDK for the Epson TM-m30III thermal receipt printer, providing easy-to-use APIs for printing, status checking, and diagnostics.

Features

  • Async/Await Pattern - Modern asynchronous API throughout
  • Connection Management - Reliable TCP/IP connection handling
  • Status Monitoring - Comprehensive printer status queries
  • Error Detection - Detailed error reporting and diagnostics
  • Printing Operations - Simple text printing with ESC/POS commands
  • Logging Support - Optional ILogger integration for diagnostics
  • Type-Safe - Strong typing with C# records for status data

Installation

Add the project reference to your solution:

dotnet add reference path/to/Inspectron.Epson/Inspectron.Epson.csproj

Or include the compiled DLL in your project.

Dependencies

  • .NET 8.0 or later
  • Microsoft.Extensions.Logging.Abstractions 8.0.0

Quick Start

Basic Printing

using Inspectron.Epson;

// Create printer instance
await using var printer = new EpsonPrinter();

// Connect to printer
await printer.ConnectAsync("192.168.1.100");

// Print text with paper cut
await printer.PrintTextAndCutAsync("Hello World!\nThis is a test receipt.");

With Logging

using Inspectron.Epson;
using Microsoft.Extensions.Logging;

// Create logger
var loggerFactory = LoggerFactory.Create(builder =>
{
    builder.AddConsole();
    builder.SetMinimumLevel(LogLevel.Information);
});

var logger = loggerFactory.CreateLogger<EpsonPrinter>();

// Create printer with logging
await using var printer = new EpsonPrinter(logger);
await printer.ConnectAsync("192.168.1.100");
await printer.PrintTextAndCutAsync("Hello World!");

Usage Examples

Checking Printer Status

await using var printer = new EpsonPrinter();
await printer.ConnectAsync("192.168.1.100");

// Get overall status with health assessment
var status = await printer.GetOverallStatusAsync();

Console.WriteLine($"Status: {status.StatusText}");
Console.WriteLine($"Ready: {status.IsReady}");
Console.WriteLine($"Model: {status.PrinterModel}");

if (!status.IsReady)
{
    Console.WriteLine("Recommendations:");
    foreach (var recommendation in status.Recommendations)
    {
        Console.WriteLine($"  - {recommendation}");
    }
}

Individual Status Queries

await using var printer = new EpsonPrinter();
await printer.ConnectAsync("192.168.1.100");

// Get specific status information
var printerStatus = await printer.GetPrinterStatusAsync();
Console.WriteLine($"Online: {printerStatus.IsOnline}");
Console.WriteLine($"Cover Closed: {printerStatus.IsCoverClosed}");

var paperStatus = await printer.GetPaperSensorStatusAsync();
Console.WriteLine($"Paper Present: {paperStatus.PaperPresent}");
Console.WriteLine($"Paper Near End: {paperStatus.PaperNearEnd}");

var errorStatus = await printer.GetErrorStatusAsync();
Console.WriteLine($"Has Error: {errorStatus.HasError}");
Console.WriteLine($"Recoverable Error: {errorStatus.RecoverableError}");

Running Diagnostics

using Inspectron.Epson;

var diagnostics = new EpsonDiagnostics();
var report = await diagnostics.RunFullDiagnosticsAsync("192.168.1.100");

Console.WriteLine(report);

Sample diagnostic output:

======================================================================
  EPSON TM-m30III PRINTER DIAGNOSTICS
======================================================================
  Printer IP:    192.168.1.100:9100
  Timestamp:     2024-01-15 14:30:45
======================================================================

⏳ Connecting to printer...
✅ Connection established

⏳ Retrieving printer information...
⏳ Querying printer status...

======================================================================
  OVERALL STATUS
======================================================================

  🟢 READY - Printer is operational

  🖨️ Printer Model                     TM-m30III

======================================================================
  GENERAL PRINTER STATUS
======================================================================
  📊 Raw Status Byte                   0x12
  📊 Binary                            00010010

  ✅ Printer Online                    YES
  ✅ Cover Closed                      YES
  ❌ Paper Feed Button Pressed         NO
  ❌ Drawer Open Signal                NO

Advanced Printing

await using var printer = new EpsonPrinter();
await printer.ConnectAsync("192.168.1.100");

// Print without cutting
await printer.PrintTextAsync("Line 1\n");
await printer.PrintTextAsync("Line 2\n");
await printer.PrintTextAsync("Line 3\n");

// Feed and cut
await printer.SendRawCommandAsync(EpsonCommands.FeedLines(5));
await printer.SendRawCommandAsync(EpsonCommands.CutPaperFull);

Sending Raw ESC/POS Commands

await using var printer = new EpsonPrinter();
await printer.ConnectAsync("192.168.1.100");

// Use predefined commands
await printer.SendRawCommandAsync(EpsonCommands.Initialize);
await printer.PrintTextAsync("Initialized printer\n");

// Or create custom commands
byte[] customCommand = { 0x1B, 0x40 }; // ESC @ (Initialize)
await printer.SendRawCommandAsync(customCommand);

API Reference

EpsonPrinter Class

Main class for printer operations.

Constructor

public EpsonPrinter(ILogger<EpsonPrinter>? logger = null)

Creates a new printer instance with optional logging support.

Connection Methods

Task ConnectAsync(string ip, int port = 9100, int timeoutSeconds = 5)

Connect to the printer at the specified IP address and port.

void Disconnect()

Disconnect from the printer.

bool IsConnected { get; }

Returns true if currently connected to the printer.

Status Query Methods

Task<PrinterStatus> GetPrinterStatusAsync()

Get general printer status (online, cover, drawer, etc.).

Task<OfflineStatus> GetOfflineStatusAsync()

Get offline status (reasons why printer is offline).

Task<ErrorStatus> GetErrorStatusAsync()

Get error status (recoverable, unrecoverable, cutter errors).

Task<PaperSensorStatus> GetPaperSensorStatusAsync()

Get paper sensor status (paper present, near end).

Task<string?> GetPrinterIdAsync()

Get printer model/ID string.

Task<OverallStatus> GetOverallStatusAsync()

Get comprehensive status with health assessment and recommendations.

Printing Methods

Task PrintTextAsync(string text)

Print text to the printer.

Task PrintTextAndCutAsync(string text, int feedLines = 5)

Print text, feed paper, and cut.

Task SendRawCommandAsync(byte[] command)

Send raw ESC/POS command bytes.

EpsonDiagnostics Class

Comprehensive diagnostics tool.

public EpsonDiagnostics(ILogger<EpsonDiagnostics>? logger = null)
Task<string> RunFullDiagnosticsAsync(string ip, int port = 9100, int timeoutSeconds = 5)

Run full diagnostic check and return formatted report.

Status Data Models

All status classes are immutable records with these common properties:

  • byte RawByte - Raw status byte from printer
  • string Binary - Binary representation (8 bits)
  • string Hex - Hexadecimal representation

PrinterStatus

  • bool DrawerOpen - Drawer kick-out connector pin 3 is HIGH
  • bool IsOnline - Printer is online
  • bool IsCoverClosed - Cover is closed
  • bool PaperFeedButtonPressed - Paper feed button is pressed

OfflineStatus

  • bool CoverOpen - Cover is open (offline reason)
  • bool PaperFeedButton - Paper feed button active (offline reason)
  • bool PaperEnd - Paper end detected (offline reason)
  • bool ErrorOccurred - Error occurred (offline reason)

ErrorStatus

  • bool RecoverableError - Recoverable error occurred
  • bool AutoCutterError - Auto-cutter error occurred
  • bool UnrecoverableError - Unrecoverable error occurred
  • bool AutoRecoveryError - Auto-recovery error occurred
  • bool HasError - True if any error is present

PaperSensorStatus

  • bool PaperNearEnd - Paper roll is near end
  • bool PaperPresent - Paper is present

OverallStatus

  • string? PrinterModel - Printer model/ID
  • PrinterStatus? PrinterStatus - General printer status
  • OfflineStatus? OfflineStatus - Offline status
  • ErrorStatus? ErrorStatus - Error status
  • PaperSensorStatus? PaperStatus - Paper sensor status
  • string StatusText - Overall status description
  • bool IsReady - True if printer is ready
  • List<string> Recommendations - List of recommendations
  • string StatusIcon - Status emoji (🟢/🟡/🟠/🔴/❓)

EpsonCommands Class

Static class containing ESC/POS command constants:

  • byte[] Initialize - Initialize printer (ESC @)
  • byte[] GetPrinterStatus - DLE EOT 1
  • byte[] GetOfflineStatus - DLE EOT 2
  • byte[] GetErrorStatus - DLE EOT 3
  • byte[] GetPaperSensorStatus - DLE EOT 4
  • byte[] GetPrinterId - GS I 1
  • byte[] CutPaperFull - Full paper cut (GS V 0)
  • byte[] CutPaperPartial - Partial paper cut (GS V 1)
  • byte[] FeedLines(byte lines) - Feed n lines (ESC d n)
  • byte[] LineFeed - Line feed (LF)

Exception Types

EpsonPrinterException

Base exception for all Epson printer errors.

EpsonConnectionException

Thrown when connection fails or is lost.

Properties:

  • string? PrinterIp - Printer IP address
  • int? PrinterPort - Printer port

EpsonCommandException

Thrown when a command fails.

Properties:

  • byte[]? Command - The command that failed

Troubleshooting

Connection Issues

Problem: Cannot connect to printer

Solutions:

  • Verify printer IP address is correct
  • Ensure printer is powered on
  • Check network connectivity (ping the printer)
  • Verify printer is on the same network
  • Check firewall settings
  • Ensure port 9100 is accessible

Timeout Errors

Problem: Operations timeout

Solutions:

  • Increase timeout parameter in ConnectAsync
  • Check printer is not busy with another job
  • Verify printer is not in an error state
  • Check network latency

Printer Offline

Problem: Printer shows as offline

Solutions:

  • Check cover is closed
  • Ensure paper is loaded
  • Clear any error conditions
  • Check offline status for specific reasons

Paper Issues

Problem: Paper not detected or near end

Solutions:

  • Load paper roll correctly
  • Ensure paper is feeding through sensor
  • Replace paper if near end
  • Check paper roll is compatible

Auto-Cutter Errors

Problem: Cutter error reported

Solutions:

  • Check for paper jams in cutter
  • Remove any obstructions
  • Open and close cover to reset
  • May require service if persistent

Technical Details

ESC/POS Protocol

This SDK uses ESC/POS commands via TCP/IP on port 9100. The DLE EOT (0x10 0x04) real-time status commands are used for status queries.

Status Byte Format

All status responses follow the format: 0xx1xx10b where:

  • Bit 7: Always 0
  • Bits 6,5,3,2: Status-specific flags
  • Bit 4: Always 1
  • Bits 1,0: Fixed pattern (10b)

Connection

  • Protocol: TCP/IP
  • Default Port: 9100
  • Character Encoding: UTF-8 for text, ASCII for responses
  • Timeout: Configurable (default 5 seconds)

License

Copyright Inspectron. All rights reserved.

Support

For issues, questions, or contributions, please contact the development team.