oasira 0.2.9
Python API client for Oasira with Firebase OAuth support, designed for Home Assistant integrations
License: MIT
Requires Python: >=3.9
Keywords: oasira, home assistant, security, api, home automation

# Oasira Python API Client

A Python API client for Oasira home security systems, designed specifically for Home Assistant integrations.

## Features

- ✅ Async/await support using aiohttp
- ✅ Customer API integration (get customer info, system users, Firebase config)
- ✅ Security API integration (alarms, alerts, events)
- ✅ Type hints for better IDE support
- ✅ Comprehensive error handling
- ✅ Context manager support for proper session cleanup
- ✅ Detailed logging

## Installation

### From PyPI (once published)

```bash
pip install oasira
```

**Note:** This package distributes only compiled bytecode to protect the source code. The functionality is identical to a source distribution.

### From source

```bash
git clone https://github.com/yourusername/oasira.git
cd oasira
pip install -e .
```

## Quick Start

```python
import asyncio
from oasira import OasiraAPIClient

async def main():
    # Initialize the client with your credentials
    # Option 1: PSK-based authentication
    async with OasiraAPIClient(
        customer_id="your_customer_id",
        system_id="your_system_id",
        customer_psk="your_customer_psk",
        system_psk="your_system_psk"
    ) as client:
        # Get customer and system information
        info = await client.get_customer_and_system()
        print(f"System: {info}")
        
        # Get system users
        users = await client.get_system_users()
        print(f"Users: {users}")
        
        # Create a security alarm
        alarm_data = {
            "sensor_device_class": "door",
            "sensor_device_name": "Front Door",
            "sensor_state": "open"
        }
        response = await client.create_security_alarm(alarm_data)
        print(f"Alarm created: {response}")

asyncio.run(main())
```

### Firebase OAuth Authentication

```python
import asyncio
from oasira import OasiraAPIClient

#### Initialization

```python
client = OasiraAPIClient(
    customer_id="...",              # Optional: Customer ID
    system_id="...",                # Optional: System ID
    customer_psk="...",             # Optional: Customer PSK token
    system_psk="...",               # Optional: System PSK token
    firebase_token="...",           # Optional: Firebase ID token for OAuth
    firebase_refresh_token="...",   # Optional: Firebase refresh token
    session=None                    # Optional: Reuse existing aiohttp session
)
```

#### Authentication Methods

**PSK Authentication (Legacy):**
- Uses `customer_psk` and `system_psk` tokens
- Passed in custom headers (`eh_customer_id`, `eh_system_id`, `system_psk`)

**Firebase OAuth Authentication (Recommended):**
- Uses Firebase ID tokens
- Passed in standard `Authorization: Bearer {token}` header
- Supports token refresh
- More secure and standard OAuth 2.0 flow     # Authenticate with Firebase
        auth_result = await client.authenticate_with_firebase(
            email="your.email@example.com",
            password="your_password",
            api_key=api_key
        )
        
        # Token is now stored and automatically used in requests
        system_info = await client.get_customer_and_system()
        print(system_info)
        
        # Refresh token when needed
        await client.refresh_firebase_token(api_key)

asyncio.run(main())
```

### Using Existing Firebase Token

```python
# Initialize with existing Firebase token
async with OasiraAPIClient(
    customer_id="your_customer_id",
    system_id="your_system_id",
    firebase_token="your_firebase_id_token",
    firebase_refresh_token="your_refresh_token",
) as client:
    # Token is automatically included in Authorization header
    info = await client.get_customer_and_system()
```

## API Reference

### OasiraAPIClient

Main client for interacting with Oasira APIs.

#### Initialization

```python
client = OasiraAPIClient(
    customer_id="...",      # Optional: Customer ID
    system_id="...",        # Optional: System ID
    customer_psk="...",     # Optional: Customer PSK token
    system_psk="...",       # Optional: System PSK token
    session=None            # Optional: Reuse existing aiohttp session
)
```

#### Customer API Methods

- `get_customer_and_system()` - Get customer and system information
#### Firebase OAuth Methods

- `authenticate_with_firebase(email, password, api_key)` - Authenticate using Firebase email/password
- `refresh_firebase_token(api_key)` - Refresh Firebase ID token using refresh token
- `get_firebase_user_info()` - Get Firebase user information using current token

