Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions src/viam/app/client.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
from typing_extensions import Self

from grpclib.client import Channel

from viam.rpc.dial import DialOptions, _dial_app, _get_access_token
from viam import logging
from viam.app.data.client import DataClient

LOGGER = logging.getLogger(__name__)


class AppClient:
"""gRPC client for all communication and interaction with app.

Use create() to instantiate an AppClient::

AppClient.create(...)
"""

@classmethod
async def create(cls, dial_options: DialOptions) -> Self:
"""
Create an app client that establishes a connection to app.viam.com.

Args:
dial_options (DialOptions): Required information for authorization and connection to app, creds and auth_entity are necessary.

Returns:
Self: the AppClient.
"""
self = cls()
self._channel = await _dial_app(dial_options)
access_token = await _get_access_token(self._channel, dial_options.auth_entity, dial_options)
self._metadata = {"authorization": f"Bearer {access_token}"}
return self

_channel: Channel
_metadata: str
_closed: bool = False

@property
def data_client(self) -> DataClient:
return DataClient(self._channel, self._metadata)

async def close(self):
raise NotImplementedError()
100 changes: 100 additions & 0 deletions src/viam/app/data/client.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
from typing import List, Optional, Mapping, Any

from grpclib.client import Channel

from viam.proto.app.data import (
DataServiceStub,
Filter,
)
from viam.proto.app.datasync import (
UploadMetadata,
SensorData,
FileData
)
from viam.proto.app.datasync import DataSyncServiceStub
from viam import logging

LOGGER = logging.getLogger(__name__)


class DataClient:
"""gRPC client for uploading and retreiving data from app

Constructor is used by AppClient to instantiate relevant service stubs. Calls to DataClient methods should be made through AppClient.
"""

def __init__(self, channel: Channel, metadata: str):
"""
Create a data client that establishes a connection to app.

Args:
channel (Channel): an already-established connection to app.
metadata (str): the required authorization token to send requests to app.
"""
self._metadata = metadata
self._data_client = DataServiceStub(channel)
self._data_sync_client = DataSyncServiceStub(channel)

_data_client: DataServiceStub
_data_sync_client: DataSyncServiceStub
_metadata: str

async def tabular_data_by_filter(
self,
filter: Optional[Filter],
dest: Optional[str]
) -> List[Mapping[str, Any]]:
raise NotImplementedError()

async def binary_data_by_filter(
self,
data_request: Optional[Filter],
dest: Optional[str]
) -> List[bytes]:
raise NotImplementedError()

async def binary_data_by_ids(self, file_ids: Optional[List[str]]) -> List[bytes]:
raise NotImplementedError()

async def delete_tabular_data_by_filter(self, filter: Optional[Filter]) -> None:
raise NotImplementedError()

async def delete_binary_data_by_filter(self, filter: Optional[Filter]) -> None:
raise NotImplementedError()

async def delete_binary_data_by_ids(self, file_ids: Optional[List[str]]) -> None:
raise NotImplementedError()

async def add_tags_to_binary_data_by_file_ids(self, file_ids: Optional[List[str]], tags: Optional[List[str]]) -> None:
raise NotImplementedError()

async def add_tags_to_binary_data_by_filter(self, filter: Optional[Filter], tags: Optional[List[str]]) -> None:
raise NotImplementedError()

async def remove_tags_from_binary_data_by_file_ids(self, file_ids: Optional[List[str]], tags: Optional[List[str]]) -> None:
raise NotImplementedError()

async def remove_tags_from_binary_data_by_filter(self, filter: Optional[Filter], tags: Optional[List[str]]) -> None:
raise NotImplementedError()

async def tags_by_filter(self, filter: Optional[Filter]) -> List[str]:
raise NotImplementedError()

# to be defined and implemented last
async def add_bounding_box_to_image_by_id(self):
raise NotImplementedError()

# to be defined and implemented last
async def remove_bounding_box_from_image_by_id(self):
raise NotImplementedError()

async def bounding_box_labels_by_filter(self, filter: Optional[Filter]) -> List[str]:
raise NotImplementedError()

# TODO (RSDK-3637): confirm arguments
async def data_capture_upload(self, metadata: Optional[UploadMetadata], sensor_contents: Optional[List[SensorData]]) -> None:
raise NotImplementedError()

# TODO (RSDK-3637): confirm arguments
async def file_upload(self, metadata: Optional[UploadMetadata], file_contents: Optional[FileData]) -> None:
raise NotImplementedError()
4 changes: 4 additions & 0 deletions src/viam/rpc/dial.py
Original file line number Diff line number Diff line change
Expand Up @@ -306,3 +306,7 @@ async def _dial_direct(address: str, options: Optional[DialOptions] = None) -> C
async def dial_direct(address: str, options: Optional[DialOptions] = None) -> Channel:
warnings.warn("dial_direct is deprecated. Use rpc.dial.dial instead.", DeprecationWarning, stacklevel=2)
return await _dial_direct(address, options)


async def _dial_app(options: DialOptions) -> Channel:
return await _dial_direct("app.viam.com:443")