Source code for terminusgps.wialon.items.unit

from urllib.parse import quote_plus, urljoin

from django.conf import settings

from terminusgps.wialon import flags
from terminusgps.wialon.items.base import WialonBase


[docs] class WialonUnit(WialonBase): def __init__(self, *args, **kwargs) -> None: super().__init__(*args, **kwargs) self._imei_number = None self._active = None self._image_uri = None
[docs] def create( self, creator_id: str | int, name: str, hw_type_id: str | int ) -> int | None: """ Creates a new Wialon unit. :param creator_id: A Wialon user id. :type creator_id: :py:obj:`str` | :py:obj:`int` :param name: A name for the unit. :type name: :py:obj:`str` :param hw_type_id: A Wialon hardware type ID. :type hw_type_id: :py:obj:`str` | :py:obj:`int` :raises ValueError: If ``creator_id`` is a :py:obj:`str` but not a digit. :raises ValueError: If ``hw_type_id`` is a :py:obj:`str` but not a digit. :returns: An id for the new unit. :rtype: :py:obj:`int` | :py:obj:`None` """ if isinstance(creator_id, str) and not creator_id.isdigit(): raise ValueError(f"'creator_id' must be a digit, got '{creator_id}'.") if isinstance(hw_type_id, str) and not hw_type_id.isdigit(): raise ValueError(f"'hw_type_id' must be a digit, got '{hw_type_id}'.") response = self.session.wialon_api.core_create_unit( **{ "creatorId": str(creator_id), "name": str(name), "hwTypeId": str(hw_type_id), "dataFlags": str(flags.DataFlag.UNIT_BASE), } ) return ( int(response.get("item", {}).get("id")) if response and response.get("item") else None )
[docs] def populate(self) -> None: super().populate() response = self.session.wialon_api.core_search_item( **{ "id": self.id, "flags": ( flags.DataFlag.UNIT_ADVANCED_PROPERTIES | flags.DataFlag.UNIT_IMAGE | flags.DataFlag.UNIT_ADMIN_FIELDS ).value, } ) if response is not None: item = response.get("item", {}) self._imei_number = item.get("uid") self._active = item.get("act", False) self._image_uri = item.get("uri")
def get_position(self) -> dict | None: return self.session.wialon_api.core_search_item( **{"id": self.id, "flags": flags.DataFlag.UNIT_POSITION} ) @property def position(self) -> dict | None: """Current GPS position of the unit.""" return self.get_position() @property def exists(self) -> bool: """Whether or not the unit exists in Wialon.""" return bool( self.session.wialon_api.core_search_item( **{"id": self.id, "flags": flags.DataFlag.UNIT_BASE.value} ).get("item", False) ) @property def available_commands(self) -> dict: """ Commands assigned to the unit. :type: :py:obj:`dict` """ return self.session.wialon_api.core_get_hw_cmds( **{"deviceTypeId": 0, "unitId": self.id} ) @property def image_uri(self) -> str: """ Image URI for the unit. :type :py:obj:`str` """ if self._image_uri is None: self.populate() return str(self._image_uri) @property def imei_number(self) -> str: """ IMEI # for the unit. :type: :py:obj:`str` """ if self._imei_number is None: self.populate() return str(self._imei_number) @property def iccid(self) -> str | None: """ SIM Card # for the unit, if any. :type: :py:obj:`str` | :py:obj:`None` """ return self.afields.get("iccid") @property def carrier(self) -> str | None: """ Name of the telecommunications company associated with the unit's SIM card, if any. :type: :py:obj:`str` | :py:obj:`None` """ return self.afields.get("carrier") @property def active(self) -> bool: """Whether or not the unit is activated.""" if self._active is None: self.populate() return bool(self._active) @property def image_url(self) -> str | None: """Returns an absolute url to the unit's icon in Wialon.""" if settings.configured and hasattr(settings, "WIALON_HOST"): return urljoin(settings.WIALON_HOST, self._image_uri) return urljoin("https://hst-api.wialon.com", self._image_uri)
[docs] def execute_command( self, name: str, link_type: str, timeout: int = 5, flags: int = 0, param: dict | None = None, ) -> None: """ Executes a command on the unit. :param name: A Wialon command name. :type name: :py:obj:`str` :param link_type: A protocol to use for the Wialon command. :type link_type: :py:obj:`str` :param timeout: How long (in seconds) to wait before timing out command execution. Default is ``5``. :type timeout: :py:obj:`int` :param flags: Flags to pass to the Wialon command execution. :type flags: :py:obj:`int` :param param: Additional parameters to execute the command with. :type param: :py:obj:`dict` | :py:obj:`None` :returns: Nothing. :rtype: :py:obj:`None` """ self.session.wialon_api.unit_exec_cmd( **{ "itemId": self.id, "commandName": name, "linkType": link_type, "timeout": timeout, "flags": flags, "param": param if param else {}, } )
[docs] def set_access_password(self, password: str) -> None: """ Sets a new access password for the unit. :param password: A new access password. :type name: :py:obj:`str` :raises WialonError: If something goes wrong with Wialon. :returns: Nothing. :rtype: :py:obj:`None` """ self.session.wialon_api.unit_update_access_password( **{"itemId": self.id, "accessPassword": password} )
[docs] def activate(self) -> None: """ Activates the unit. :raises WialonError: If something goes wrong with Wialon. :returns: Nothing. :rtype: :py:obj:`None` """ self.session.wialon_api.unit_set_active( **{"itemId": self.id, "active": int(True)} )
[docs] def deactivate(self) -> None: """ Deactivates the unit. :raises WialonError: If something goes wrong with Wialon. :returns: Nothing. :rtype: :py:obj:`None` """ self.session.wialon_api.unit_set_active( **{"itemId": self.id, "active": int(False)} )
[docs] def assign_phone(self, phone: str) -> None: """ Assigns a phone number to the unit. :param phone: A phone number beginning with a country code. :type phone: :py:obj:`str` :raises WialonError: If something goes wrong with Wialon. :returns: Nothing. :rtype: :py:obj:`None` """ self.session.wialon_api.unit_update_phone( **{"itemId": self.id, "phoneNumber": quote_plus(phone)} )
[docs] def get_phone_numbers( self, cfield_key: str = "to_number", afield_key: str = "to_number" ) -> list[str]: """ Retrieves all phone numbers assigned to the unit. This includes any attached drivers, custom/admin fields or otherwise assigned phone numbers. :param cfield_key: A custom field key used to retrieve phone numbers. Default is :py:obj:`"to_number"`. :type cfield_key: :py:obj:`str` :param afield_key: An admin field key used to retrieve phone numbers. Default is :py:obj:`"to_number"`. :type afield_key: :py:obj:`str` :raises WialonError: If something goes wrong with Wialon. :returns: A list of phone numbers. :rtype: :py:obj:`list` """ phones_0: list[str] = self._get_driver_phone_numbers() phones_1: list[str] = self._get_cfield_phone_numbers(key=cfield_key) phones_2: list[str] = self._get_afield_phone_numbers(key=afield_key) return list(frozenset(phones_0 + phones_1 + phones_2))
[docs] def clean_phone_numbers(self, phones: list[str]) -> list[str]: """Takes a list of phone numbers and returns a list of clean phone numbers.""" return [ clean_num for num in phones for clean_num in (num.split(",") if "," in num else [num]) ]
def _get_afield_phone_numbers(self, key: str) -> list[str]: """ Retrives phone numbers saved in an admin field by key. :param key: An admin field key. :type key: :py:obj:`str` :raises WialonError: If something goes wrong with Wialon. :returns: A list of phone numbers. :rtype: :py:obj:`list` """ if key not in self.afields.keys(): return [] return self.clean_phone_numbers([self.afields[key]]) def _get_cfield_phone_numbers(self, key: str) -> list[str]: """ Retrives phone numbers saved in a custom field by key. :param key: A custom field key. :type key: :py:obj:`str` :raises WialonError: If something goes wrong with Wialon. :returns: A list of phone numbers. :rtype: :py:obj:`list` """ if key not in self.cfields.keys(): return [] return self.clean_phone_numbers([self.cfields[key]]) def _get_driver_phone_numbers(self) -> list[str]: """ Returns a list of phone numbers assigned to drivers attached to the unit. :raises WialonError: If something goes wrong with Wialon. :returns: A list of phone numbers. :rtype: :py:obj:`list` """ response = self.session.wialon_api.resource_get_unit_drivers( **{"unitId": self.id} ) if response: dirty_phones = [driver[0].get("ph") for driver in response.values()] return self.clean_phone_numbers(dirty_phones) return []