# SOME/IP Driver

`jumpstarter-driver-someip` provides SOME/IP (Scalable service-Oriented Middleware over IP)
protocol operations for Jumpstarter. This driver wraps the
[opensomeip](https://github.com/vtz/opensomeip-python) Python binding to enable remote
RPC calls, service discovery, raw messaging, and event subscriptions with automotive
ECUs over Ethernet.

## Installation

```shell
pip3 install --extra-index-url https://pkg.jumpstarter.dev/simple/ jumpstarter-driver-someip
```

## Configuration

| Parameter         | Type        | Default       | Description                                           |
|-------------------|-------------|---------------|-------------------------------------------------------|
| `host`            | str         | required      | Local IP address to bind                              |
| `port`            | int         | 30490         | Local SOME/IP port                                    |
| `transport_mode`  | str         | `UDP`         | Transport protocol: `UDP` or `TCP`                    |
| `multicast_group` | str         | `239.127.0.1` | SD multicast group address                            |
| `multicast_port`  | int         | 30490         | SD multicast port                                     |
| `remote_host`     | str \| None | `None`        | Remote ECU IP for static routing (bypasses SD)        |
| `remote_port`     | int \| None | `None`        | Remote ECU port (defaults to `port` when `remote_host` is set) |

### UDP (default)

```yaml
export:
  someip:
    type: jumpstarter_driver_someip.driver.SomeIp
    config:
      host: "192.168.1.100"
      port: 30490
      transport_mode: UDP
      multicast_group: "239.127.0.1"
      multicast_port: 30490
```

### TCP

```yaml
export:
  someip:
    type: jumpstarter_driver_someip.driver.SomeIp
    config:
      host: "192.168.1.100"
      port: 30490
      transport_mode: TCP
```

### Static remote endpoint (no Service Discovery)

When the target ECU does not run SOME/IP-SD (e.g. Zephyr firmware with
multicast TX disabled), set `remote_host` and optionally `remote_port`
to send messages directly without Service Discovery:

```yaml
export:
  someip:
    type: jumpstarter_driver_someip.driver.SomeIp
    config:
      host: "192.168.100.1"
      port: 30490
      transport_mode: UDP
      remote_host: "192.168.100.10"
      remote_port: 30490
```

## Usage

### RPC Call

```python
from jumpstarter.common.utils import env

with env() as client:
    someip = client.someip

    response = someip.rpc_call(0x1234, 0x0001, b"\x01\x02\x03")
    print(f"Response: {bytes.fromhex(response.payload)}")
    print(f"Return code: {response.return_code}")
```

### Service Discovery + RPC

```python
from jumpstarter.common.utils import env

with env() as client:
    someip = client.someip

    # Discover available services
    services = someip.find_service(0x1234, timeout=3.0)
    for svc in services:
        print(f"Found: service={svc.service_id:#06x} instance={svc.instance_id:#06x}")

    # Call the first discovered service
    if services:
        resp = someip.rpc_call(0x1234, 0x0001, b"\x10\x20")
        print(f"RPC result: {resp.payload}")
```

### Event Subscription

```python
from jumpstarter.common.utils import env

with env() as client:
    someip = client.someip

    # Subscribe to event group 1
    someip.subscribe_eventgroup(1)

    # Wait for event notifications
    try:
        event = someip.receive_event(timeout=10.0)
        print(f"Event service={event.service_id:#06x} id={event.event_id:#06x}")
        print(f"Payload: {bytes.fromhex(event.payload)}")
    finally:
        someip.unsubscribe_eventgroup(1)
```

### Raw Messaging

```python
from jumpstarter.common.utils import env

with env() as client:
    someip = client.someip

    someip.send_message(0x1234, 0x0001, b"\xAA\xBB")
    msg = someip.receive_message(timeout=2.0)
    print(f"Received from service={msg.service_id:#06x}: {msg.payload}")
```

### Connection Management

```python
from jumpstarter.common.utils import env

with env() as client:
    someip = client.someip

    # Perform operations...
    someip.rpc_call(0x1234, 0x0001, b"\x01")

    # Reconnect after network disruption
    someip.reconnect()

    # Continue operations
    someip.rpc_call(0x1234, 0x0001, b"\x02")

    # Clean up
    someip.close_connection()
```

## API Reference

```{eval-rst}
.. autoclass:: jumpstarter_driver_someip.driver.SomeIp()
```
