unitapi 0.1.36
Real-Time Annotation and Stream Processing Interface
License: Apache-2.0
Requires Python: >=3.7.3
Keywords: python, unitapi, streaming, real-time, annotation, processing



# UnitAPI: Universal Hardware Interface as Network Devices [<span style='font-size:20px;'>&#x270D;</span>](git@github.com:UnitApi/python/edit/main/docs/index.md)

## Overview

UnitAPI (Unit Hardware API) is a comprehensive Python framework for managing and interacting with network-connected hardware devices across different platforms and protocols. It provides a unified, flexible, and secure approach to device communication and control.

## Key Features

### 1. Device Management
- Automatic device discovery
- Dynamic device registration
- Multi-protocol support
- Flexible device abstraction

### 2. Communication Protocols
- WebSocket
- MQTT
- Custom protocol extensions

### 3. Security
- Token-based authentication
- Encryption
- Access control
- Audit logging

### 4. Device Types
- Cameras
- Microphones
- Speakers
- GPIO Controllers
- Custom device implementations

## Architecture

### High-Level Architecture

```mermaid
graph TD
    A[Device Layer] --> B[Protocol Layer]
    B --> C[Core Framework]
    
    subgraph "Device Layer"
        A1[Device Types]
    end
    
    subgraph "Protocol Layer"
        B1[Protocols]
    end
    
    subgraph "Core Framework"
        C1[Server]
        C2[Client]
        C3[Security]
    end
```

### Component Diagram

```mermaid
graph TD
    Client[Client API] --> |Requests| Server[Server API]
    Server --> |Manages| Devices[Device Registry]
    Server --> |Uses| Security[Security Module]
    Server --> |Communicates via| Protocols[Protocol Handlers]
    Protocols --> |Connect to| Devices
    
    subgraph "Device Types"
        D1[Camera]
        D2[Microphone]
        D3[Speaker]
        D4[GPIO]
        D5[Input Devices]
    end
    
    Devices --> D1
    Devices --> D2
    Devices --> D3
    Devices --> D4
    Devices --> D5
```

### Device Inheritance Structure

```mermaid
classDiagram
    BaseDevice <|-- Camera
    BaseDevice <|-- Microphone
    BaseDevice <|-- Speaker
    BaseDevice <|-- GPIO
    BaseDevice <|-- InputDevice
    InputDevice <|-- Keyboard
    InputDevice <|-- Mouse
    InputDevice <|-- Touchscreen
    InputDevice <|-- Gamepad
    
    class BaseDevice {
        +device_id: str
        +device_type: str
        +metadata: dict
        +connect()
        +disconnect()
        +is_connected(): bool
    }
    
    class Camera {
        +capture_frame()
        +start_stream()
        +stop_stream()
    }
    
    class Microphone {
        +record_audio()
        +start_recording()
        +stop_recording()
    }
    
    class Speaker {
        +play_audio()
        +set_volume()
        +get_volume()
    }
```

### Communication Sequence

```mermaid
sequenceDiagram
    participant Client
    participant Server
    participant Device
    
    Client->>Server: Connect()
    Server-->>Client: Connection Established
    
    Client->>Server: List Devices()
    Server-->>Client: Available Devices
    
    Client->>Server: Connect to Device(device_id)
    Server->>Device: Establish Connection
    Device-->>Server: Connection Status
    Server-->>Client: Device Connected
    
    Client->>Server: Send Command(device_id, command, params)
    Server->>Device: Execute Command
    Device-->>Server: Command Result
    Server-->>Client: Command Response
    
    Client->>Server: Disconnect from Device(device_id)
    Server->>Device: Close Connection
    Device-->>Server: Disconnected
    Server-->>Client: Device Disconnected
    
    Client->>Server: Disconnect()
    Server-->>Client: Connection Closed
```

### Device Discovery Process

```mermaid
flowchart TD
    A[Start Discovery] --> B{Local Network Scan}
    B --> C[Find Devices]
    C --> D{For Each Device}
    D --> E[Query Device Info]
    E --> F{Supported Protocol?}
    F -->|Yes| G[Register Device]
    F -->|No| H[Skip Device]
    G --> I[Next Device]
    H --> I
    I --> J{More Devices?}
    J -->|Yes| D
    J -->|No| K[Discovery Complete]
```

### Device Connection Lifecycle

```mermaid
stateDiagram-v2
    [*] --> Disconnected
    Disconnected --> Connecting: connect()
    Connecting --> Connected: connection_established
    Connecting --> Error: connection_failed
    Connected --> Active: device_ready
    Active --> Idle: no_activity
    Idle --> Active: new_command
    Active --> Error: command_failed
    Error --> Reconnecting: auto_reconnect
    Reconnecting --> Connected: reconnection_successful
    Reconnecting --> Disconnected: reconnection_failed
    Connected --> Disconnecting: disconnect()
    Active --> Disconnecting: disconnect()
    Idle --> Disconnecting: disconnect()
    Disconnecting --> Disconnected: disconnection_complete
    Disconnected --> [*]
```