#### Utility Methods

- `update_credentials(customer_id, system_id, customer_psk, system_psk, firebase_token, firebase_refresh_token)` - Update API credentials
#### Security API Methods

- `create_security_alarm(alarm_data)` - Create a security alarm
- `create_monitoring_alarm(alarm_data)` - Create a monitoring alarm
- `create_medical_alarm(alarm_data)` - Create a medical alert alarm
- `create_event(alarm_id, event_data)` - Create a security event
- `create_alert(alert_data)` - Create a security alert
- `get_alarm_status(alarm_id)` - Get current alarm status
- `cancel_alarm(alarm_id)` - Cancel an active alarm
- `confirm_pending_alarm()` - Confirm a pending alarm

#### Utility Methods

- `update_credentials(customer_id, system_id, customer_psk, system_psk)` - Update API credentials

### Error Handling

```python
from oasira import OasiraAPIClient, OasiraAPIError

try:
    async with OasiraAPIClient(...) as client:
### Example Integration Usage

```python
"""Platform for Oasira integration."""
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
from oasira import OasiraAPIClient, OasiraAPIError

async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
    """Set up from a config entry."""
    
    # Option 1: PSK authentication
    client = OasiraAPIClient(
        customer_id=entry.data["customer_id"],
        system_id=entry.data["system_id"],
        customer_psk=entry.data["customer_psk"],
        system_psk=entry.data["system_psk"],
        session=hass.helpers.aiohttp_client.async_get_clientsession()
    )
    
    # Option 2: Firebase OAuth authentication
    # client = OasiraAPIClient(
    #     customer_id=entry.data["customer_id"],
    #     system_id=entry.data["system_id"],
    #     firebase_token=entry.data["firebase_token"],
    #     firebase_refresh_token=entry.data["firebase_refresh_token"],
    #     session=hass.helpers.aiohttp_client.async_get_clientsession()
    # )
```

### Example Integration Usage

```python
"""Platform for Oasira integration."""
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
from oasira import OasiraAPIClient, OasiraAPIError

async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
    """Set up from a config entry."""
    
    client = OasiraAPIClient(
        customer_id=entry.data["customer_id"],
        system_id=entry.data["system_id"],
        customer_psk=entry.data["customer_psk"],
        system_psk=entry.data["system_psk"],
        session=hass.helpers.aiohttp_client.async_get_clientsession()
    )
    
    # Verify credentials
    try:
        await client.get_customer_and_system()
    except OasiraAPIError as err:
        _LOGGER.error("Failed to authenticate: %s", err)
        return False
    
    hass.data.setdefault(DOMAIN, {})
    hass.data[DOMAIN][entry.entry_id] = client
    
    return True
```

### Coordinator Example

```python
"""DataUpdateCoordinator for Oasira."""
from datetime import timedelta
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
from oasira import OasiraAPIClient, OasiraAPIError

class OasiraCoordinator(DataUpdateCoordinator):
    """Class to manage fetching Oasira data."""

    def __init__(self, hass: HomeAssistant, client: OasiraAPIClient) -> None:
        """Initialize coordinator."""
        super().__init__(
            hass,
            logger=_LOGGER,
            name="Oasira",
            update_interval=timedelta(seconds=30),
        )
        self.client = client

    async def _async_update_data(self):
        """Fetch data from API."""
        try:
            return await self.client.get_customer_and_system()
        except OasiraAPIError as err:
            raise UpdateFailed(f"Error communicating with API: {err}") from err
```

## Development

### Setup Development Environment

```bash
# Clone the repository
git clone https://github.com/yourusername/oasira.git
cd oasira

# Install development dependencies
pip install -e ".[dev]"
```

### Running Tests

```bash
pytest
pytest --cov=oasira  # With coverage
```

### Code Formatting

```bash
# Format code
black oasira tests

# Sort imports
isort oasira tests

# Type checking
mypy oasira

# Linting
pylint oasira
```

## License

This project is licensed under the MIT License - see the LICENSE file for details.

## Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

## Support

For issues and questions, please use the [GitHub issue tracker](https://github.com/yourusername/oasira/issues).