"""
Devices represent cloud-registered Webex RoomOS devices. Devices may be associated with Workspaces.
Searching and viewing details for your devices requires an auth token with the spark:devices_read scope. Updating or
deleting your devices requires an auth token with the spark:devices_write scope. Viewing the list of all devices in
an organization requires an administrator auth token with the spark-admin:devices_read scope. Adding, updating,
or deleting all devices in an organization requires an administrator auth token with the spark-admin:devices_write
scope. Generating an activation code requires an auth token with the identity:placeonetimepassword_create scope.
"""
from collections.abc import Generator
from dataclasses import dataclass
from datetime import datetime
from typing import Optional, Any, List
from pydantic import Field, model_validator, field_validator
from ..api_child import ApiChild
from ..base import SafeEnum as Enum, enum_str
from ..base import to_camel, ApiModel
from ..common import DevicePlatform
from ..rest import RestSession
from ..telephony import DeviceManagedBy
from ..telephony.jobs import DeviceSettingsJobsApi
__all__ = ['DevicesApi', 'Device', 'TagOp', 'ActivationCodeResponse', 'ProductType', 'ConnectionStatus']
[docs]
class ProductType(str, Enum):
phone = 'phone'
roomdesk = 'roomdesk'
[docs]
class ConnectionStatus(str, Enum):
connected = 'connected'
disconnected = 'disconnected'
connected_with_issues = 'connected_with_issues'
offline_expired = 'offline_expired'
activating = 'activating'
unknown = 'unknown'
[docs]
class Device(ApiModel):
#: A unique identifier for the device.
device_id: str = Field(alias='id')
#: A friendly name for the device
display_name: str
#: The workspace associated with the device.
workspace_id: Optional[str] = None
#: The person associated with the device.
person_id: Optional[str] = None
#: The organization associated with the device
org_id: str
#: The capabilities of the device.
capabilities: list[str]
#: The permissions the user has for this device. For example, xapi means this user is entitled to using the xapi
#: against this device.
permissions: list[str]
#: The connection status of the device.
connection_status: ConnectionStatus
#: The product name. A display friendly version of the device's model.
product: str
#: The product type.
product_type: ProductType = Field(alias='type')
#: Tags assigned to the device.
tags: list[str]
#: The current IP address of the device.
ip: Optional[str] = None
#: The current network connectivty for the device.
active_interface: Optional[str] = None
#: The unique address for the network adapter.
mac: Optional[str] = None
#: The primary SIP address to dial this device.
primary_sip_url: Optional[str] = None
#: All SIP addresses to dial this device.
sip_urls: list[Any]
error_codes: Optional[list[Any]] = None
#: Serial number for the device.
serial: Optional[str] = None
#: The operating system name data and version tag.
software: Optional[str] = None
#: The upgrade channel the device is assigned to.
upgrade_channel: Optional[str] = None
#: The date and time that the device was registered, in ISO8601 format.
created: Optional[datetime] = None
#: The location associated with the device.
location_id: Optional[str] = None
#: The workspace location associated with the device.
workspace_location_id: Optional[str] = None
#: The date and time that the device was first seen, in ISO8601 format.
first_seen: Optional[datetime] = None
#: The date and time that the device was last seen, in ISO8601 format.
last_seen: Optional[datetime] = None
#: Entity managing the device configuration.
managed_by: Optional[DeviceManagedBy] = None
#: Manufacturer of the device
#: only for 3rd party devices
manufacturer: Optional[str] = None
#: The Line/Port identifies a device endpoint in standalone mode or a SIP URI public identity in IMS mode
#: only for 3rd party devices
line_port: Optional[str] = None
#: Contains the body of the HTTP response received following the request to the Console API
#: Not set if the response has no body
#: only for 3rd party devices
outbound_proxy: Optional[str] = None
#: SIP authentication user ame for the owner of the device
#: only for 3rd party devices
sip_user_name: Optional[str] = None
#: The device platform.
device_platform: Optional[DevicePlatform] = None
@model_validator(mode='before')
def pop_place_id(cls, values):
"""
:meta private:
"""
values.pop('placeId', None)
return values
@field_validator('mac')
def mac_no_colon(cls, v: str) -> str:
"""
:meta private:
"""
return v.replace(':', '')
[docs]
class TagOp(str, Enum):
add = 'add'
remove = 'remove'
replace = 'replace'
[docs]
class ActivationCodeResponse(ApiModel):
#: The activation code.
code: str
#: The date and time the activation code expires.
expiry_time: datetime
[docs]
@dataclass(init=False)
class DevicesApi(ApiChild, base='devices'):
"""
Devices represent cloud-registered Webex RoomOS devices or IP Phones. Devices may be associated with Workspaces
or People.
The following scopes are required for performing the specified actions:
Searching and viewing details for devices requires an auth token with the spark:devices_read scope.
Updating or deleting your devices requires an auth token with the spark:devices_write scope.
Viewing the list of all devices in an organization requires an administrator auth token with
the spark-admin:devices_read scope.
Adding, updating, or deleting all devices in an organization requires an administrator auth token with
the spark-admin:devices_write scope.
Generating an activation code requires an auth token with the identity:placeonetimepassword_create scope.
"""
#: device jobs Api
settings_jobs: DeviceSettingsJobsApi
def __init__(self, *, session: RestSession):
super().__init__(session=session)
self.settings_jobs = DeviceSettingsJobsApi(session=session)
[docs]
def list(self, person_id: str = None, workspace_id: str = None, location_id: str = None,
workspace_location_id: str = None, display_name: str = None, product: str = None,
product_type: ProductType = None, tag: str = None, connection_status: ConnectionStatus = None,
serial: str = None, software: str = None, upgrade_channel: str = None, error_code: str = None,
capability: str = None, permission: str = None, mac: str = None, device_platform: DevicePlatform = None,
org_id: str = None, **params) -> Generator[Device, None, None]:
"""
List Devices
Lists all active Webex devices associated with the authenticated user, such as devices activated in personal
mode. Administrators can list all devices within an organization.
:param person_id: List devices by person ID.
:type person_id: str
:param workspace_id: List devices by workspace ID.
:type workspace_id: str
:param location_id: List devices by location ID.
:type location_id: str
:param workspace_location_id: List devices by workspace location ID. Deprecated, prefer `location_id`.
:type workspace_location_id: str
:param display_name: List devices with this display name.
:type display_name: str
:param product: List devices with this product name.
:type product: str
:param product_type: List devices with this type. Possible values: roomdesk, phone, accessory, webexgo, unknown
:type product_type: str
:param tag: List devices which have a tag. Searching for multiple tags (logical AND) can be done by comma
:type tag: str
separating the tag values or adding several tag parameters.
:param connection_status: List devices with this connection statu
:type connection_status: str
:param serial: List devices with this serial number.
:type serial: str
:param software: List devices with this software version.
:type software: str
:param upgrade_channel: List devices with this upgrade channel.
:type upgrade_channel: str
:param error_code: List devices with this error code.
:type error_code: str
:param capability: List devices with this capability. For example: xapi
:type capability: str
:param permission: List devices with this permission.
:type permission: str
:param mac: List devices with this MAC address.
:type mac: str
:param device_platform: List devices with this device platform.
:type device_platform: DevicePlatform
:param org_id: List devices in this organization. Only admin users of another organization (such as partners)
may use this parameter.
:type org_id: str
:return: Generator yielding :class:`Device` instances
"""
params.update((to_camel(p), enum_str(v))
for p, v in locals().items()
if p not in {'self', 'params'} and v is not None)
pt = params.pop('productType', None)
if pt is not None:
params['type'] = pt
url = self.ep()
return self.session.follow_pagination(url=url, model=Device, params=params, item_key='items')
[docs]
def details(self, device_id: str, org_id: str = None) -> Device:
"""
Get Device Details
Shows details for a device, by ID.
Specify the device ID in the deviceId parameter in the URI.
:param device_id: A unique identifier for the device.
:type device_id: str
:param org_id:
:type org_id: str
:return: Device details
:rtype: Device
"""
url = self.ep(device_id)
params = org_id and {'orgId': org_id} or None
data = self.get(url=url, params=params)
return Device.model_validate(data)
[docs]
def delete(self, device_id: str, org_id: str = None):
"""
Delete a Device
Deletes a device, by ID.
Specify the device ID in the deviceId parameter in the URI.
:param device_id: A unique identifier for the device.
:type device_id: str
:param org_id:
:type org_id: str
"""
url = self.ep(device_id)
params = org_id and {'orgId': org_id} or None
super().delete(url=url, params=params)
[docs]
def activation_code(self, workspace_id: str = None, person_id: str = None, model: str = None,
org_id: str = None) -> ActivationCodeResponse:
"""
Create a Device Activation Code
Generate an activation code for a device in a specific workspace by `workspaceId` or for a person by
`personId`. This requires an auth token with the `identity:placeonetimepassword_create` and
`spark-admin:devices_write` scopes.
* Adding a device to a workspace with calling type `none` or `thirdPartySipCalling` will reset the workspace
calling type to `freeCalling`.
* Either `workspaceId` or `personId` should be provided. If both are supplied, the request will be invalid.
* If no `model` is supplied, the `code` returned will only be accepted on RoomOS devices.
* If your device is a phone, you must provide the `model` as a field. You can get the `model` from the
`supported devices
<https://developer.webex.com/docs/api/v1/device-call-settings/read-the-list-of-supported-devices>`_ API.
:param workspace_id: The ID of the workspace where the device will be activated.
:type workspace_id: str
:param person_id: The ID of the person who will own the device once activated.
:type person_id: str
:param model: The model of the device being created.
:type model: str
:param org_id: The organization associated with the activation code generated.
:type org_id: str
:rtype: ActivationCodeResponse
"""
params = org_id and {'orgId': org_id} or None
body = {}
if workspace_id is not None:
body['workspaceId'] = workspace_id
if person_id is not None:
body['personId'] = person_id
if model is not None:
body['model'] = model
url = self.ep('activationCode')
data = self.post(url=url, json=body, params=params)
return ActivationCodeResponse.model_validate(data)
[docs]
def create_by_mac_address(self, mac: str, workspace_id: str = None, person_id: str = None,
model: str = None, password: str = None, org_id: str = None) -> Device:
"""
Create a phone by it's MAC address in a specific workspace or for a person.
Specify the mac, model and either workspaceId or personId.
:param mac: The MAC address of the device being created.
:type mac: str
:param workspace_id: The ID of the workspace where the device will be activated.
:type workspace_id: str
:param person_id: The ID of the person who will own the device once activated.
:type person_id: str
:param model: The model of the device being created.
:type model: str
:param password: SIP password to be configured for the phone, only required with third party devices.
:type password: str
:param org_id: The organization associated with the device.
:type org_id: str
:return: created device information
:rtype: Device
"""
params = org_id and {'orgId': org_id} or None
body = {'mac': mac}
if workspace_id is not None:
body['workspaceId'] = workspace_id
if person_id is not None:
body['personId'] = person_id
if model is not None:
body['model'] = model
if password is not None:
body.password = password
url = self.ep()
data = super().post(url=url, json=body, params=params)
return Device.model_validate(data)