npm package: @leonardojc/capacitor-serial-port
Description: Enhanced Capacitor plugin for serial port communication on Android devices with improved byte handling and ISO-8859-1 encoding support
Author: LeonardoJC Android
Latest version: 1.1.8

# Capacitor Serial Port Plugin

A comprehensive Capacitor plugin for serial port communication on Android devices.

## Install

```bash
npm install @leonardojc/capacitor-serial-port
npx cap sync
```

## Permissions

### Android

Add these permissions to your `android/app/src/main/AndroidManifest.xml`:

```xml
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
```

**Note:** This plugin requires root access on Android devices to access certain serial ports. Some ports like `/dev/ttyS2` may be accessible without root depending on device configuration.

## API

<docgen-index>

* [`listPorts()`](#listports)
* [`openPort(...)`](#openport)
* [`closePort()`](#closeport)
* [`writeData(...)`](#writedata)
* [`getStatus()`](#getstatus)
* [`setupPermissions(...)`](#setuppermissions)
* [`addListener('serialData', ...)`](#addlistenerserialdata)
* [`addListener('serialError', ...)`](#addlistenerserialerror)
* [`addListener('connectionChange', ...)`](#addlistenerconnectionchange)
* [`removeAllListeners()`](#removealllisteners)
* [Interfaces](#interfaces)

</docgen-index>

<docgen-api>
<!--Update the source file JSDoc comments and rerun docgen to update the docs below-->

### listPorts()

```typescript
listPorts() => Promise<ListPortsResult>
```

List available serial ports on the device

**Returns:** <code>Promise&lt;<a href="#listportsresult">ListPortsResult</a>&gt;</code>

**Since:** 1.0.0

----

### openPort(...)

```typescript
openPort(options: OpenPortOptions) => Promise<OpenPortResult>
```

Open connection to a serial port

| Param         | Type                                                      | Description                             |
| ------------- | --------------------------------------------------------- | --------------------------------------- |
| **`options`** | <code><a href="#openportoptions">OpenPortOptions</a></code> | Configuration for opening the port |

**Returns:** <code>Promise&lt;<a href="#openportresult">OpenPortResult</a>&gt;</code>

**Since:** 1.0.0

----

### closePort()

```typescript
closePort() => Promise<ClosePortResult>
```

Close the current serial port connection

**Returns:** <code>Promise&lt;<a href="#closeportresult">ClosePortResult</a>&gt;</code>

**Since:** 1.0.0

----

### writeData(...)

```typescript
writeData(options: WriteDataOptions) => Promise<WriteDataResult>
```

Write data to the serial port

| Param         | Type                                                        | Description      |
| ------------- | ----------------------------------------------------------- | ---------------- |
| **`options`** | <code><a href="#writedataoptions">WriteDataOptions</a></code> | Data to write |

**Returns:** <code>Promise&lt;<a href="#writedataresult">WriteDataResult</a>&gt;</code>

**Since:** 1.0.0

----

### getStatus()

```typescript
getStatus() => Promise<StatusResult>
```

Get current status of the serial port connection

**Returns:** <code>Promise&lt;<a href="#statusresult">StatusResult</a>&gt;</code>

**Since:** 1.0.0

----

### setupPermissions(...)

```typescript
setupPermissions(options: SetupPermissionsOptions) => Promise<SetupPermissionsResult>
```

Setup permissions for accessing the serial port (Android only)

| Param         | Type                                                                      | Description                         |
| ------------- | ------------------------------------------------------------------------- | ----------------------------------- |
| **`options`** | <code><a href="#setuppermissionsoptions">SetupPermissionsOptions</a></code> | Port path for permission setup |

**Returns:** <code>Promise&lt;<a href="#setuppermissionsresult">SetupPermissionsResult</a>&gt;</code>

**Since:** 1.0.0

----

### addListener('serialData', ...)

```typescript
addListener(eventName: 'serialData', listenerFunc: (event: SerialDataEvent) => void) => Promise<PluginListenerHandle>
```

Add a listener for serial data events

| Param              | Type                                                                        | Description                              |
| ------------------ | --------------------------------------------------------------------------- | ---------------------------------------- |
| **`eventName`**    | <code>'serialData'</code>                                                     | Name of the event to listen for    |
| **`listenerFunc`** | <code>(event: <a href="#serialdataevent">SerialDataEvent</a>) =&gt; void</code> | Function to call when event occurs |

**Returns:** <code>Promise&lt;<a href="#pluginlistenerhandle">PluginListenerHandle</a>&gt;</code>

**Since:** 1.0.0

----

### addListener('serialError', ...)

```typescript
addListener(eventName: 'serialError', listenerFunc: (event: SerialErrorEvent) => void) => Promise<PluginListenerHandle>
```

Add a listener for serial error events

| Param              | Type                                                                          | Description                              |
| ------------------ | ----------------------------------------------------------------------------- | ---------------------------------------- |
| **`eventName`**    | <code>'serialError'</code>                                                      | Name of the event to listen for    |
| **`listenerFunc`** | <code>(event: <a href="#serialerrorevent">SerialErrorEvent</a>) =&gt; void</code> | Function to call when event occurs |

**Returns:** <code>Promise&lt;<a href="#pluginlistenerhandle">PluginListenerHandle</a>&gt;</code>

**Since:** 1.0.0

----

### addListener('connectionChange', ...)

```typescript
addListener(eventName: 'connectionChange', listenerFunc: (event: ConnectionChangeEvent) => void) => Promise<PluginListenerHandle>
```

Add a listener for connection change events

| Param              | Type                                                                                      | Description                              |
| ------------------ | ----------------------------------------------------------------------------------------- | ---------------------------------------- |
| **`eventName`**    | <code>'connectionChange'</code>                                                              | Name of the event to listen for    |
| **`listenerFunc`** | <code>(event: <a href="#connectionchangeevent">ConnectionChangeEvent</a>) =&gt; void</code> | Function to call when event occurs |

**Returns:** <code>Promise&lt;<a href="#pluginlistenerhandle">PluginListenerHandle</a>&gt;</code>

**Since:** 1.0.0

----

### removeAllListeners()

```typescript
removeAllListeners() => Promise<void>
```

Remove all listeners for this plugin

**Since:** 1.0.0

----

### Interfaces

#### ListPortsResult

Result from listing ports operation

| Prop        | Type                        | Description                     | Since   |
| ----------- | --------------------------- | ------------------------------- | ------- |
| **`ports`** | <code>SerialPort[]</code> | Array of available serial ports | 1.0.0 |

#### SerialPort

Represents a serial port on the device

| Prop               | Type                 | Description                            | Since   |
| ------------------ | -------------------- | -------------------------------------- | ------- |
| **`path`**         | <code>string</code>  | Path to the serial port device file  | 1.0.0 |
| **`manufacturer`** | <code>string</code>  | Manufacturer information (if available) | 1.0.0 |
| **`serialNumber`** | <code>string</code>  | Serial number of the device (if available) | 1.0.0 |
| **`vendorId`**     | <code>string</code>  | Vendor ID (if available)              | 1.0.0 |
| **`productId`**    | <code>string</code>  | Product ID (if available)             | 1.0.0 |
| **`readable`**     | <code>boolean</code> | Whether the port is readable          | 1.0.0 |
| **`writable`**     | <code>boolean</code> | Whether the port is writable          | 1.0.0 |

#### OpenPortResult

Result from opening port operation

| Prop          | Type                 | Description                      | Since   |
| ------------- | -------------------- | -------------------------------- | ------- |
| **`success`** | <code>boolean</code> | Whether the operation was successful | 1.0.0 |
| **`message`** | <code>string</code>  | Message describing the result   | 1.0.0 |

#### OpenPortOptions

Options for opening a serial port connection

| Prop           | Type                                                         | Description                         | Default      | Since   |
| -------------- | ------------------------------------------------------------ | ----------------------------------- | ------------ | ------- |
| **`path`**     | <code>string</code>                                          | Path to the serial port device    |              | 1.0.0 |
| **`baudRate`** | <code>number</code>                                          | Baud rate for communication        | <code>9600</code> | 1.0.0 |
| **`dataBits`** | <code>number</code>                                          | Number of data bits                | <code>8</code>    | 1.0.0 |
| **`stopBits`** | <code>number</code>                                          | Number of stop bits                | <code>1</code>    | 1.0.0 |
| **`parity`**   | <code>'none' \| 'even' \| 'odd' \| 'mark' \| 'space'</code> | Parity setting                     | <code>'none'</code> | 1.0.0 |

#### ClosePortResult

Result from closing port operation

| Prop          | Type                 | Description                      | Since   |
| ------------- | -------------------- | -------------------------------- | ------- |
| **`success`** | <code>boolean</code> | Whether the operation was successful | 1.0.0 |
| **`message`** | <code>string</code>  | Message describing the result   | 1.0.0 |

#### WriteDataResult

Result from writing data operation

| Prop          | Type                 | Description                      | Since   |
| ------------- | -------------------- | -------------------------------- | ------- |
| **`success`** | <code>boolean</code> | Whether the operation was successful | 1.0.0 |
| **`message`** | <code>string</code>  | Message describing the result   | 1.0.0 |

#### WriteDataOptions

Options for writing data to serial port

| Prop       | Type                | Description                        | Since   |
| ---------- | ------------------- | ---------------------------------- | ------- |
| **`data`** | <code>string</code> | Data to write to the serial port | 1.0.0 |

#### StatusResult

Result from getting status operation

| Prop            | Type                 | Description                              | Since   |
| --------------- | -------------------- | ---------------------------------------- | ------- |
| **`connected`** | <code>boolean</code> | Whether a port is currently connected   | 1.0.0 |
| **`port`**      | <code>string</code>  | Path of the currently connected port    | 1.0.0 |

#### SetupPermissionsResult

Result from setting up permissions operation

| Prop          | Type                 | Description                      | Since   |
| ------------- | -------------------- | -------------------------------- | ------- |
| **`success`** | <code>boolean</code> | Whether the operation was successful | 1.0.0 |
| **`message`** | <code>string</code>  | Message describing the result   | 1.0.0 |

#### SetupPermissionsOptions

Options for setting up permissions

| Prop           | Type                | Description                     | Since   |
| -------------- | ------------------- | ------------------------------- | ------- |
| **`portPath`** | <code>string</code> | Path to the serial port device | 1.0.0 |

#### PluginListenerHandle

Plugin listener handle for removing listeners

| Prop         | Type                          | Description |
| ------------ | ----------------------------- | ----------- |
| **`remove`** | <code>() =&gt; Promise&lt;void&gt;</code> |        |

#### SerialDataEvent

Event fired when serial data is received

| Prop            | Type                | Description                     | Since   |
| --------------- | ------------------- | ------------------------------- | ------- |
| **`data`**      | <code>string</code> | The received data              | 1.0.0 |
| **`timestamp`** | <code>number</code> | Timestamp when data was received | 1.0.0 |

#### SerialErrorEvent

Event fired when a serial error occurs

| Prop          | Type                | Description   | Since   |
| ------------- | ------------------- | ------------- | ------- |
| **`message`** | <code>string</code> | Error message | 1.0.0 |
| **`code`**    | <code>string</code> | Error code    | 1.0.0 |

#### ConnectionChangeEvent

Event fired when connection status changes

| Prop            | Type                 | Description                  | Since   |
| --------------- | -------------------- | ---------------------------- | ------- |
| **`connected`** | <code>boolean</code> | Whether currently connected | 1.0.0 |
| **`port`**      | <code>string</code>  | Port path (if connected)    | 1.0.0 |

</docgen-api>

## Usage Example

```typescript
import { SerialPort } from '@leonardojc/capacitor-serial-port';

// List available ports  
const result = await SerialPort.listPorts();
console.log('Available ports:', result.ports);

// Setup permissions (Android only, requires root)
await SerialPort.setupPermissions({ portPath: '/dev/ttyS2' });

// Open port
await SerialPort.openPort({
  path: '/dev/ttyS2',
  baudRate: 9600,
  dataBits: 8,
  stopBits: 1,
  parity: 'none'
});

// Listen for data
SerialPort.addListener('serialData', (event) => {
  console.log('Received:', event.data);
});

// Listen for errors
SerialPort.addListener('serialError', (event) => {
  console.error('Serial error:', event.message);
});

// Listen for connection changes
SerialPort.addListener('connectionChange', (event) => {
  console.log('Connection changed:', event.connected);
});

// Send data
await SerialPort.writeData({ data: 'Hello Serial Port!' });

// Get status
const status = await SerialPort.getStatus();
console.log('Connected:', status.connected);

// Close port
await SerialPort.closePort();
```

## Platform Support

| Platform | Status |
|----------|--------|
| Android  | ✅     |
| iOS      | ❌     |
| Web      | ✅ (Mock) |

### Capacitor Version Support

| Plugin Version | Capacitor Version | Android API | Status |
|----------------|-------------------|-------------|--------|
| 1.1.x          | 7.x              | 24+         | ✅ Current |
| 1.0.x          | 6.x              | 22+         | ⚠️ Legacy |

## Requirements

- **Capacitor 7.0+**
- **Android API Level 24+** (Android 7.0+)
- **JDK 17+** for Android builds
- **Root access** (for most serial ports on Android)

## Common Serial Ports on Android

- `/dev/ttyS0`, `/dev/ttyS1`, `/dev/ttyS2`, `/dev/ttyS3` - System serial ports
- `/dev/ttyUSB0`, `/dev/ttyUSB1` - USB serial adapters  
- `/dev/ttyACM0`, `/dev/ttyACM1` - Arduino/CDC ACM devices

## Migration Guide

### From v1.0.x to v1.1.x (Capacitor 6 → 7)

1. **Update Capacitor to version 7**:
   ```bash
   npm install @capacitor/core@^7.0.0 @capacitor/android@^7.0.0
   ```

2. **Update the plugin**:
   ```bash
   npm install @leonardojc/capacitor-serial-port@^1.1.0
   ```

3. **Sync your project**:
   ```bash
   npx cap sync
   ```

4. **Update your Android project** (if needed):
   - Minimum SDK is now 24 (Android 7.0)
   - Target SDK is now 35 (Android 15)
   - Java 17+ is required

5. **Test thoroughly** - No API changes, but underlying platform updates may affect behavior

### Breaking Changes in v1.1.0
- Minimum Capacitor version: 6.x → 7.x
- Minimum Android SDK: 22 → 24
- Java compatibility: 11 → 17

## License

MIT

## Contributing

Contributions are welcome! Please read our contributing guidelines and submit pull requests to our repository.

## Support

If you encounter any issues or have questions, please open an issue on our GitHub repository.