# 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:

```bash
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

```csharp
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

```csharp
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

```csharp
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

```csharp
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

```csharp
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

```csharp
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

```csharp
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

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

Creates a new printer instance with optional logging support.

#### Connection Methods

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

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

```csharp
void Disconnect()
```

Disconnect from the printer.

```csharp
bool IsConnected { get; }
```

Returns true if currently connected to the printer.

#### Status Query Methods

```csharp
Task<PrinterStatus> GetPrinterStatusAsync()
```

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

```csharp
Task<OfflineStatus> GetOfflineStatusAsync()
```

Get offline status (reasons why printer is offline).

```csharp
Task<ErrorStatus> GetErrorStatusAsync()
```

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

```csharp
Task<PaperSensorStatus> GetPaperSensorStatusAsync()
```

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

```csharp
Task<string?> GetPrinterIdAsync()
```

Get printer model/ID string.

```csharp
Task<OverallStatus> GetOverallStatusAsync()
```

Get comprehensive status with health assessment and recommendations.

#### Printing Methods

```csharp
Task PrintTextAsync(string text)
```

Print text to the printer.

```csharp
Task PrintTextAndCutAsync(string text, int feedLines = 5)
```

Print text, feed paper, and cut.

```csharp
Task SendRawCommandAsync(byte[] command)
```

Send raw ESC/POS command bytes.

### EpsonDiagnostics Class

Comprehensive diagnostics tool.

```csharp
public EpsonDiagnostics(ILogger<EpsonDiagnostics>? logger = null)
```

```csharp
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.