### Deployment Architecture

```mermaid
graph TD
    subgraph "Cloud Environment"
        CloudServer[Central Management Server]
        Database[(Device Registry DB)]
        CloudServer --- Database
    end
    
    subgraph "Local Network A"
        GatewayA[Local Gateway]
        DeviceA1[Camera]
        DeviceA2[Microphone]
        DeviceA3[Speaker]
        GatewayA --- DeviceA1
        GatewayA --- DeviceA2
        GatewayA --- DeviceA3
    end
    
    subgraph "Local Network B"
        GatewayB[Local Gateway]
        DeviceB1[GPIO Controller]
        DeviceB2[Input Devices]
        GatewayB --- DeviceB1
        GatewayB --- DeviceB2
    end
    
    subgraph "Remote Devices"
        RemoteDevice1[Remote Camera]
        RemoteDevice2[Remote Speaker]
    end
    
    CloudServer --- GatewayA
    CloudServer --- GatewayB
    CloudServer --- RemoteDevice1
    CloudServer --- RemoteDevice2
    
    Client1[Client Application] --- CloudServer
    Client2[Client Application] --- GatewayA
    Client3[Client Application] --- GatewayB
```

### Network Topology

```mermaid
graph TD
    subgraph "Internet"
        Cloud[Cloud Services]
    end
    
    subgraph "Home Network"
        Router[Home Router]
        Server[UnitAPI Server]
        Dev1[Camera]
        Dev2[Microphone]
        Dev3[Speaker]
        
        Router --- Server
        Server --- Dev1
        Server --- Dev2
        Server --- Dev3
    end
    
    subgraph "Remote Location"
        RemoteRouter[Remote Router]
        RemoteDev1[Remote Camera]
        RemoteDev2[Remote Microphone]
        
        RemoteRouter --- RemoteDev1
        RemoteRouter --- RemoteDev2
    end
    
    Cloud --- Router
    Cloud --- RemoteRouter
    
    Client[Client Application] --- Cloud
    LocalClient[Local Client] --- Server
```

### Implementation Timeline

```mermaid
gantt
    title UnitAPI Implementation Timeline
    dateFormat  YYYY-MM-DD
    
    section Planning
    Requirements Analysis      :a1, 2024-01-01, 14d
    Architecture Design        :a2, after a1, 21d
    
    section Development
    Core Framework            :d1, after a2, 30d
    Protocol Implementation   :d2, after d1, 21d
    Device Types              :d3, after d1, 28d
    Security Features         :d4, after d2, 14d
    
    section Testing
    Unit Testing              :t1, after d3, 14d
    Integration Testing       :t2, after t1, 14d
    Performance Testing       :t3, after t2, 7d
    
    section Deployment
    Documentation             :p1, after d4, 14d
    Example Creation          :p2, after p1, 7d
    Release                   :milestone, after t3, 0d
```

### Device Type Distribution

```mermaid
pie title Device Types in Typical Deployment
    "Cameras" : 25
    "Microphones" : 20
    "Speakers" : 20
    "Input Devices" : 15
    "GPIO Controllers" : 10
    "Custom Devices" : 10
```

### User Experience Journey

```mermaid
journey
    title UnitAPI User Experience
    section Discovery
      Find UnitAPI: 5: User
      Read Documentation: 3: User
      Evaluate Features: 4: User
    section Installation
      Install Package: 5: User, Developer
      Configure Environment: 3: Developer
      Test Installation: 4: Developer
    section Development
      Create Server: 5: Developer
      Register Devices: 4: Developer
      Implement Client: 3: Developer
    section Deployment
      Test in Production: 2: Developer, Admin
      Monitor Performance: 3: Admin
      Scale System: 4: Admin
    section Maintenance
      Update Framework: 3: Developer, Admin
      Add New Devices: 5: Developer
      Troubleshoot Issues: 2: Developer, Admin
```

## Quick Start

### Installation

```bash
pip install unitapi
```

#### Optional Protocol Support
```bash
# Install with specific protocol support
pip install unitapi[mqtt]
pip install unitapi[websocket]
```

### Basic Usage

#### Server Setup
```python
from unitapi.core.server import UnitAPIServer

# Create a server instance
server = UnitAPIServer(host='0.0.0.0', port=7890)

# Register a device
server.register_device(
    device_id='temp_sensor_01', 
    device_type='sensor',
    metadata={
        'location': 'living_room',
        'capabilities': ['temperature', 'humidity']
    }
)

# Start the server
server.start()
```

#### Client Interaction
```python
from unitapi.core.client import UnitAPIClient

# Create a client
client = UnitAPIClient(server_host='localhost', server_port=7890)

# List available devices
devices = client.list_devices()
print("Available Devices:", devices)
```

## Core Concepts

### 1. Devices
- Represent physical or virtual network-connected devices
- Provide a consistent interface for interaction
- Support custom device type creation

### 2. Protocols
- Abstraction layer for different communication methods
- Easy integration of new protocols
- Seamless device communication

### 3. Security
- Comprehensive authentication mechanisms
- Fine-grained access control
- Encryption of device communications

## Use Cases

- Smart Home Automation
- Industrial IoT
- Remote Monitoring
- Network Device Management
- Distributed Sensor Networks
- Remote Audio Control

## Documentation Sections

1. [Installation Guide](installation.md)
2. [Usage Guide](usage.md)
3. [Device Types](device_types.md)
4. [Protocols](protocols.md)
5. [Security](security.md)
6. [Examples](examples.md)
7. [Remote Speaker Agent](remote_speaker_agent.md)

## Contributing

We welcome contributions! Please read our [Contribution Guidelines](CONTRIBUTING.md) for details on how to get started.

## Support

- GitHub Issues: [UnitAPI Issues](https://github.com/UnitApi/python/issues)
- Email: support@unitapi.com

## License

UnitAPI is open-source software licensed under the MIT License.

## Version

Current Version: 0.1.5

## Compatibility

- Python 3.8+
- Supported Platforms:
  - Windows 10/11
  - macOS 10.15+
  - Linux (Ubuntu 20.04+, Debian 10+)
  - Raspberry Pi (Raspbian/Raspberry Pi OS)

## Performance Characteristics

- Low-latency device communication
- Minimal overhead
- Scalable architecture
- Async-first design

## Roadmap

### Upcoming Features
- Enhanced machine learning integration
- More device type support
- Advanced discovery mechanisms
- Cloud service integrations
- Improved remote device management

## Disclaimer

UnitAPI is an evolving project. While we strive for stability, 
the API may change in future versions.

## Acknowledgments

Thanks to all contributors and the open-source community 
for making this project possible.

# UnitAPI Device Types [<span style='font-size:20px;'>&#x270D;</span>](git@github.com:UnitApi/python/edit/main/docs/device_types.md)

UnitAPI supports various device types, each with its own capabilities and interfaces. This document provides detailed information about the built-in device types and how to create custom device types.

## Overview

UnitAPI's device abstraction layer provides a consistent interface for interacting with different types of hardware and virtual devices. Each device type inherits from the `BaseDevice` class and implements specific functionality relevant to that device category.

UnitAPI device types are organized into the following categories:
- **Sensor Devices**: Devices that capture data from the environment (cameras, microphones, etc.)
- **Output Devices**: Devices that produce output (speakers, displays, etc.)
- **Input Devices**: Devices that accept user input (mouse, keyboard, touchscreen, gamepad, etc.)
- **GPIO Devices**: Devices that interact with general-purpose input/output pins

## Built-in Device Types

### 1. Camera Devices

Camera devices provide interfaces for capturing images and video streams.

#### Features
- Image capture
- Video streaming
- Camera configuration (resolution, FPS)
- Connection management

#### Example Usage
```python
from unitapi.devices.camera import CameraDevice
import asyncio

async def main():
    # Create a camera device
    camera = CameraDevice(
        device_id='camera_01',
        name='Main Camera',
        metadata={
            'resolution': '1080p',
            'fps': 30,
            'location': 'front_door'
        }
    )
    
    # Connect to the camera
    await camera.connect()
    
    # Capture an image
    image_data = await camera.capture_image()
    print(f"Image captured: {image_data}")
    
    # Start a video stream
    stream_info = await camera.start_video_stream(duration=10)
    print(f"Stream started: {stream_info}")
    
    # Disconnect when done
    await camera.disconnect()

asyncio.run(main())
```

### 2. Microphone Devices

Microphone devices provide interfaces for recording audio.

#### Features
- Audio recording
- Sample rate and channel configuration
- Connection management

#### Example Usage
```python
from unitapi.devices.microphone import MicrophoneDevice
import asyncio

async def main():
    # Create a microphone device
    mic = MicrophoneDevice(
        device_id='mic_01',
        name='Desktop Microphone',
        metadata={
            'sample_rate': 44100,
            'channels': 2,
            'location': 'office'
        }
    )
    
    # Connect to the microphone
    await mic.connect()
    
    # Record audio
    audio_data = await mic.record_audio(duration=5, sample_rate=44100)
    print(f"Audio recorded: {audio_data}")
    
    # Disconnect when done
    await mic.disconnect()

asyncio.run(main())
```

### 3. GPIO Devices

GPIO (General Purpose Input/Output) devices provide interfaces for controlling digital pins, typically on devices like Raspberry Pi.

#### Features
- Pin mode configuration (input/output)
- Digital read/write operations
- PWM (Pulse Width Modulation) control
- Connection management

#### Example Usage
```python
from unitapi.devices.gpio import GPIODevice
import asyncio

async def main():
    # Create GPIO device
    gpio = GPIODevice(
        device_id='rpi_gpio_01', 
        name='Raspberry Pi GPIO',
        metadata={'total_pins': 40}
    )
    
    # Connect to the GPIO device
    await gpio.connect()
    
    # Set pin mode and control
    await gpio.set_pin_mode(18, 'output')
    await gpio.digital_write(18, True)
    
    # Read from a pin
    await gpio.set_pin_mode(17, 'input')
    pin_value = await gpio.digital_read(17)
    print(f"Pin 17 value: {pin_value}")
    
    # PWM control
    await gpio.set_pin_mode(12, 'output')
    await gpio.pwm_write(12, 0.5)  # 50% duty cycle
    
    # Disconnect when done
    await gpio.disconnect()

asyncio.run(main())
```

### 4. Speaker Devices

Speaker devices provide interfaces for playing audio.

#### Features
- Audio playback
- Volume control
- Audio format configuration
- Connection management

#### Example Usage
```python
from unitapi.devices.remote_speaker_device import RemoteSpeakerDevice
import asyncio

async def main():
    # Create a speaker device
    speaker = RemoteSpeakerDevice(
        device_id='speaker_01',
        name='Living Room Speaker',
        metadata={
            'sample_rate': 44100,
            'channels': 2,
            'location': 'living_room'
        }
    )
    
    # Connect to the speaker
    await speaker.connect()
    
    # Play audio
    await speaker.play_audio('path/to/audio.wav')
    
    # Play a test tone
    await speaker.play_test_tone(frequency=440, duration=2.0)
    
    # Disconnect when done
    await speaker.disconnect()

asyncio.run(main())
```

### 5. Mouse Devices

Mouse devices provide interfaces for controlling cursor movement and button actions.

#### Features
- Cursor movement (absolute and relative)
- Button actions (click, double-click, press, release)
- Scrolling
- Drag operations
- Connection management

#### Example Usage
```python
from unitapi.devices import MouseDevice
import asyncio

async def main():
    # Create a mouse device
    mouse = MouseDevice(
        device_id='mouse_01',
        name='Virtual Mouse',
        metadata={'dpi': 1200}
    )
    
    # Connect to the mouse
    await mouse.connect()
    
    # Move the mouse to an absolute position
    await mouse.move_to(500, 300)
    
    # Perform a left click
    await mouse.click()
    
    # Perform a right click
    await mouse.click(button="right")
    
    # Perform a drag operation
    await mouse.drag(700, 400)
    
    # Scroll the mouse wheel
    await mouse.scroll(5)  # Scroll up
    
    # Disconnect when done
    await mouse.disconnect()

asyncio.run(main())
```

### 6. Keyboard Devices

Keyboard devices provide interfaces for simulating keyboard input.

#### Features
- Key press and release
- Text typing
- Hotkey combinations
- Modifier key support
- Connection management

#### Example Usage
```python
from unitapi.devices import KeyboardDevice
import asyncio

async def main():
    # Create a keyboard device
    keyboard = KeyboardDevice(
        device_id='keyboard_01',
        name='Virtual Keyboard',
        metadata={'layout': 'us'}
    )
    
    # Connect to the keyboard
    await keyboard.connect()
    
    # Type some text
    await keyboard.type_text("Hello, UnitAPI!")
    
    # Press individual keys
    await keyboard.press_key("a")
    
    # Press a hotkey combination (Ctrl+C)
    await keyboard.press_hotkey("ctrl", "c")
    
    # Disconnect when done
    await keyboard.disconnect()

asyncio.run(main())
```

### 7. Touchscreen Devices

Touchscreen devices provide interfaces for simulating touch input.

#### Features
- Single and multi-touch support
- Tap and double-tap gestures
- Swipe gestures
- Pinch gestures (zoom in/out)
- Rotation gestures
- Connection management

#### Example Usage
```python
from unitapi.devices import TouchscreenDevice
import asyncio

async def main():
    # Create a touchscreen device
    touchscreen = TouchscreenDevice(
        device_id='touchscreen_01',
        name='Virtual Touchscreen',
        metadata={
            'width': 1920,
            'height': 1080,
            'multi_touch': True
        }
    )
    
    # Connect to the touchscreen
    await touchscreen.connect()
    
    # Perform a tap
    await touchscreen.tap(500, 300)
    
    # Perform a swipe
    await touchscreen.swipe(200, 500, 800, 500, duration=0.5)
    
    # Perform a pinch (zoom out)
    await touchscreen.pinch(
        center_x=960,
        center_y=540,
        start_distance=200,
        end_distance=100,
        duration=0.5
    )
    
    # Disconnect when done
    await touchscreen.disconnect()

asyncio.run(main())
```

### 8. Gamepad Devices

Gamepad devices provide interfaces for simulating game controller input.

#### Features
- Button press and release
- Analog trigger control
- Analog stick movement
- Vibration/rumble control
- Controller state management
- Connection management

#### Example Usage
```python
from unitapi.devices import GamepadDevice
import asyncio

async def main():
    # Create a gamepad device
    gamepad = GamepadDevice(
        device_id='gamepad_01',
        name='Virtual Gamepad',
        metadata={'controller_type': 'xbox'}
    )
    
    # Connect to the gamepad
    await gamepad.connect()
    
    # Press buttons
    await gamepad.press_button("a")
    await gamepad.press_button("b")
    
    # Set trigger values
    await gamepad.set_trigger("left_trigger", 0.5)
    
    # Move analog sticks
    await gamepad.move_stick("left_stick", 0.5, 0.0)  # Move right
    
    # Set vibration/rumble
    await gamepad.set_vibration(left_motor=0.7, right_motor=0.3)
    
    # Get current gamepad state
    state = await gamepad.get_state()
    print(f"Gamepad state: {state}")
    
    # Disconnect when done
    await gamepad.disconnect()

asyncio.run(main())
```

## Creating Custom Device Types

You can create custom device types by inheriting from the `BaseDevice` class or one of its subclasses.

### Basic Custom Device

```python
from unitapi.devices.base import BaseDevice, DeviceStatus
import asyncio
import logging

class CustomDevice(BaseDevice):
    """Custom device implementation."""
    
    def __init__(self, device_id: str, name: str, metadata=None):
        """Initialize custom device."""
        super().__init__(
            device_id=device_id,
            name=name,
            device_type="custom",
            metadata=metadata or {}
        )
        self.logger = logging.getLogger(__name__)
    
    async def connect(self) -> bool:
        """Connect to the device."""
        try:
            # Custom connection logic
            await asyncio.sleep(1)  # Simulate connection delay
            self.status = DeviceStatus.ONLINE
            self.logger.info(f"Device {self.device_id} connected")
            return True
        except Exception as e:
            self.status = DeviceStatus.ERROR
            self.logger.error(f"Connection failed: {e}")
            return False
    
    async def disconnect(self) -> bool:
        """Disconnect from the device."""
        try:
            # Custom disconnection logic
            await asyncio.sleep(0.5)  # Simulate disconnection delay
            self.status = DeviceStatus.OFFLINE
            self.logger.info(f"Device {self.device_id} disconnected")
            return True
        except Exception as e:
            self.logger.error(f"Disconnection failed: {e}")
            return False
    
    async def execute_command(self, command: str, params=None) -> dict:
        """Execute a command on the device."""
        try:
            if command == "custom_command":
                # Implement custom command logic
                return {"status": "success", "result": "Custom command executed"}
            else:
                raise ValueError(f"Unsupported command: {command}")
        except Exception as e:
            self.logger.error(f"Command execution failed: {e}")
            return {"error": str(e)}
```

### Custom Sensor Device

```python
from unitapi.devices.base import SensorDevice
import asyncio
import random
import logging

class TemperatureSensor(SensorDevice):
    """Temperature sensor implementation."""
    
    def __init__(self, device_id: str, name: str, metadata=None):
        """Initialize temperature sensor."""
        super().__init__(
            device_id=device_id,
            name=name,
            device_type="temperature_sensor",
            metadata=metadata or {}
        )
        self.logger = logging.getLogger(__name__)
        self.min_temp = metadata.get("min_temp", 15.0) if metadata else 15.0
        self.max_temp = metadata.get("max_temp", 30.0) if metadata else 30.0
    
    async def read_sensor(self) -> dict:
        """Read temperature data."""
        try:
            # Simulate temperature reading
            await asyncio.sleep(0.5)
            temperature = random.uniform(self.min_temp, self.max_temp)
            
            return {
                "device_id": self.device_id,
                "timestamp": asyncio.get_event_loop().time(),
                "temperature": round(temperature, 1),
                "unit": "°C"
            }
        except Exception as e:
            self.logger.error(f"Sensor reading failed: {e}")
            return {"error": str(e)}
```

## Device Registration

Once you've created a device, you need to register it with the UnitAPI server:

```python
from unitapi.core.server import UnitAPIServer
import asyncio

async def main():
    # Create a server
    server = UnitAPIServer(host='0.0.0.0', port=7890)
    
    # Create a custom device
    custom_device = CustomDevice(
        device_id='custom_01',
        name='My Custom Device',
        metadata={'capability': 'custom_function'}
    )
    
    # Register the device
    server.register_device(
        device_id=custom_device.device_id,
        device_type=custom_device.type,
        metadata=custom_device.metadata
    )
    
    # Start the server
    await server.start()

asyncio.run(main())
```

## Device Discovery

UnitAPI provides a device discovery mechanism that can automatically detect and register devices:

```python
from examples.device_discovery import DeviceDiscoveryService
import asyncio

async def main():
    # Create a discovery service
    discovery = DeviceDiscoveryService(
        server_host='0.0.0.0',
        server_port=7890,
        discovery_port=7891,
        debug=True
    )
    
    # Discover devices
    devices = await discovery.discover_devices()
    print(f"Discovered {len(devices)} devices")
    
    # Start the discovery service
    await discovery.start()

asyncio.run(main())
```

## Best Practices

1. **Asynchronous Operations**: Always use `async`/`await` for device operations to ensure non-blocking behavior.
2. **Error Handling**: Implement proper error handling in all device methods.
3. **Logging**: Use the logging module to provide informative logs for debugging.
4. **Status Management**: Keep the device status updated (`ONLINE`, `OFFLINE`, `ERROR`, `BUSY`).
5. **Resource Cleanup**: Ensure proper cleanup in the `disconnect` method.
6. **Metadata**: Use metadata to store device-specific configuration and capabilities.
7. **Command Interface**: Implement a consistent command interface through the `execute_command` method.

 [<span style='font-size:20px;'>&#x270D;</span>](git@github.com:UnitApi/python/edit/main/docs/footer.mddocs/device_types.md)


# UnitAPI Installation Guide [<span style='font-size:20px;'>&#x270D;</span>](git@github.com:UnitApi/python/edit/main/docs/installation.md)

## Prerequisites

- Python 3.8+
- pip package manager

## Installation Methods

### 1. pip Installation (Recommended)

```bash
pip install unitapi
```

### 2. Optional Protocol Support

```bash
# Install with MQTT support
pip install unitapi[mqtt]

# Install with WebSocket support
pip install unitapi[websocket]
```

### 3. From Source

```bash
# Clone the repository
git clone https://github.com/UnitApi/python.git
cd unitapi

# Install dependencies
pip install -r requirements.txt

# Install the package
pip install .
```

## Verification

To verify the installation, run:

```bash
python -c "import unitapi; print(unitapi.__version__)"
```

## Dependencies

### Core Dependencies
- `asyncio`
- `pydantic`
- `cryptography`
- `python-jose`

### Optional Dependencies
- `paho-mqtt` (for MQTT support)
- `websockets` (for WebSocket support)
- `pyaudio` (for audio device support)
- `opencv-python` (for camera support)

## Troubleshooting

### Common Installation Issues

1. **Python Version Compatibility**
   - Ensure you're using Python 3.8 or newer
   - Use `python3 -m pip install unitapi` if multiple Python versions are installed

2. **Permission Issues**
   - On Unix-like systems, use `sudo pip install unitapi` 
   - Recommended: Use virtual environments

3. **Dependency Conflicts**
   - Create a virtual environment before installation
   ```bash
   python3 -m venv unitapi_env
   source unitapi_env/bin/activate  # On Windows: unitapi_env\Scripts\activate
   pip install unitapi
   ```

4. **PyAudio Installation Issues**
   - On Linux, you may need to install PortAudio development headers:
   ```bash
   sudo apt-get install portaudio19-dev
   pip install pyaudio
   ```
   - On macOS, you can use Homebrew:
   ```bash
   brew install portaudio
   pip install pyaudio
   ```
   - On Windows, you might need to install a pre-built wheel:
   ```bash
   pip install pipwin
   pipwin install pyaudio
   ```

## Development Installation

For contributors and developers:

```bash
# Clone the repository
git clone https://github.com/UnitApi/python.git
cd unitapi

# Create virtual environment
python3 -m venv venv
source venv/bin/activate  # Activate virtual environment

# Install development dependencies
pip install -r requirements.txt
pip install -r requirements-dev.txt

# Install the package in editable mode
pip install -e .
```

## System-Specific Notes

### Raspberry Pi
- Ensure `python3-dev` package is installed
```bash
sudo apt-get update
sudo apt-get install python3-dev
pip install unitapi
```

### Docker
```dockerfile
FROM python:3.9-slim

# Install UnitAPI
RUN pip install unitapi

# Optional: Install additional protocol support
RUN pip install unitapi[mqtt,websocket]
```

## Updating UnitAPI

```bash
# Upgrade to latest version
pip install --upgrade unitapi

# Upgrade with specific protocol support
pip install --upgrade unitapi[mqtt]
```

## Uninstallation

```bash
pip uninstall unitapi
```

## Remote Speaker Agent Installation

For installing the Remote Speaker Agent on a remote machine, see the [Remote Speaker Agent documentation](remote_speaker_agent.md).

### Quick Remote Installation

```bash
# Install on a remote machine via SSH
scripts/install_remote_speaker_agent_via_ssh.sh remote-host [remote-user]

# Example:
scripts/install_remote_speaker_agent_via_ssh.sh 192.168.1.100 pi

# UnitAPI Protocols [<span style='font-size:20px;'>&#x270D;</span>](git@github.com:UnitApi/python/edit/main/docs/protocols.md)

UnitAPI supports multiple communication protocols for device interaction. This document provides detailed information about the built-in protocols and how to implement custom protocols.

## Overview

The protocol layer in UnitAPI provides an abstraction for different communication methods, allowing devices to communicate regardless of the underlying protocol. This enables seamless integration of devices that use different communication standards.

## Built-in Protocols

### 1. WebSocket Protocol

The WebSocket protocol provides real-time, bidirectional communication between clients and servers. It's ideal for applications that require low-latency, high-frequency updates.

#### Features
- Real-time bidirectional communication
- Message-based data exchange
- Support for both client and server roles
- Custom message handlers

#### Example Usage (Client)
```python
from unitapi.protocols.websocket import WebSocketProtocol
import asyncio

async def main():
    # Create WebSocket protocol handler
    ws_client = WebSocketProtocol(host='localhost', port=8765)
    
    # Connect to WebSocket server
    await ws_client.connect()
    
    # Define a message handler
    async def handle_temperature_data(data):
        print(f"Received temperature: {data}")
    
    # Register the message handler
    ws_client.add_message_handler('temperature_data', handle_temperature_data)
    
    # Send a message
    await ws_client.send('device_command', {
        'device_id': 'sensor_01',
        'command': 'read_temperature'
    })
    
    # Wait for some time to receive messages
    await asyncio.sleep(10)
    
    # Disconnect when done
    await ws_client.disconnect()

asyncio.run(main())
```

#### Example Usage (Server)
```python
from unitapi.protocols.websocket import WebSocketProtocol
import asyncio

async def main():
    # Create WebSocket protocol handler
    ws_server = WebSocketProtocol(host='0.0.0.0', port=8765)
    
    # Start WebSocket server
    await ws_server.create_server()
    
    # The server will handle incoming connections and messages automatically
    # based on the internal _handle_client and _process_message methods

asyncio.run(main())
```

### 2. MQTT Protocol

MQTT (Message Queuing Telemetry Transport) is a lightweight publish-subscribe messaging protocol designed for constrained devices and low-bandwidth, high-latency networks. It's ideal for IoT applications.

#### Features
- Publish-subscribe messaging pattern
- Quality of Service (QoS) levels
- Retained messages
- Last Will and Testament (LWT)

#### Example Usage
```python
from unitapi.protocols.mqtt import MQTTProtocol
import asyncio

async def main():
    # Create MQTT protocol handler
    mqtt_client = MQTTProtocol(broker='localhost', port=1883)
    
    # Connect to MQTT broker
    await mqtt_client.connect()
    
    # Define a message handler
    def handle_temperature_data(topic, payload):
        print(f"Received temperature on {topic}: {payload}")
    
    # Subscribe to a topic
    await mqtt_client.subscribe('unitapi/devices/+/temperature')
    
    # Register the message handler
    mqtt_client.add_message_handler('unitapi/devices/+/temperature', handle_temperature_data)
    
    # Publish a message
    await mqtt_client.publish('unitapi/devices/sensor_01/temperature', '22.5')
    
    # Wait for some time to receive messages
    await asyncio.sleep(10)
    
    # Disconnect when done
    await mqtt_client.disconnect()

asyncio.run(main())
```

## Protocol Selection

UnitAPI allows you to choose the appropriate protocol based on your application's requirements:

```python
from unitapi.core.server import UnitAPIServer
from unitapi.protocols.websocket import WebSocketProtocol
from unitapi.protocols.mqtt import MQTTProtocol
import asyncio

async def main():
    # Create a server
    server = UnitAPIServer(host='0.0.0.0', port=7890)
    
    # Create protocol handlers
    websocket = WebSocketProtocol(host='0.0.0.0', port=8765)
    mqtt = MQTTProtocol(broker='localhost', port=1883)
    
    # Start the server and protocols
    server_task = asyncio.create_task(server.start())
    websocket_task = asyncio.create_task(websocket.create_server())
    
    # Connect MQTT client
    await mqtt.connect()
    
    # Wait for all tasks
    await asyncio.gather(server_task, websocket_task)

asyncio.run(main())
```

## Creating Custom Protocols

You can create custom protocols by implementing the necessary methods for your specific communication needs.

### Basic Custom Protocol

```python
import asyncio
import logging
from typing import Dict, Any, Callable

class CustomProtocol:
    """Custom protocol implementation."""
    
    def __init__(self, host: str, port: int):
        """Initialize custom protocol."""
        self.host = host
        self.port = port
        self.logger = logging.getLogger(__name__)
        self._message_handlers = {}
        self._connected = False
    
    async def connect(self) -> bool:
        """Connect to the custom protocol server."""
        try:
            # Implement custom connection logic
            await asyncio.sleep(1)  # Simulate connection delay
            self._connected = True
            self.logger.info(f"Connected to {self.host}:{self.port}")
            return True
        except Exception as e:
            self.logger.error(f"Connection failed: {e}")
            return False
    
    async def disconnect(self) -> bool:
        """Disconnect from the custom protocol server."""
        try:
            # Implement custom disconnection logic
            await asyncio.sleep(0.5)  # Simulate disconnection delay
            self._connected = False
            self.logger.info(f"Disconnected from {self.host}:{self.port}")
            return True
        except Exception as e:
            self.logger.error(f"Disconnection failed: {e}")
            return False
    
    async def send(self, message_type: str, data: Dict[str, Any]) -> bool:
        """Send a message via the custom protocol."""
        try:
            if not self._connected:
                raise ConnectionError("Not connected")
            
            # Implement custom message sending logic
            self.logger.info(f"Sending message: {message_type}")
            
            # Simulate message sending
            await asyncio.sleep(0.2)
            
            return True
        except Exception as e:
            self.logger.error(f"Message sending failed: {e}")
            return False
    
    def add_message_handler(self, message_type: str, handler: Callable) -> None:
        """Register a handler for specific message types."""
        self._message_handlers[message_type] = handler
        self.logger.info(f"Registered handler for message type: {message_type}")
    
    async def create_server(self) -> None:
        """Create a server for the custom protocol."""
        try:
            # Implement custom server creation logic
            self.logger.info(f"Starting server on {self.host}:{self.port}")
            
            # Simulate server running
            while True:
                await asyncio.sleep(1)
        except Exception as e:
            self.logger.error(f"Server creation failed: {e}")
```

## Protocol Interoperability

UnitAPI's protocol abstraction allows devices to communicate regardless of the underlying protocol. This is achieved through a common message format and protocol-specific adapters.

### Example: Cross-Protocol Communication

```python
from unitapi.core.server import UnitAPIServer
from unitapi.protocols.websocket import WebSocketProtocol
from unitapi.protocols.mqtt import MQTTProtocol
import asyncio

async def main():
    # Create a server
    server = UnitAPIServer(host='0.0.0.0', port=7890)
    
    # Create protocol handlers
    websocket = WebSocketProtocol(host='0.0.0.0', port=8765)
    mqtt = MQTTProtocol(broker='localhost', port=1883)
    
    # Connect protocols
    await websocket.connect()
    await mqtt.connect()
    
    # Define a message handler that bridges protocols
    async def bridge_temperature_data(data):
        # When temperature data is received via WebSocket,
        # republish it via MQTT
        if 'temperature' in data:
            device_id = data.get('device_id', 'unknown')
            temperature = data.get('temperature')
            await mqtt.publish(f'unitapi/devices/{device_id}/temperature', str(temperature))
    
    # Register the bridge handler
    websocket.add_message_handler('temperature_data', bridge_temperature_data)
    
    # Start the server
    await server.start()

asyncio.run(main())
```

## Best Practices

1. **Protocol Selection**: Choose the appropriate protocol based on your application's requirements:
   - WebSocket for real-time, bidirectional communication
   - MQTT for lightweight, publish-subscribe messaging in IoT applications

2. **Error Handling**: Implement proper error handling for connection, disconnection, and message sending/receiving.

3. **Message Handlers**: Use message handlers to process incoming messages asynchronously.

4. **Connection Management**: Ensure proper connection and disconnection to avoid resource leaks.

5. **Security**: Consider security implications when selecting and implementing protocols:
   - Use secure variants (WSS for WebSocket, MQTTS for MQTT)
   - Implement authentication and authorization
   - Encrypt sensitive data

6. **Logging**: Use the logging module to provide informative logs for debugging.

7. **Asynchronous Operations**: Always use `async`/`await` for protocol operations to ensure non-blocking behavior.

# UnitAPI Security [<span style='font-size:20px;'>&#x270D;</span>](git@github.com:UnitApi/python/edit/main/docs/security.md)

UnitAPI provides comprehensive security features to protect device communications and ensure proper access control. This document outlines the security mechanisms available in UnitAPI and best practices for securing your applications.

## Overview

Security is a critical aspect of any IoT or device management system. UnitAPI implements several security layers to protect against unauthorized access, data breaches, and other security threats.

## Authentication

UnitAPI provides a flexible authentication system that supports various authentication methods.

### Token-based Authentication

```python
from unitapi.security.authentication import AuthenticationManager
import asyncio

async def main():
    # Create authentication manager
    auth_manager = AuthenticationManager()